BIND 10 trac598_new, updated. 4569c1b87f5d04f663e1c8e2813d090a78dd9e40 [trac598_new] Fix the conflicts when merging master.

BIND 10 source code commits bind10-changes at lists.isc.org
Wed May 11 02:52:49 UTC 2011


The branch, trac598_new has been updated
       via  4569c1b87f5d04f663e1c8e2813d090a78dd9e40 (commit)
       via  29d36377ec206cbe52274ee9a5a6e88ef27921d5 (commit)
       via  25b33e62902b5bb181405e2177d2fe935cfe6c75 (commit)
       via  a892818fb13a1839c82104523cb6cb359c970e88 (commit)
       via  df1ab797a9d1a2a188060c70071bb8fa7d6f1a01 (commit)
       via  b653f950b906ecf4194d2a2cd07fa92ae47dd546 (commit)
       via  ceef68cd1223ae14d8412adbe18af2812ade8c2d (commit)
       via  879d981650dff5ee577712aa45aa9b363b039a04 (commit)
       via  e595402348d7766d7e3f7fd8d9f32bd8b144f747 (commit)
       via  33cd7d9232078f70aa380309a3615a1a9d743988 (commit)
       via  fb26d933e7af0cc07fe686ef88ef95b28cd10d2b (commit)
       via  48d2369e3a7c0e55f5c94973ab0191ddfbaa02c1 (commit)
       via  afd75a89d7aeba622b53c5b37e3f76572ef68c3a (commit)
       via  b395258c708b49a5da8d0cffcb48d83294354ba3 (commit)
       via  569b2b6e5d84277316bce84c0e118ffd116ffe5e (commit)
       via  e5687a75c06966ab68ad453093fb6c7b9d8fe761 (commit)
       via  119678f768f09b13d6ecb715ad731d1dca8f05b0 (commit)
       via  4903410e45670b30d7283f5d69dc28c2069237d6 (commit)
       via  27a4c936d87d31952f6a8377e04cae1fb90edffd (commit)
       via  9eb7b41d5253c44e59987170a74e345b651c96bc (commit)
       via  7efc144e0eacc123544507d635630b7949052993 (commit)
       via  4ff5a9f61d9ad1c96468556771562f1dbad7ec98 (commit)
       via  c16b3ab523860ccca5e8e9648b58801c3eefae29 (commit)
       via  8bfccfb1fead0448e959126e07dad1a800880575 (commit)
       via  9a8870c515be763e8be63cdc28231883601867d4 (commit)
       via  fb1d629419b6c58b9c9f410e6c027c8769e0c9a3 (commit)
       via  0709f8b56df68cfe0c79ed98bfe7e9dd25ce0e1e (commit)
       via  40e06e655ce78197f0b52d8c5dc9c7516795362f (commit)
       via  b5646b50e23e6049f233f755d7e143a09d4fb19c (commit)
       via  d4d910b28b3226d1330b7da1df170c406771b939 (commit)
       via  7bb5dc265a830d8993c9cb1da55194631e657587 (commit)
       via  1e3c154cd21cede83a8bbd7a559c20752b58ce24 (commit)
       via  434719dc9b7eeee0d0901fa6f5e1847bc40691c2 (commit)
       via  0ecb807011196eac01f281d40bc7c9d44565b364 (commit)
       via  fa321eca22c746101dd9cf67c7bc9da6de30483a (commit)
       via  ee2664ecf4fda60a78e97d39c4f69b4f22d5aa24 (commit)
       via  fb283c1a0e6f8cdacc9c326f00caef141b058f1f (commit)
       via  4c178871eba133fbbf56c2dac1dde1a28ad20477 (commit)
       via  ffa2f0672084c1f16e5784cdcdd55822f119feaa (commit)
       via  7c40e60eeaad7f2c1ea79f92e866dee08eafd5ab (commit)
       via  fcc1b5e13946c5e58e2bd0bf287f551e161f0544 (commit)
       via  b6d140b6169c130b06896d2b40df58752991a47d (commit)
       via  eab5008d28b04fdd7c0f4c93051fd3b1c1a416f7 (commit)
       via  313464eed2b54281b8b2357002cd7dfb9231ddf6 (commit)
       via  121d3e844ad6d8ed8aa21dd48c53095e2f770117 (commit)
       via  c3dad479414b01979693ba71c832aedd681f5044 (commit)
       via  a23491a635d7f74132fc0b91eac832275f8f1f87 (commit)
       via  9a2ca8e5de8a23018ebb0ac7fee819c065542ff1 (commit)
       via  284c8b457d8a8940265da1e4d0c7b1050806afbb (commit)
       via  7c54055c0e47c7a0e36fcfab4b47ff180c0ca8c8 (commit)
       via  5c497dfce7d23487c2aefe9907f942c39c4c5846 (commit)
       via  83717978e3941e4eb5d7dc90d26a88256efd3175 (commit)
       via  df0c3599c1f3ad957df20eb8cc04c33d1c958e4a (commit)
       via  40870d717a8017379cdb68db9ed15ca71faddd5f (commit)
       via  d846851699d5c76937533adf9ff9d948dfd593ca (commit)
       via  372a2f033edf044d3f515f3b5009d0c8fce3ce16 (commit)
       via  89fcb0f002447e2cc3148e212f1ecd4f6d1bd821 (commit)
       via  a437d4e26b81bb07181ff35a625c540703eee845 (commit)
       via  0338dd8c3ef74395235bc37533269fb252142263 (commit)
       via  28c50de2e9ef07250b54a3d99850ee353f511ffe (commit)
       via  297955d6928e3202c25d0f1fa17708c032c46a40 (commit)
       via  2979d921553eaaf59cfbe6b78bd726e09006ca9e (commit)
       via  db0ca2fbc64b390f261b5e36938c736321b171f9 (commit)
       via  7f0a7a5ff8d2452c4b48575a725f97e5981aff66 (commit)
       via  2aca19e705f02400a6b213ef84fa81c86dff0375 (commit)
       via  cf46f370333b15487f6c02f85749d90c2e0bd710 (commit)
       via  4fff42d6c9ae24effcae3f6eaa73a8a4eda5a38f (commit)
       via  25bc145bb597683411ece6ad7cb72fc0fabedeae (commit)
       via  4a2c0e7a8852496e9b8f9a56f5058cb1f55d3f55 (commit)
       via  25301e86fb8aa4cb8d98933a0c3b7dcf46f8c4be (commit)
       via  50ebc839b1c8389eb1b7b70f02758a9034138552 (commit)
       via  bb568b0fbb855dcf79681de5024c09b91251ccda (commit)
       via  f1dfe74d6b9b2b8c4dc85dd39a43084dc2b73aa9 (commit)
       via  6daf339b7a83843a12d4938424063d1b96929924 (commit)
       via  3ce5e0a2b96c84ae003ea372bb84ebb19ca355e8 (commit)
       via  9e8b5ec4233217fba5c7e9b17afd6c01e4fc7b79 (commit)
       via  cca71e70d0667d066ba5ab63c65b21d83cbb896c (commit)
       via  2d514a764119f29d3e2fbb04366d880df1866928 (commit)
       via  e22700fc2021180a0dab3f312df5fdabe9bc47e2 (commit)
       via  98d147ea68fc1e62b6e7e3bc74c80e9457b5249f (commit)
       via  ac7ff7f2226bdba60809b70caa82659b77c6e2e6 (commit)
       via  677cebce1708ba85e46a0712d939176dc7ab7a94 (commit)
       via  f0fe344b15c3e1be2604201000e6c9fbe6a910bc (commit)
       via  5a4d69114ef60bbb86c4fc2190b78761ac4ccc3f (commit)
       via  776f5ebd79615b0c05f2009c09bf61c44c59343a (commit)
       via  314e299226288d66efe5e65d8e00fc041b688f35 (commit)
       via  0e3b55edc75e91ea11df51ecffae0ae4ff07fdac (commit)
       via  0261bbec3a5cd8770aee567aaebab2a4f93c2303 (commit)
       via  e997ff18a6bf1eeb23391e0957db0defdecd0213 (commit)
       via  9e183cb0529aeb9f0674b5727affa223d8fc9db5 (commit)
       via  31a6f34026c83594bd9f205df18eb290114d9ea1 (commit)
       via  e34dd62b8eca7abfbfd4851140d663efc43041f1 (commit)
       via  8320ec6eb230fe761ae4769367f10383e967655c (commit)
       via  d033a50a7e32664848c360b160e9170cdcd79886 (commit)
       via  c8b7abc5751b171621be9edd5156dd2691ff60d1 (commit)
       via  b8422db8e0120d3998b15581dddcbfe4efe91a68 (commit)
       via  da16cc776443e1414f779d7402996c6949934765 (commit)
       via  d6db622c5649e745fb3c64218e36c41545c47aed (commit)
       via  cce60befee1e0c25e20449b9242112cc0a777089 (commit)
       via  89dd4548179485bdf76a84d289ab88ba65bd07bc (commit)
       via  364be72653933235d362a57c9342bae1c6e17b3a (commit)
       via  43f9ce0c56cd14c0349a8f3c3c9a5f4dc092f65a (commit)
       via  ebe0c4b1e66d359227bdd1bd47395fee7b957f14 (commit)
       via  d9b00f6ded6d0cfb41a0939cb613c1e7bd703a67 (commit)
       via  2c60d79949a79fc8f093f3447c949e7c63f83137 (commit)
       via  0ede9e8f8c0e1d89a01cdb1eccb5256363bda0cf (commit)
       via  64cee1a7ad8341b83954e022487744060b59d04a (commit)
       via  177b356c926307e94a95e6e2de7a3f0ee7124021 (commit)
       via  1867180c5e2263baf319514b5b765b8eb4049c08 (commit)
       via  6c554c8b4e37daeaa4182d05af69a40a0b78cea2 (commit)
       via  6eb7a93e81027bcf67435188c1ff7788965253cb (commit)
       via  cacab413e886e8c90691428e1e3f78b77814945e (commit)
       via  04f7331a44e0bfd48f52d06f6fd463c6652dd38f (commit)
       via  5b4feea19e2cc1bdf18ce52cf0062828ad9067c7 (commit)
       via  ec1ad752576f7f3541b1b57f906256c6a5ae0dc6 (commit)
       via  1ce2874170c85de79a896b1cc3077d9f3032d9e0 (commit)
       via  b92cca798d702273d63d56d9197782edeb927c8c (commit)
       via  abdf624576745fa0a4f37319e3c7dbd76047e2d2 (commit)
       via  28143beb0e57bbd4d62432b81edc8e179b95959f (commit)
       via  76705c8fc54809ece24609deda2d156a844d2bf5 (commit)
       via  a42b39784b65894e7dc164f1b7f2f887715f0c45 (commit)
       via  0310b8b77e6adb8671d1f9ebfe826e394e95f53f (commit)
       via  29170e28d19f35a874d84b88f7c0873c51e28f89 (commit)
       via  53d9f46923a22920c04d5bc4fc706ec202686b1b (commit)
       via  2842dda9275c1a471d70d3a571d810c8d715bf3a (commit)
       via  78bd2b77782510d02748254a8c79249e493b6024 (commit)
       via  daf48e860413d4c3229ce309253b29d1ad974c7a (commit)
       via  daa24430a497d145849a687f51252bfed16a2caf (commit)
       via  6d03a35ac6dec0508d30cd778fed48257fc6c0e1 (commit)
       via  87e4b9874ac16ccc5d236a2fcb8221942713e086 (commit)
       via  d9433ad4bd9aec1028b9b05aa55e9b083e35a4d4 (commit)
       via  9df42279a47eb617f586144dce8cce680598558a (commit)
       via  0640f80c7a62cf9c3e289f8290c5a3b44f4385f5 (commit)
       via  05c6223cf7f145ec6e96cffed0561a03387b7367 (commit)
       via  cc788af2c45043fbb98365d5fb85c1d16307dda2 (commit)
       via  fd45c40964a9557c0a6534c6d0cbe5c377d05066 (commit)
       via  475e26bae3b3c4c8823c4931638d0a7af0ac66cd (commit)
       via  f4ad75548592b2f3eeae22de5685cacbf5c82bae (commit)
       via  dabf205231ff9e720d8693800e311a89ace18488 (commit)
       via  ed5025a1322aec3c6aa2855ec807bdcb8e013f1d (commit)
       via  e4034daa010c24286b969cd9ad6d75c30895cd52 (commit)
       via  4903de33e8f5d16ed99b6ad6b22fac023e653f71 (commit)
       via  2bb4420b73b5485cbd05a221a414a40f9e7674b0 (commit)
       via  0660b35c79dce9ff27361fee48da8c174bf05cd5 (commit)
       via  3e37899f95fe561fee0a73fb5d85071065ef3c7d (commit)
       via  088bb8cbca563a17b97166bcbb799fd50bbbca4f (commit)
       via  f099c11348b7947c64f7467677e9afa58ca7023c (commit)
       via  ad134794bd3fdbb058fe5d50d8e92c71d03d47cc (commit)
       via  309bc10ee624106cf75165efd4251312deed3212 (commit)
       via  5cd716bd9844e154e6ca58a981787614a3a6fe6c (commit)
       via  adfd1014c34da20e272f058c9cce43130c637071 (commit)
       via  65874313065ddb02756d5ef06c8802c7540c17c7 (commit)
       via  98eab34d80219120219d064f6b3b9f0afce3e59a (commit)
       via  00e36b253bd643b007f89a8ccb3addac1a723eba (commit)
       via  7be4a7e7f859881a3e5a3f4268dbdbc3468b7214 (commit)
       via  abdb0ff5e8cdd781d7c4960bb51d8538f4e3b44e (commit)
       via  d4ab440d337cb9ef3f1301c3b655ed0a913cf257 (commit)
       via  33eb030ea0a6f980573c9a7ffff41c99535df98e (commit)
       via  6c274fd95d3c2bcc99113108f5a68aa0364f924c (commit)
       via  241c11e7b06b233585b52df53a9273ab8e0ad405 (commit)
       via  3427f489904a83ed1adb8e740aaaf1f6ba80267e (commit)
       via  dfddb7ba4637530a542b833ee14083421eeba826 (commit)
       via  1cbd51919237a6e65983be46e4f5a63d1877b1d3 (commit)
       via  d743478f2b76e0f37381f64d5f4e90417260d67c (commit)
       via  bc436f1f6715aabcc62c468fa6cfd7d3bf694f29 (commit)
       via  0194e3a376aa9c1ec2c232b0f2fd9a6cf02e448d (commit)
       via  74472396fc8f91daedcd6a286b34b5cae8a5ab57 (commit)
       via  e5cae846407b0f627ea67ba687132c141c4de57b (commit)
       via  5542432e850b29dcd316842a61fcbc2903acbaab (commit)
       via  b963854734ff8ba78ccb14f2e5a481c9426881c6 (commit)
       via  ea46adf9f6bbdd78a06ae748d979986a75b9b8d2 (commit)
       via  ffbe8a099bece23efb94e3adbe8fdfff8cfb379e (commit)
       via  3c194549a61e68ed38bbcd90e69f1f954ff286f4 (commit)
       via  5a6f9f8c21674d8f70fe33de2b7d7e23c105e888 (commit)
       via  5573b0bc953d1a9589d2e0f06b8da58dadb64bc3 (commit)
       via  b1cb4c4a1421bb512d093690c95d27425b33e1e5 (commit)
       via  521c140da800fdb7a7c87e53e01270e02ae4bce2 (commit)
       via  c32718be9f5409b6f72d98ddcd0b1ccd4c5c2293 (commit)
       via  2ec061bcb5fbdd5893377a233219af11a6309cf4 (commit)
       via  1096417815a2e2241aa059a24fada61108b2ca90 (commit)
       via  2463b96680bb3e9a76e50c38a4d7f1d38d810643 (commit)
       via  912b79387bbbe16f5a97513dce140d31917e091e (commit)
       via  a1703e5ae5fc9458c066fb4aab7666bf4e5fdb8a (commit)
       via  823fa0556364ad5bdcd26cb7a42999d502f3af02 (commit)
       via  e37bfa349bd0b7866a57519bf7f86dbb18c3a104 (commit)
       via  145a6173191e6cd39be3d495a6e5d0511dfe867a (commit)
       via  fb7877b06ba873d4fb222409dd92b4701ae11ffb (commit)
       via  21385dbdb72fe02275c859a88674a9d2166a0ed0 (commit)
       via  158af09a0032d47503a9e52102bc495b8d5bba46 (commit)
       via  e9f3843c953ce9a3e05c3dcc4b8df2a67a9d9e6d (commit)
       via  9f729b786ad2d12fde55cbaad5de72918fbe209e (commit)
       via  20336851f494ff1d9c8937400a99ed4d0203a340 (commit)
       via  246e56b3bb7792789b3aa891e21e580976d9e7be (commit)
       via  168bed01625dd25fc2c40bd6b402763849e840ec (commit)
       via  e831ffa2129fc5e013a0217f004896f6f40f258e (commit)
       via  4eda7bbc802b24730eb8ef9e5716fc47f19d5a00 (commit)
       via  fb4a0a36ba0d90409684e8042916341ce35c5f21 (commit)
       via  7b1677584cd0cc94825741792f9ed66f16029938 (commit)
       via  fe8babb0a2953fbe1755b79db136c0cae25682e2 (commit)
       via  9140fab9bab5f6502bd15d391fd51ac078b0b89b (commit)
       via  1241ddcffa16285d0a7bb01d6a8526e19fbb70cb (commit)
       via  fafa0c06f358f9cc32860535bef1c56d25f20775 (commit)
       via  bf1cf162e37ff391874569c82c6bef7e8b7e4f18 (commit)
       via  122d477847f80c7d77bec087a849b9e6743c17d3 (commit)
       via  e74f6d5e8f9abb081bde606bc46319488c7e546b (commit)
       via  f137e0fa3a387fcc13898ea6da6b61dcd80dc8ef (commit)
       via  457ef26144222d0eac25e93751ad8f0c8b12b8e5 (commit)
       via  572ac2cf62e18f7eb69d670b890e2a3443bfd6e7 (commit)
       via  8038f6efe5645a6100b9021b145f7b414efb6d86 (commit)
       via  cf456aa1546145ac403e75535e555d773b39ff20 (commit)
       via  006b2ea9dabd869bc05682b73b083ea815d520db (commit)
       via  c34d8eb763ceb840f65de77a22eb67c8b1ab6392 (commit)
       via  2aa47d167c58b6718706f8e037927b824ff0cf00 (commit)
       via  7ed21ab7e857037f18944e63fa5deac02ecf017a (commit)
       via  81c81d70342c7aacfb2689d86aa239e231c310cd (commit)
       via  9b16d3b4c04d35914b9eeba56a168d5039d7342b (commit)
       via  e16c86b6229017d8b79f8bbe342976ca2b938c3c (commit)
       via  604e90d1e0c928cc8d94146beea6e24fe2252eec (commit)
       via  dcf58b7836e854107438368905576de7d29e0e3b (commit)
       via  f4f11a9b1c09adb07e2d6b99a0bd342d5a75ea3f (commit)
       via  74e6966d7f8f8216dad871f1648cab977fb9fea2 (commit)
       via  0334c1798ea43061494a530d8bc274283f1f1fc7 (commit)
       via  dcd582cc0a7d02d69c3c7c28916980f71034f9b2 (commit)
       via  c6947d22cd80d5934ad53c91b74c640c8a64e57c (commit)
       via  40f4efbbd9f5685147cd1abf19d12c336bc1b8d9 (commit)
       via  a57662d6db020dd0b334472b5bb7ea88aefb6a7d (commit)
       via  122d9611bd552c3113eca8aa5e91d2b8a3018210 (commit)
       via  36b32903369f9a3afda93e2537d369d2402a3bfc (commit)
       via  bb5efb65cb0114b5bf985fd1588e8b645d4c45aa (commit)
       via  7ae7577211c77f31a9f30be122d245add72d893d (commit)
       via  0eea320309f86b8f1f95bed053078bdcf4c82071 (commit)
       via  8eb1d7a04312f7fa70ee3c986e66b6444a1dfde4 (commit)
       via  99c44efcd64b8262614354faaef2b5abb6fb644e (commit)
       via  af9f4f7fdaf88b906022bb808f44c6e586e702fc (commit)
       via  1ea4834d960f3d5f14ff8cee312448baab72e075 (commit)
       via  f1ac03b8147047bee020fbc019d4969f16c75064 (commit)
       via  231b29911894b0f5ddbd0d1444d9dfdf9cb5abb3 (commit)
       via  4e8ed21d6a2e80e81393e64d808bb07655f42cbf (commit)
       via  5012fabe00f1ebcbd2d67564df325fc69a529b5c (commit)
       via  160b06212023cfce40c1ff6f13c5307c4d4f6e50 (commit)
       via  8541053e6fffaf84127fddd2c0a25d0dcd5c635b (commit)
       via  5e89e6afd429bf91d66f2f70435342fa1de388a4 (commit)
       via  a37c25cdb88ceb49b518d27a324ad7523f936fb2 (commit)
       via  b1610a09098d7019c6701daf77c2b8b98eb03b75 (commit)
       via  04330565df2cc183a92f196772e03b05482046eb (commit)
       via  44f4b82933783502be198c0ab0a81020fb3fe510 (commit)
       via  3437b4fa8efb83ce5395ec159e85b38951e23504 (commit)
       via  4b65b6bdb511b88979d0b1c6f44161c223e1dc9d (commit)
       via  3f6620c5ba918a2a411aca9430fd8ac347e1aeca (commit)
       via  2018011dab54aaff10385ae4905c1a5706997062 (commit)
       via  b751b7e0cc08dca691029169909a54a0bd1e6b45 (commit)
       via  d7cf894e555a8aa8508f695fabac2061822d454d (commit)
       via  41361697fe474af2b511e922c18dc0b211f1344c (commit)
       via  0dc2e2582d63c42847400701a7c3c6b0fb2d6d9b (commit)
       via  4d55533790df1992aee5c088d4f91593d055c080 (commit)
       via  c374a5c5a329a307346be02d5b884ab57e1cb8c1 (commit)
       via  cd3ce64ac0ac3e82ba905f3eea77f1040b7e69b8 (commit)
       via  660d7d782c81bc55b8cc009836c35d9ca3948063 (commit)
       via  a9f80cc455747b38115c5279bafde024e78b5f30 (commit)
       via  24aa99548a4164d2c57adcf3829cc50f1fd34de5 (commit)
       via  f8a702716291db0b289aa211e5adac6fb2790cb7 (commit)
       via  390af5c81d043a9f4cc8e908365e7f0734bddb8f (commit)
       via  2df69541deceaa8a3bbbcc04d2087e94aa063d11 (commit)
       via  ed3c8e2f7a386b05b696d3ff79fa285ae7a050e9 (commit)
       via  1f16df990ddee676893ae701b8553fd42d6992a7 (commit)
       via  aa0ddfbb4f0aa61cfee383f5459c2183b353674b (commit)
       via  4f1d8d0f2ce99880306f7926a23b28f1aa8e4fd9 (commit)
       via  a7c4e0bc10a5430008d12081f4cb30d1d0d26723 (commit)
       via  3987357f56e0fc2feca75001b963a11f1b7120ff (commit)
       via  6cece2fc1d8a086b65421a583cf35b40f6ee1751 (commit)
       via  400d3b61a32c0fc47c5f41a93ea649fbde6a5445 (commit)
       via  fac1bf01a628b3b922af67cdd94f05257b6eef9a (commit)
       via  34ba5055b70c9de09d406b3e51ad2e02b98f6439 (commit)
       via  238dca82160452df0eb732ce014166777380767e (commit)
       via  253d063204f1e0656c89650999c76f942b4840f6 (commit)
       via  817462f1ea1f1e9b4e05b2da90b8d311a7b59843 (commit)
       via  30ab4cfbd7f0744653248efc5635c68930359eea (commit)
       via  97feb3a88bae42f4051cd67384a4dc7dcd018c9a (commit)
       via  b78eefc13bc53a301327674a10d88cb917d6f28d (commit)
       via  34d2f102aedbdb6b818f8eb8deb1e00fe431dae4 (commit)
       via  6eab8b3fc5922c7b9c6403f4510b929544eafe30 (commit)
       via  e29c4f167f9d466eb9310989e836a0be428e5ace (commit)
       via  992f3702aad9c83836af20d32e96313ff22cde3b (commit)
       via  150914707089969bde30fbc6276abc00f3211ba3 (commit)
       via  342926bcc0d317101321ff9afe6cf61967472a6a (commit)
       via  7a7299fb09d2a02023041d3fe7a92e22d17ab549 (commit)
      from  7f642b767c8274a6f3344e4a5e1141e9e7f38924 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 4569c1b87f5d04f663e1c8e2813d090a78dd9e40
Merge: 7f642b767c8274a6f3344e4a5e1141e9e7f38924 29d36377ec206cbe52274ee9a5a6e88ef27921d5
Author: zhanglikun <zhanglikun at cnnic.cn>
Date:   Wed May 11 10:47:47 2011 +0800

    [trac598_new] Fix the conflicts when merging master.

-----------------------------------------------------------------------

Summary of changes:
 ChangeLog                                          |  100 +-
 Makefile.am                                        |  450 ++--
 configure.ac                                       |  103 +-
 doc/Doxyfile                                       |   11 +-
 ext/asio/README                                    |    9 +-
 ext/asio/asio.hpp                                  |    2 +-
 ext/asio/asio/basic_datagram_socket.hpp            |   13 +-
 ext/asio/asio/basic_deadline_timer.hpp             |   13 +-
 ext/asio/asio/basic_io_object.hpp                  |    9 +-
 ext/asio/asio/basic_raw_socket.hpp                 |   15 +-
 ext/asio/asio/basic_serial_port.hpp                |   20 +-
 ext/asio/asio/basic_socket.hpp                     |   13 +-
 ext/asio/asio/basic_socket_acceptor.hpp            |    9 +-
 ext/asio/asio/basic_socket_iostream.hpp            |   17 +-
 ext/asio/asio/basic_socket_streambuf.hpp           |   19 +-
 ext/asio/asio/basic_stream_socket.hpp              |   13 +-
 ext/asio/asio/basic_streambuf.hpp                  |   38 +-
 ext/asio/asio/basic_streambuf_fwd.hpp              |   33 +
 ext/asio/asio/buffer.hpp                           |   22 +-
 ext/asio/asio/buffered_read_stream.hpp             |   15 +-
 ext/asio/asio/buffered_read_stream_fwd.hpp         |    6 +-
 ext/asio/asio/buffered_stream.hpp                  |   13 +-
 ext/asio/asio/buffered_stream_fwd.hpp              |    6 +-
 ext/asio/asio/buffered_write_stream.hpp            |   17 +-
 ext/asio/asio/buffered_write_stream_fwd.hpp        |    6 +-
 ext/asio/asio/buffers_iterator.hpp                 |   20 +-
 ext/asio/asio/completion_condition.hpp             |    8 +-
 ext/asio/asio/datagram_socket_service.hpp          |   12 +-
 ext/asio/asio/deadline_timer.hpp                   |   10 +-
 ext/asio/asio/deadline_timer_service.hpp           |   14 +-
 ext/asio/asio/detail/array_fwd.hpp                 |   25 +
 ext/asio/asio/detail/base_from_completion_cond.hpp |   17 +-
 ext/asio/asio/detail/bind_handler.hpp              |   31 +-
 ext/asio/asio/detail/buffer_resize_guard.hpp       |   12 +-
 ext/asio/asio/detail/buffer_sequence_adapter.hpp   |   20 +-
 ext/asio/asio/detail/buffered_stream_storage.hpp   |   14 +-
 ext/asio/asio/detail/call_stack.hpp                |   11 +-
 ext/asio/asio/detail/completion_handler.hpp        |   34 +-
 ext/asio/asio/detail/config.hpp                    |  205 ++
 ext/asio/asio/detail/consuming_buffers.hpp         |   20 +-
 ext/asio/asio/detail/deadline_timer_service.hpp    |   76 +-
 ext/asio/asio/detail/descriptor_ops.hpp            |  171 +-
 ext/asio/asio/detail/descriptor_read_op.hpp        |  114 +
 ext/asio/asio/detail/descriptor_write_op.hpp       |  114 +
 ext/asio/asio/detail/dev_poll_reactor.hpp          |  366 +---
 ext/asio/asio/detail/dev_poll_reactor_fwd.hpp      |   19 +-
 ext/asio/asio/detail/epoll_reactor.hpp             |  426 +---
 ext/asio/asio/detail/epoll_reactor_fwd.hpp         |   26 +-
 ext/asio/asio/detail/event.hpp                     |   14 +-
 .../asio/detail/eventfd_select_interrupter.hpp     |  120 +-
 ext/asio/asio/detail/fd_set_adapter.hpp            |   15 +-
 ext/asio/asio/detail/fenced_block.hpp              |   34 +-
 ext/asio/asio/detail/gcc_arm_fenced_block.hpp      |   76 +
 ext/asio/asio/detail/gcc_hppa_fenced_block.hpp     |   58 +
 ext/asio/asio/detail/gcc_sync_fenced_block.hpp     |   61 +
 ext/asio/asio/detail/gcc_x86_fenced_block.hpp      |   18 +-
 ext/asio/asio/detail/handler_alloc_helpers.hpp     |  238 +--
 ext/asio/asio/detail/handler_invoke_helpers.hpp    |   14 +-
 ext/asio/asio/detail/hash_map.hpp                  |   35 +-
 ext/asio/asio/detail/impl/descriptor_ops.ipp       |  382 +++
 ext/asio/asio/detail/impl/dev_poll_reactor.hpp     |   77 +
 ext/asio/asio/detail/impl/dev_poll_reactor.ipp     |  338 +++
 ext/asio/asio/detail/impl/epoll_reactor.hpp        |   75 +
 ext/asio/asio/detail/impl/epoll_reactor.ipp        |  390 +++
 .../detail/impl/eventfd_select_interrupter.ipp     |  125 +
 ext/asio/asio/detail/impl/kqueue_reactor.hpp       |   79 +
 ext/asio/asio/detail/impl/kqueue_reactor.ipp       |  385 +++
 .../asio/detail/impl/pipe_select_interrupter.ipp   |   96 +
 ext/asio/asio/detail/impl/posix_event.ipp          |   46 +
 ext/asio/asio/detail/impl/posix_mutex.ipp          |   46 +
 ext/asio/asio/detail/impl/posix_thread.ipp         |   74 +
 ext/asio/asio/detail/impl/posix_tss_ptr.ipp        |   46 +
 .../detail/impl/reactive_descriptor_service.ipp    |  136 +
 .../detail/impl/reactive_serial_port_service.ipp   |  151 +
 .../detail/impl/reactive_socket_service_base.ipp   |  212 ++
 .../asio/detail/impl/resolver_service_base.ipp     |  106 +
 ext/asio/asio/detail/impl/select_reactor.hpp       |   84 +
 ext/asio/asio/detail/impl/select_reactor.ipp       |  273 ++
 ext/asio/asio/detail/impl/service_registry.hpp     |   70 +
 ext/asio/asio/detail/impl/service_registry.ipp     |  164 ++
 ext/asio/asio/detail/impl/socket_ops.ipp           | 2917 ++++++++++++++++++++
 .../asio/detail/impl/socket_select_interrupter.ipp |  151 +
 ext/asio/asio/detail/impl/strand_service.hpp       |  140 +
 ext/asio/asio/detail/impl/strand_service.ipp       |  106 +
 ext/asio/asio/detail/impl/task_io_service.hpp      |   60 +
 ext/asio/asio/detail/impl/task_io_service.ipp      |  354 +++
 ext/asio/asio/detail/impl/throw_error.ipp          |   47 +
 ext/asio/asio/detail/impl/timer_queue.ipp          |   85 +
 ext/asio/asio/detail/impl/timer_queue_set.ipp      |  101 +
 ext/asio/asio/detail/impl/win_event.ipp            |   50 +
 .../asio/detail/impl/win_iocp_handle_service.ipp   |  452 +++
 ext/asio/asio/detail/impl/win_iocp_io_service.hpp  |  115 +
 ext/asio/asio/detail/impl/win_iocp_io_service.ipp  |  496 ++++
 .../detail/impl/win_iocp_serial_port_service.ipp   |  180 ++
 .../detail/impl/win_iocp_socket_service_base.ipp   |  575 ++++
 ext/asio/asio/detail/impl/win_mutex.ipp            |   78 +
 ext/asio/asio/detail/impl/win_thread.ipp           |  138 +
 ext/asio/asio/detail/impl/win_tss_ptr.ipp          |   57 +
 ext/asio/asio/detail/impl/winsock_init.ipp         |   69 +
 ext/asio/asio/detail/io_control.hpp                |   14 +-
 ext/asio/asio/detail/kqueue_reactor.hpp            |  406 +---
 ext/asio/asio/detail/kqueue_reactor_fwd.hpp        |   23 +-
 ext/asio/asio/detail/local_free_on_block_exit.hpp  |   18 +-
 ext/asio/asio/detail/macos_fenced_block.hpp        |   20 +-
 ext/asio/asio/detail/mutex.hpp                     |   14 +-
 ext/asio/asio/detail/noncopyable.hpp               |   14 +-
 ext/asio/asio/detail/null_event.hpp                |   18 +-
 ext/asio/asio/detail/null_fenced_block.hpp         |    6 +-
 ext/asio/asio/detail/null_mutex.hpp                |   18 +-
 ext/asio/asio/detail/null_signal_blocker.hpp       |   28 +-
 ext/asio/asio/detail/null_thread.hpp               |   31 +-
 ext/asio/asio/detail/null_tss_ptr.hpp              |   18 +-
 ext/asio/asio/detail/object_pool.hpp               |  146 +
 ext/asio/asio/detail/old_win_sdk_compat.hpp        |   18 +-
 ext/asio/asio/detail/op_queue.hpp                  |   10 +-
 ext/asio/asio/detail/operation.hpp                 |   15 +-
 ext/asio/asio/detail/pipe_select_interrupter.hpp   |   84 +-
 ext/asio/asio/detail/pop_options.hpp               |   16 +-
 ext/asio/asio/detail/posix_event.hpp               |   44 +-
 ext/asio/asio/detail/posix_fd_set_adapter.hpp      |   19 +-
 ext/asio/asio/detail/posix_mutex.hpp               |   43 +-
 ext/asio/asio/detail/posix_signal_blocker.hpp      |   23 +-
 ext/asio/asio/detail/posix_thread.hpp              |   80 +-
 ext/asio/asio/detail/posix_tss_ptr.hpp             |   44 +-
 ext/asio/asio/detail/push_options.hpp              |   18 +-
 .../asio/detail/reactive_descriptor_service.hpp    |  549 +----
 ext/asio/asio/detail/reactive_null_buffers_op.hpp  |   83 +
 .../asio/detail/reactive_serial_port_service.hpp   |  186 +-
 ext/asio/asio/detail/reactive_socket_accept_op.hpp |  131 +
 .../asio/detail/reactive_socket_connect_op.hpp     |  101 +
 ext/asio/asio/detail/reactive_socket_recv_op.hpp   |  118 +
 .../asio/detail/reactive_socket_recvfrom_op.hpp    |  128 +
 ext/asio/asio/detail/reactive_socket_send_op.hpp   |  115 +
 ext/asio/asio/detail/reactive_socket_sendto_op.hpp |  118 +
 ext/asio/asio/detail/reactive_socket_service.hpp   | 1576 +----------
 .../asio/detail/reactive_socket_service_base.hpp   |  298 ++
 ext/asio/asio/detail/reactor.hpp                   |   10 +-
 ext/asio/asio/detail/reactor_fwd.hpp               |   30 +-
 ext/asio/asio/detail/reactor_op.hpp                |   11 +-
 ext/asio/asio/detail/reactor_op_queue.hpp          |   13 +-
 ext/asio/asio/detail/regex_fwd.hpp                 |   31 +
 ext/asio/asio/detail/resolve_endpoint_op.hpp       |  116 +
 ext/asio/asio/detail/resolve_op.hpp                |  126 +
 ext/asio/asio/detail/resolver_service.hpp          |  401 +---
 ext/asio/asio/detail/resolver_service_base.hpp     |  123 +
 ext/asio/asio/detail/scoped_lock.hpp               |   10 +-
 ext/asio/asio/detail/select_interrupter.hpp        |   21 +-
 ext/asio/asio/detail/select_reactor.hpp            |  308 +--
 ext/asio/asio/detail/select_reactor_fwd.hpp        |   11 +-
 ext/asio/asio/detail/service_registry.hpp          |  197 +--
 ext/asio/asio/detail/service_registry_fwd.hpp      |   10 +-
 ext/asio/asio/detail/shared_ptr.hpp                |   38 +
 ext/asio/asio/detail/signal_blocker.hpp            |   24 +-
 ext/asio/asio/detail/signal_init.hpp               |   20 +-
 ext/asio/asio/detail/socket_holder.hpp             |   17 +-
 ext/asio/asio/detail/socket_ops.hpp                | 2051 ++------------
 ext/asio/asio/detail/socket_option.hpp             |   14 +-
 ext/asio/asio/detail/socket_select_interrupter.hpp |  156 +-
 ext/asio/asio/detail/socket_types.hpp              |   76 +-
 ext/asio/asio/detail/solaris_fenced_block.hpp      |   20 +-
 ext/asio/asio/detail/strand_service.hpp            |  204 +--
 ext/asio/asio/detail/task_io_service.hpp           |  381 +---
 ext/asio/asio/detail/task_io_service_fwd.hpp       |   11 +-
 ext/asio/asio/detail/task_io_service_operation.hpp |   18 +-
 ext/asio/asio/detail/thread.hpp                    |   14 +-
 ext/asio/asio/detail/throw_error.hpp               |   35 +-
 ext/asio/asio/detail/timer_op.hpp                  |   11 +-
 ext/asio/asio/detail/timer_queue.hpp               |  289 ++-
 ext/asio/asio/detail/timer_queue_base.hpp          |   11 +-
 ext/asio/asio/detail/timer_queue_fwd.hpp           |   10 +-
 ext/asio/asio/detail/timer_queue_set.hpp           |   85 +-
 ext/asio/asio/detail/timer_scheduler.hpp           |   11 +-
 ext/asio/asio/detail/timer_scheduler_fwd.hpp       |   28 +-
 ext/asio/asio/detail/tss_ptr.hpp                   |   14 +-
 ext/asio/asio/detail/wait_handler.hpp              |   76 +
 ext/asio/asio/detail/weak_ptr.hpp                  |   39 +
 ext/asio/asio/detail/win_event.hpp                 |   40 +-
 ext/asio/asio/detail/win_fd_set_adapter.hpp        |   16 +-
 ext/asio/asio/detail/win_fenced_block.hpp          |   36 +-
 ext/asio/asio/detail/win_iocp_handle_read_op.hpp   |  101 +
 ext/asio/asio/detail/win_iocp_handle_service.hpp   |  573 +----
 ext/asio/asio/detail/win_iocp_handle_write_op.hpp  |   97 +
 ext/asio/asio/detail/win_iocp_io_service.hpp       |  599 +----
 ext/asio/asio/detail/win_iocp_io_service_fwd.hpp   |   30 +-
 ext/asio/asio/detail/win_iocp_null_buffers_op.hpp  |  112 +
 ext/asio/asio/detail/win_iocp_operation.hpp        |   19 +-
 ext/asio/asio/detail/win_iocp_overlapped_op.hpp    |   84 +
 ext/asio/asio/detail/win_iocp_overlapped_ptr.hpp   |   72 +-
 .../asio/detail/win_iocp_serial_port_service.hpp   |  214 +-
 ext/asio/asio/detail/win_iocp_socket_accept_op.hpp |  158 ++
 ext/asio/asio/detail/win_iocp_socket_recv_op.hpp   |  108 +
 .../asio/detail/win_iocp_socket_recvfrom_op.hpp    |  116 +
 ext/asio/asio/detail/win_iocp_socket_send_op.hpp   |  102 +
 ext/asio/asio/detail/win_iocp_socket_service.hpp   | 1806 +-----------
 .../asio/detail/win_iocp_socket_service_base.hpp   |  385 +++
 ext/asio/asio/detail/win_mutex.hpp                 |   69 +-
 ext/asio/asio/detail/win_thread.hpp                |  153 +-
 ext/asio/asio/detail/win_tss_ptr.hpp               |   44 +-
 ext/asio/asio/detail/wince_thread.hpp              |   32 +-
 ext/asio/asio/detail/winsock_init.hpp              |  120 +-
 ext/asio/asio/detail/wrapped_handler.hpp           |   18 +-
 ext/asio/asio/error.hpp                            |   44 +-
 ext/asio/asio/error_code.hpp                       |   28 +-
 ext/asio/asio/handler_alloc_hook.hpp               |    8 +-
 ext/asio/asio/handler_invoke_hook.hpp              |    4 +-
 ext/asio/asio/impl/error.ipp                       |   33 +
 ext/asio/asio/impl/error_code.ipp                  |   97 +-
 ext/asio/asio/impl/io_service.hpp                  |  132 +
 ext/asio/asio/impl/io_service.ipp                  |  143 +-
 ext/asio/asio/impl/read.hpp                        |  386 +++
 ext/asio/asio/impl/read_at.hpp                     |  410 +++
 ext/asio/asio/impl/read_until.hpp                  |  902 ++++++
 ext/asio/asio/impl/serial_port_base.hpp            |   59 +
 ext/asio/asio/impl/serial_port_base.ipp            |  106 +-
 ext/asio/asio/impl/src.cpp                         |   25 +
 ext/asio/asio/impl/src.hpp                         |   65 +
 ext/asio/asio/impl/write.hpp                       |  396 +++
 ext/asio/asio/impl/write_at.hpp                    |  417 +++
 ext/asio/asio/io_service.hpp                       |  105 +-
 ext/asio/asio/ip/address.hpp                       |  207 +--
 ext/asio/asio/ip/address_v4.hpp                    |  175 +-
 ext/asio/asio/ip/address_v6.hpp                    |  305 +--
 ext/asio/asio/ip/basic_endpoint.hpp                |  235 +--
 ext/asio/asio/ip/basic_resolver.hpp                |   13 +-
 ext/asio/asio/ip/basic_resolver_entry.hpp          |   11 +-
 ext/asio/asio/ip/basic_resolver_iterator.hpp       |   18 +-
 ext/asio/asio/ip/basic_resolver_query.hpp          |   15 +-
 ext/asio/asio/ip/detail/endpoint.hpp               |  140 +
 ext/asio/asio/ip/detail/impl/endpoint.ipp          |  202 ++
 ext/asio/asio/ip/detail/socket_option.hpp          |   17 +-
 ext/asio/asio/ip/host_name.hpp                     |   44 +-
 ext/asio/asio/ip/icmp.hpp                          |   13 +-
 ext/asio/asio/ip/impl/address.hpp                  |   53 +
 ext/asio/asio/ip/impl/address.ipp                  |  203 ++
 ext/asio/asio/ip/impl/address_v4.hpp               |   53 +
 ext/asio/asio/ip/impl/address_v4.ipp               |  178 ++
 ext/asio/asio/ip/impl/address_v6.hpp               |   53 +
 ext/asio/asio/ip/impl/address_v6.ipp               |  313 +++
 ext/asio/asio/ip/impl/basic_endpoint.hpp           |   55 +
 ext/asio/asio/ip/impl/host_name.ipp                |   56 +
 ext/asio/asio/ip/multicast.hpp                     |   15 +-
 ext/asio/asio/ip/resolver_query_base.hpp           |   15 +-
 ext/asio/asio/ip/resolver_service.hpp              |   23 +-
 ext/asio/asio/ip/tcp.hpp                           |   15 +-
 ext/asio/asio/ip/udp.hpp                           |   13 +-
 ext/asio/asio/ip/unicast.hpp                       |   15 +-
 ext/asio/asio/ip/v6_only.hpp                       |   11 +-
 ext/asio/asio/is_read_buffered.hpp                 |   11 +-
 ext/asio/asio/is_write_buffered.hpp                |   11 +-
 ext/asio/asio/local/basic_endpoint.hpp             |  137 +-
 ext/asio/asio/local/connect_pair.hpp               |   30 +-
 ext/asio/asio/local/datagram_protocol.hpp          |   20 +-
 ext/asio/asio/local/detail/endpoint.hpp            |  133 +
 ext/asio/asio/local/detail/impl/endpoint.ipp       |  138 +
 ext/asio/asio/local/stream_protocol.hpp            |   20 +-
 ext/asio/asio/placeholders.hpp                     |    9 +-
 ext/asio/asio/posix/basic_descriptor.hpp           |   20 +-
 ext/asio/asio/posix/basic_stream_descriptor.hpp    |   24 +-
 ext/asio/asio/posix/descriptor_base.hpp            |   19 +-
 ext/asio/asio/posix/stream_descriptor.hpp          |   14 +-
 ext/asio/asio/posix/stream_descriptor_service.hpp  |   32 +-
 ext/asio/asio/raw_socket_service.hpp               |   12 +-
 ext/asio/asio/read.hpp                             |   17 +-
 ext/asio/asio/read_at.hpp                          |   17 +-
 ext/asio/asio/read_until.hpp                       |   21 +-
 ext/asio/asio/serial_port.hpp                      |   10 +-
 ext/asio/asio/serial_port_base.hpp                 |   71 +-
 ext/asio/asio/serial_port_service.hpp              |   23 +-
 ext/asio/asio/socket_acceptor_service.hpp          |    8 +-
 ext/asio/asio/socket_base.hpp                      |   11 +-
 ext/asio/asio/ssl.hpp                              |    2 +-
 ext/asio/asio/ssl/basic_context.hpp                |   16 +-
 ext/asio/asio/ssl/context.hpp                      |   11 +-
 ext/asio/asio/ssl/context_base.hpp                 |   15 +-
 ext/asio/asio/ssl/context_service.hpp              |   15 +-
 .../asio/ssl/detail/openssl_context_service.hpp    |   15 +-
 ext/asio/asio/ssl/detail/openssl_init.hpp          |   15 +-
 ext/asio/asio/ssl/detail/openssl_operation.hpp     |   22 +-
 .../asio/ssl/detail/openssl_stream_service.hpp     |   26 +-
 ext/asio/asio/ssl/detail/openssl_types.hpp         |   16 +-
 ext/asio/asio/ssl/stream.hpp                       |   17 +-
 ext/asio/asio/ssl/stream_base.hpp                  |   11 +-
 ext/asio/asio/ssl/stream_service.hpp               |   18 +-
 ext/asio/asio/strand.hpp                           |    9 +-
 ext/asio/asio/stream_socket_service.hpp            |   12 +-
 ext/asio/asio/streambuf.hpp                        |   10 +-
 ext/asio/asio/system_error.hpp                     |   11 +-
 ext/asio/asio/thread.hpp                           |    7 +-
 ext/asio/asio/time_traits.hpp                      |    6 +-
 ext/asio/asio/version.hpp                          |    4 +-
 ext/asio/asio/windows/basic_handle.hpp             |   22 +-
 .../asio/windows/basic_random_access_handle.hpp    |   24 +-
 ext/asio/asio/windows/basic_stream_handle.hpp      |   22 +-
 ext/asio/asio/windows/overlapped_ptr.hpp           |   26 +-
 ext/asio/asio/windows/random_access_handle.hpp     |   14 +-
 .../asio/windows/random_access_handle_service.hpp  |   30 +-
 ext/asio/asio/windows/stream_handle.hpp            |   14 +-
 ext/asio/asio/windows/stream_handle_service.hpp    |   31 +-
 ext/asio/asio/write.hpp                            |   17 +-
 ext/asio/asio/write_at.hpp                         |   17 +-
 src/bin/auth/main.cc                               |   10 +-
 src/bin/auth/statistics.cc                         |    4 -
 src/bin/auth/tests/Makefile.am                     |    2 -
 src/bin/bind10/bind10.py.in                        |    5 +
 src/bin/bind10/run_bind10.sh.in                    |    4 +-
 src/bin/bind10/tests/bind10_test.py.in             |   21 +-
 src/bin/cfgmgr/b10-cfgmgr.py.in                    |    2 +-
 src/bin/host/Makefile.am                           |   31 +-
 src/bin/host/README                                |   16 +-
 src/bin/host/b10-host.1                            |  122 +
 src/bin/host/b10-host.xml                          |  201 ++
 src/bin/host/host.cc                               |   73 +-
 src/bin/msgq/tests/msgq_test.py                    |    2 +-
 src/bin/resolver/response_scrubber.cc              |   24 +-
 src/bin/stats/Makefile.am                          |   27 +-
 src/bin/stats/b10-stats-httpd.8                    |  132 +
 src/bin/stats/b10-stats-httpd.xml                  |  215 ++
 src/bin/stats/run_b10-stats.sh.in                  |   33 -
 src/bin/stats/run_b10-stats_stub.sh.in             |   33 -
 src/bin/stats/stats-httpd-xml.tpl.in               |   24 +
 src/bin/stats/stats-httpd-xsd.tpl.in               |   38 +
 src/bin/stats/stats-httpd-xsl.tpl.in               |   56 +
 src/bin/stats/stats-httpd.spec.in                  |   54 +
 src/bin/stats/stats.py.in                          |   13 +-
 src/bin/stats/stats.spec.in                        |  140 +
 src/bin/stats/stats.spec.pre.in                    |  140 -
 src/bin/stats/stats_httpd.py.in                    |  485 ++++
 src/bin/stats/stats_stub.py.in                     |  154 -
 src/bin/stats/tests/Makefile.am                    |   10 +-
 src/bin/stats/tests/b10-stats-httpd_test.py        |  444 +++
 src/bin/stats/tests/b10-stats_stub_test.py         |  115 -
 src/bin/stats/tests/b10-stats_test.py              |   18 +-
 src/bin/stats/tests/fake_select.py                 |   43 +
 src/bin/stats/tests/fake_socket.py                 |   70 +
 src/bin/stats/tests/http/Makefile.am               |    2 +
 .../stats/tests/{isc/utils => http}/__init__.py    |    0 
 src/bin/stats/tests/http/server.py                 |   96 +
 src/bin/stats/tests/isc/cc/session.py              |   46 +-
 src/bin/stats/tests/isc/config/ccsession.py        |   59 +-
 src/bin/stats/tests/isc/util/process.py            |    5 +-
 src/bin/stats/tests/isc/utils/Makefile.am          |    2 -
 src/bin/stats/tests/isc/utils/process.py           |   18 -
 src/bin/stats/tests/stats_test.in                  |   31 -
 src/bin/xfrin/tests/Makefile.am                    |    2 +-
 src/bin/xfrin/tests/xfrin_test.py                  |   51 +
 src/bin/xfrin/xfrin.py.in                          |   94 +-
 src/bin/xfrin/xfrin.spec                           |    5 +
 src/bin/xfrout/tests/Makefile.am                   |    2 +-
 src/bin/zonemgr/tests/zonemgr_test.py              |  150 +-
 src/bin/zonemgr/zonemgr.py.in                      |   23 +-
 src/bin/zonemgr/zonemgr.spec.pre.in                |   12 +-
 src/cppcheck-suppress.lst                          |    2 +-
 src/lib/Makefile.am                                |    5 +-
 src/lib/asiodns/Makefile.am                        |   13 +-
 src/lib/asiodns/asiodef.cc                         |   39 -
 src/lib/asiodns/asiodef.h                          |   23 -
 src/lib/asiodns/asiodef.mes                        |   56 +
 src/lib/asiodns/asiodef.msg                        |   56 -
 src/lib/asiodns/io_fetch.cc                        |   54 +-
 src/lib/asiolink/Makefile.am                       |    1 -
 src/lib/asiolink/interval_timer.h                  |    2 +-
 src/lib/asiolink/io_service.h                      |    2 +-
 src/lib/asiolink/tests/Makefile.am                 |    4 -
 src/lib/asiolink/tests/run_unittests.cc            |    1 -
 src/lib/cc/Makefile.am                             |    1 +
 src/lib/cc/tests/Makefile.am                       |    1 -
 src/lib/config/Makefile.am                         |    1 -
 src/lib/config/tests/fake_session.cc               |    8 +-
 src/lib/cryptolink/Makefile.am                     |   14 +
 src/lib/cryptolink/crypto_hmac.cc                  |  237 ++
 src/lib/cryptolink/crypto_hmac.h                   |  209 ++
 src/lib/cryptolink/cryptolink.cc                   |   69 +
 src/lib/cryptolink/cryptolink.h                    |  204 ++
 src/lib/cryptolink/tests/Makefile.am               |   26 +
 src/lib/cryptolink/tests/crypto_unittests.cc       |  511 ++++
 src/lib/cryptolink/tests/run_unittests.cc          |   22 +
 src/lib/datasrc/data_source.cc                     |   21 +-
 src/lib/datasrc/tests/datasrc_unittest.cc          |   16 +
 src/lib/dns/Makefile.am                            |   64 +-
 src/lib/dns/edns.cc                                |   29 +-
 src/lib/dns/edns.h                                 |   12 +-
 src/lib/dns/message.cc                             |  419 ++--
 src/lib/dns/message.h                              |   55 +-
 src/lib/dns/messagerenderer.cc                     |    5 +-
 src/lib/dns/python/Makefile.am                     |    1 +
 src/lib/dns/python/message_python.cc               |  123 +-
 src/lib/dns/python/pydnspp.cc                      |    5 +
 src/lib/dns/python/tests/Makefile.am               |    3 +-
 src/lib/dns/python/tests/message_python_test.py    |   37 +-
 src/lib/dns/python/tests/tsig_python_test.py       |   29 +
 src/lib/dns/python/tests/tsigkey_python_test.py    |   22 +
 src/lib/dns/python/tsig_python.cc                  |  157 ++
 src/lib/dns/python/tsigkey_python.cc               |   40 +-
 src/lib/dns/question.cc                            |    2 +-
 src/lib/dns/question.h                             |    6 +-
 src/lib/dns/rdata/any_255/tsig_250.cc              |   12 +-
 src/lib/dns/rrclass-placeholder.h                  |    4 +-
 src/lib/dns/rrclass.cc                             |    2 +-
 src/lib/dns/rrset.cc                               |    6 +-
 src/lib/dns/rrset.h                                |    6 +-
 src/lib/dns/rrttl.cc                               |    2 +-
 src/lib/dns/rrttl.h                                |    4 +-
 src/lib/dns/tests/Makefile.am                      |    6 +
 src/lib/dns/tests/message_unittest.cc              |  192 ++-
 src/lib/dns/tests/run_unittests.cc                 |    3 +
 src/lib/dns/tests/testdata/Makefile.am             |   21 +-
 src/lib/dns/tests/testdata/gen-wiredata.py.in      |   92 +-
 src/lib/dns/tests/testdata/message_fromWire12.spec |   21 +
 src/lib/dns/tests/testdata/message_fromWire13.spec |   20 +
 src/lib/dns/tests/testdata/message_fromWire14.spec |   21 +
 src/lib/dns/tests/testdata/message_fromWire15.spec |   22 +
 src/lib/dns/tests/testdata/message_fromWire16.spec |   21 +
 src/lib/dns/tests/testdata/message_toText1.spec    |   24 +
 src/lib/dns/tests/testdata/message_toText1.txt     |   14 +
 src/lib/dns/tests/testdata/message_toText2.spec    |   14 +
 src/lib/dns/tests/testdata/message_toText2.txt     |    8 +
 src/lib/dns/tests/testdata/message_toText3.spec    |   31 +
 src/lib/dns/tests/testdata/message_toText3.txt     |   17 +
 src/lib/dns/tests/testdata/message_toWire2.spec    |   21 +
 src/lib/dns/tests/testdata/message_toWire3.spec    |   22 +
 src/lib/dns/tests/testdata/tsigrecord_toWire1.spec |   16 +
 src/lib/dns/tests/testdata/tsigrecord_toWire2.spec |   19 +
 src/lib/dns/tests/tsig_unittest.cc                 |  505 ++++
 src/lib/dns/tests/tsigerror_unittest.cc            |  102 +
 src/lib/dns/tests/tsigkey_unittest.cc              |   43 +
 src/lib/dns/tests/tsigrecord_unittest.cc           |  160 ++
 src/lib/dns/tsig.cc                                |  207 ++
 src/lib/dns/tsig.h                                 |  232 ++
 src/lib/dns/tsigerror.cc                           |   57 +
 src/lib/dns/tsigerror.h                            |  328 +++
 src/lib/dns/tsigkey.cc                             |   96 +-
 src/lib/dns/tsigkey.h                              |   36 +
 src/lib/dns/tsigrecord.cc                          |  145 +
 src/lib/dns/tsigrecord.h                           |  285 ++
 src/lib/log/Makefile.am                            |    4 +-
 src/lib/log/README                                 |  119 +-
 src/lib/log/compiler/message.cc                    |   47 +-
 src/lib/log/log_formatter.cc                       |   42 +
 src/lib/log/log_formatter.h                        |  146 +
 src/lib/log/logger.cc                              |   63 +-
 src/lib/log/logger.h                               |   25 +-
 src/lib/log/logger_impl.cc                         |   20 +-
 src/lib/log/logger_impl.h                          |   62 +-
 src/lib/log/logger_support.cc                      |   89 +-
 src/lib/log/logger_support.h                       |   31 +
 src/lib/log/macros.h                               |   50 +
 src/lib/log/message_exception.cc                   |   26 -
 src/lib/log/message_exception.h                    |   37 +-
 src/lib/log/message_reader.cc                      |  182 +-
 src/lib/log/message_reader.h                       |   19 +-
 src/lib/log/messagedef.cc                          |   70 +-
 src/lib/log/messagedef.h                           |   14 +-
 src/lib/log/messagedef.mes                         |  202 +-
 src/lib/log/tests/Makefile.am                      |    1 +
 src/lib/log/tests/log_formatter_unittest.cc        |  125 +
 src/lib/log/tests/logger_support_test.cc           |   18 +-
 src/lib/log/tests/message_dictionary_unittest.cc   |    4 +-
 src/lib/log/tests/message_reader_unittest.cc       |   47 +-
 src/lib/log/tests/run_time_init_test.sh.in         |   41 +-
 src/lib/nsas/Makefile.am                           |   31 +-
 src/lib/nsas/nameserver_address_store.cc           |    7 +
 src/lib/nsas/nameserver_address_store.h            |    1 -
 src/lib/nsas/nameserver_entry.cc                   |   24 +-
 src/lib/nsas/nsas_log.cc                           |   26 +
 src/lib/nsas/nsas_log.h                            |   53 +
 src/lib/nsas/nsasdef.mes                           |   61 +
 src/lib/nsas/tests/Makefile.am                     |    1 +
 src/lib/nsas/tests/nameserver_address_unittest.cc  |    3 +-
 src/lib/nsas/tests/nameserver_entry_unittest.cc    |    3 +-
 src/lib/nsas/tests/nsas_test.h                     |  148 +-
 src/lib/nsas/tests/run_unittests.cc                |    9 +
 src/lib/python/isc/notify/tests/Makefile.am        |    2 +-
 src/lib/resolve/recursive_query.cc                 |   66 +-
 src/lib/resolve/tests/recursive_query_unittest.cc  |  110 +-
 src/lib/server_common/portconfig.cc                |   19 +-
 src/lib/server_common/tests/portconfig_unittest.cc |    2 +-
 src/lib/util/encode/base_n.cc                      |    2 +-
 src/lib/util/time_utilities.cc                     |    7 +-
 src/lib/util/time_utilities.h                      |   28 +
 src/lib/util/unittests/Makefile.am                 |    5 +-
 src/lib/util/unittests/newhook.cc                  |   51 +
 src/lib/util/unittests/newhook.h                   |   82 +
 src/lib/util/unittests/resolver.h                  |  193 ++
 src/lib/util/unittests/testdata.cc                 |   61 +
 src/lib/util/unittests/testdata.h                  |   54 +
 src/lib/util/unittests/textdata.h                  |  103 +
 tests/tools/badpacket/scan.cc                      |    4 -
 tests/tools/badpacket/tests/Makefile.am            |    1 +
 488 files changed, 31083 insertions(+), 15182 deletions(-)
 create mode 100644 ext/asio/asio/basic_streambuf_fwd.hpp
 create mode 100644 ext/asio/asio/detail/array_fwd.hpp
 create mode 100644 ext/asio/asio/detail/config.hpp
 create mode 100644 ext/asio/asio/detail/descriptor_read_op.hpp
 create mode 100644 ext/asio/asio/detail/descriptor_write_op.hpp
 create mode 100644 ext/asio/asio/detail/gcc_arm_fenced_block.hpp
 create mode 100644 ext/asio/asio/detail/gcc_hppa_fenced_block.hpp
 create mode 100644 ext/asio/asio/detail/gcc_sync_fenced_block.hpp
 create mode 100644 ext/asio/asio/detail/impl/descriptor_ops.ipp
 create mode 100644 ext/asio/asio/detail/impl/dev_poll_reactor.hpp
 create mode 100644 ext/asio/asio/detail/impl/dev_poll_reactor.ipp
 create mode 100644 ext/asio/asio/detail/impl/epoll_reactor.hpp
 create mode 100644 ext/asio/asio/detail/impl/epoll_reactor.ipp
 create mode 100644 ext/asio/asio/detail/impl/eventfd_select_interrupter.ipp
 create mode 100644 ext/asio/asio/detail/impl/kqueue_reactor.hpp
 create mode 100644 ext/asio/asio/detail/impl/kqueue_reactor.ipp
 create mode 100644 ext/asio/asio/detail/impl/pipe_select_interrupter.ipp
 create mode 100644 ext/asio/asio/detail/impl/posix_event.ipp
 create mode 100644 ext/asio/asio/detail/impl/posix_mutex.ipp
 create mode 100644 ext/asio/asio/detail/impl/posix_thread.ipp
 create mode 100644 ext/asio/asio/detail/impl/posix_tss_ptr.ipp
 create mode 100644 ext/asio/asio/detail/impl/reactive_descriptor_service.ipp
 create mode 100644 ext/asio/asio/detail/impl/reactive_serial_port_service.ipp
 create mode 100644 ext/asio/asio/detail/impl/reactive_socket_service_base.ipp
 create mode 100644 ext/asio/asio/detail/impl/resolver_service_base.ipp
 create mode 100644 ext/asio/asio/detail/impl/select_reactor.hpp
 create mode 100644 ext/asio/asio/detail/impl/select_reactor.ipp
 create mode 100644 ext/asio/asio/detail/impl/service_registry.hpp
 create mode 100644 ext/asio/asio/detail/impl/service_registry.ipp
 create mode 100644 ext/asio/asio/detail/impl/socket_ops.ipp
 create mode 100644 ext/asio/asio/detail/impl/socket_select_interrupter.ipp
 create mode 100644 ext/asio/asio/detail/impl/strand_service.hpp
 create mode 100644 ext/asio/asio/detail/impl/strand_service.ipp
 create mode 100644 ext/asio/asio/detail/impl/task_io_service.hpp
 create mode 100644 ext/asio/asio/detail/impl/task_io_service.ipp
 create mode 100644 ext/asio/asio/detail/impl/throw_error.ipp
 create mode 100644 ext/asio/asio/detail/impl/timer_queue.ipp
 create mode 100644 ext/asio/asio/detail/impl/timer_queue_set.ipp
 create mode 100644 ext/asio/asio/detail/impl/win_event.ipp
 create mode 100644 ext/asio/asio/detail/impl/win_iocp_handle_service.ipp
 create mode 100644 ext/asio/asio/detail/impl/win_iocp_io_service.hpp
 create mode 100644 ext/asio/asio/detail/impl/win_iocp_io_service.ipp
 create mode 100644 ext/asio/asio/detail/impl/win_iocp_serial_port_service.ipp
 create mode 100644 ext/asio/asio/detail/impl/win_iocp_socket_service_base.ipp
 create mode 100644 ext/asio/asio/detail/impl/win_mutex.ipp
 create mode 100644 ext/asio/asio/detail/impl/win_thread.ipp
 create mode 100644 ext/asio/asio/detail/impl/win_tss_ptr.ipp
 create mode 100644 ext/asio/asio/detail/impl/winsock_init.ipp
 create mode 100644 ext/asio/asio/detail/object_pool.hpp
 create mode 100644 ext/asio/asio/detail/reactive_null_buffers_op.hpp
 create mode 100644 ext/asio/asio/detail/reactive_socket_accept_op.hpp
 create mode 100644 ext/asio/asio/detail/reactive_socket_connect_op.hpp
 create mode 100644 ext/asio/asio/detail/reactive_socket_recv_op.hpp
 create mode 100644 ext/asio/asio/detail/reactive_socket_recvfrom_op.hpp
 create mode 100644 ext/asio/asio/detail/reactive_socket_send_op.hpp
 create mode 100644 ext/asio/asio/detail/reactive_socket_sendto_op.hpp
 create mode 100644 ext/asio/asio/detail/reactive_socket_service_base.hpp
 create mode 100644 ext/asio/asio/detail/regex_fwd.hpp
 create mode 100644 ext/asio/asio/detail/resolve_endpoint_op.hpp
 create mode 100644 ext/asio/asio/detail/resolve_op.hpp
 create mode 100644 ext/asio/asio/detail/resolver_service_base.hpp
 create mode 100644 ext/asio/asio/detail/shared_ptr.hpp
 create mode 100644 ext/asio/asio/detail/wait_handler.hpp
 create mode 100644 ext/asio/asio/detail/weak_ptr.hpp
 create mode 100644 ext/asio/asio/detail/win_iocp_handle_read_op.hpp
 create mode 100644 ext/asio/asio/detail/win_iocp_handle_write_op.hpp
 create mode 100644 ext/asio/asio/detail/win_iocp_null_buffers_op.hpp
 create mode 100644 ext/asio/asio/detail/win_iocp_overlapped_op.hpp
 create mode 100644 ext/asio/asio/detail/win_iocp_socket_accept_op.hpp
 create mode 100644 ext/asio/asio/detail/win_iocp_socket_recv_op.hpp
 create mode 100644 ext/asio/asio/detail/win_iocp_socket_recvfrom_op.hpp
 create mode 100644 ext/asio/asio/detail/win_iocp_socket_send_op.hpp
 create mode 100644 ext/asio/asio/detail/win_iocp_socket_service_base.hpp
 create mode 100644 ext/asio/asio/impl/error.ipp
 create mode 100644 ext/asio/asio/impl/io_service.hpp
 create mode 100644 ext/asio/asio/impl/read.hpp
 create mode 100644 ext/asio/asio/impl/read_at.hpp
 create mode 100644 ext/asio/asio/impl/read_until.hpp
 create mode 100644 ext/asio/asio/impl/serial_port_base.hpp
 create mode 100644 ext/asio/asio/impl/src.cpp
 create mode 100644 ext/asio/asio/impl/src.hpp
 create mode 100644 ext/asio/asio/impl/write.hpp
 create mode 100644 ext/asio/asio/impl/write_at.hpp
 create mode 100644 ext/asio/asio/ip/detail/endpoint.hpp
 create mode 100644 ext/asio/asio/ip/detail/impl/endpoint.ipp
 create mode 100644 ext/asio/asio/ip/impl/address.hpp
 create mode 100644 ext/asio/asio/ip/impl/address.ipp
 create mode 100644 ext/asio/asio/ip/impl/address_v4.hpp
 create mode 100644 ext/asio/asio/ip/impl/address_v4.ipp
 create mode 100644 ext/asio/asio/ip/impl/address_v6.hpp
 create mode 100644 ext/asio/asio/ip/impl/address_v6.ipp
 create mode 100644 ext/asio/asio/ip/impl/basic_endpoint.hpp
 create mode 100644 ext/asio/asio/ip/impl/host_name.ipp
 create mode 100644 ext/asio/asio/local/detail/endpoint.hpp
 create mode 100644 ext/asio/asio/local/detail/impl/endpoint.ipp
 mode change 100644 => 100755 src/bin/bind10/run_bind10.sh.in
 create mode 100644 src/bin/host/b10-host.1
 create mode 100644 src/bin/host/b10-host.xml
 create mode 100644 src/bin/stats/b10-stats-httpd.8
 create mode 100644 src/bin/stats/b10-stats-httpd.xml
 delete mode 100644 src/bin/stats/run_b10-stats.sh.in
 delete mode 100644 src/bin/stats/run_b10-stats_stub.sh.in
 create mode 100644 src/bin/stats/stats-httpd-xml.tpl.in
 create mode 100644 src/bin/stats/stats-httpd-xsd.tpl.in
 create mode 100644 src/bin/stats/stats-httpd-xsl.tpl.in
 create mode 100644 src/bin/stats/stats-httpd.spec.in
 mode change 100755 => 100644 src/bin/stats/stats.py.in
 create mode 100644 src/bin/stats/stats.spec.in
 delete mode 100644 src/bin/stats/stats.spec.pre.in
 create mode 100644 src/bin/stats/stats_httpd.py.in
 delete mode 100755 src/bin/stats/stats_stub.py.in
 create mode 100644 src/bin/stats/tests/b10-stats-httpd_test.py
 delete mode 100644 src/bin/stats/tests/b10-stats_stub_test.py
 create mode 100644 src/bin/stats/tests/fake_select.py
 create mode 100644 src/bin/stats/tests/fake_socket.py
 create mode 100644 src/bin/stats/tests/http/Makefile.am
 rename src/bin/stats/tests/{isc/utils => http}/__init__.py (100%)
 create mode 100644 src/bin/stats/tests/http/server.py
 delete mode 100644 src/bin/stats/tests/isc/utils/Makefile.am
 delete mode 100644 src/bin/stats/tests/isc/utils/process.py
 delete mode 100644 src/bin/stats/tests/stats_test.in
 delete mode 100644 src/lib/asiodns/asiodef.cc
 delete mode 100644 src/lib/asiodns/asiodef.h
 create mode 100644 src/lib/asiodns/asiodef.mes
 delete mode 100644 src/lib/asiodns/asiodef.msg
 create mode 100644 src/lib/cryptolink/Makefile.am
 create mode 100644 src/lib/cryptolink/crypto_hmac.cc
 create mode 100644 src/lib/cryptolink/crypto_hmac.h
 create mode 100644 src/lib/cryptolink/cryptolink.cc
 create mode 100644 src/lib/cryptolink/cryptolink.h
 create mode 100644 src/lib/cryptolink/tests/Makefile.am
 create mode 100644 src/lib/cryptolink/tests/crypto_unittests.cc
 create mode 100644 src/lib/cryptolink/tests/run_unittests.cc
 create mode 100644 src/lib/dns/python/tests/tsig_python_test.py
 create mode 100644 src/lib/dns/python/tsig_python.cc
 create mode 100644 src/lib/dns/tests/testdata/message_fromWire12.spec
 create mode 100644 src/lib/dns/tests/testdata/message_fromWire13.spec
 create mode 100644 src/lib/dns/tests/testdata/message_fromWire14.spec
 create mode 100644 src/lib/dns/tests/testdata/message_fromWire15.spec
 create mode 100644 src/lib/dns/tests/testdata/message_fromWire16.spec
 create mode 100644 src/lib/dns/tests/testdata/message_toText1.spec
 create mode 100644 src/lib/dns/tests/testdata/message_toText1.txt
 create mode 100644 src/lib/dns/tests/testdata/message_toText2.spec
 create mode 100644 src/lib/dns/tests/testdata/message_toText2.txt
 create mode 100644 src/lib/dns/tests/testdata/message_toText3.spec
 create mode 100644 src/lib/dns/tests/testdata/message_toText3.txt
 create mode 100644 src/lib/dns/tests/testdata/message_toWire2.spec
 create mode 100644 src/lib/dns/tests/testdata/message_toWire3.spec
 create mode 100644 src/lib/dns/tests/testdata/tsigrecord_toWire1.spec
 create mode 100644 src/lib/dns/tests/testdata/tsigrecord_toWire2.spec
 create mode 100644 src/lib/dns/tests/tsig_unittest.cc
 create mode 100644 src/lib/dns/tests/tsigerror_unittest.cc
 create mode 100644 src/lib/dns/tests/tsigrecord_unittest.cc
 create mode 100644 src/lib/dns/tsig.cc
 create mode 100644 src/lib/dns/tsig.h
 create mode 100644 src/lib/dns/tsigerror.cc
 create mode 100644 src/lib/dns/tsigerror.h
 create mode 100644 src/lib/dns/tsigrecord.cc
 create mode 100644 src/lib/dns/tsigrecord.h
 create mode 100644 src/lib/log/log_formatter.cc
 create mode 100644 src/lib/log/log_formatter.h
 create mode 100644 src/lib/log/macros.h
 delete mode 100644 src/lib/log/message_exception.cc
 create mode 100644 src/lib/log/tests/log_formatter_unittest.cc
 create mode 100644 src/lib/nsas/nsas_log.cc
 create mode 100644 src/lib/nsas/nsas_log.h
 create mode 100644 src/lib/nsas/nsasdef.mes
 create mode 100644 src/lib/util/unittests/newhook.cc
 create mode 100644 src/lib/util/unittests/newhook.h
 create mode 100644 src/lib/util/unittests/resolver.h
 create mode 100644 src/lib/util/unittests/testdata.cc
 create mode 100644 src/lib/util/unittests/testdata.h
 create mode 100644 src/lib/util/unittests/textdata.h

-----------------------------------------------------------------------
diff --git a/ChangeLog b/ChangeLog
index 3cd1727..6c7beda 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,93 @@
+234.	[func]      jerry
+	src/bin/xfrin: update xfrin to use TSIG. Currently it only supports
+	sending a signed TSIG request or SOA request.
+	(Trac #815, git a892818fb13a1839c82104523cb6cb359c970e88)
+
+233.	[func]      stephen
+	Added new-style logging statements to the NSAS code.
+	(Trac #745, git ceef68cd1223ae14d8412adbe18af2812ade8c2d)
+
+232.	[func]      stephen
+	To facilitate the writing of extended descriptions in message files,
+	altered the message file format.  The message is now flagged with a "%"
+	as the first non-blank character in the line and the lines in the
+	extended description are no longer preceded by a "+".
+	(Trac #900, git b395258c708b49a5da8d0cffcb48d83294354ba3)
+
+231.	[func]*
+	The logging interface changed slightly. We use
+	logger.foo(MESSAGE_ID).arg(bar); instead of logger.foo(MESSAGE_ID, bar);
+	internally. The message definitions use '%1,%2,...' instead of '%s,%d',
+	which allows us to cope better with mismatched placeholders and allows
+	reordering of them in case of translation.
+	(Trac901, git 4903410e45670b30d7283f5d69dc28c2069237d6)
+
+230.	[bug]		naokikambe
+	Removed too repeated verbose messages in two cases of:
+	 - when auth sends statistics data to stats
+	 - when stats receives statistics data from other modules
+	(Trac#620, git 0ecb807011196eac01f281d40bc7c9d44565b364)
+
+229.	[doc]		jreed
+	Add manual page for b10-host.
+	(git a437d4e26b81bb07181ff35a625c540703eee845)
+
+228.	[func]*		jreed
+	The host tool is renamed to b10-host. While the utility is
+	a work in progress, it is expected to now be shipped with
+	tarballs. Its initial goal was to be a host(1) clone,
+	rewritten in C++ from scratch and using BIND 10's libdns++.
+	It now supports the -a (any), -c class, -d (verbose) switches
+	and has improved output.
+	(Trac #872, git d846851699d5c76937533adf9ff9d948dfd593ca)
+
+227.	[build]		jreed
+	Add missing libdns++ rdata files for the distribution (this
+	fixes distcheck error). Change three generated libdns++
+	headers to "nodist" so they aren't included in the distribution
+	(they were mistakenly included in last tarball).
+
+226.	[func]*		jelte
+	Introduced an API for cryptographic operations. Currently it only
+	supports HMAC, intended for use with TSIG. The current
+	implementation uses Botan as the backend library.
+	This introduces a new dependency, on Botan.  Currently only Botan
+	1.8.x works; older or newer versions don't.
+	(Trac #781, git 9df42279a47eb617f586144dce8cce680598558a)
+
+225.	[func]		naokikambe
+	Added the HTTP/XML interface(b10-stats-httpd) to the
+	statistics feature in BIND 10. b10-stats-httpd is a standalone
+	HTTP server and it requests statistics data to the stats
+	daemon(b10-stats) and sends it to HTTP clients in XML
+	format. Items of the data collected via b10-stats-httpd
+	are almost equivalent to ones which are collected via
+	bindctl. Since it also can send XSL(Extensible Stylessheet
+	Language) document and XSD(XML Schema definition) document,
+	XML document is human-friendly to view through web browsers
+	and its data types are strictly defined.
+	(Trac #547, git 1cbd51919237a6e65983be46e4f5a63d1877b1d3)
+
+224.	[bug]		jinmei
+	b10-auth, src/lib/datasrc: inconsistency between the hot spot
+	cache and actual data source could cause a crash while query
+	processing.  The crash could happen, e.g., when an sqlite3 DB file
+	is being updated after a zone transfer while b10-auth handles a
+	query using the corresponding sqlite3 data source.
+	(Trac #851, git 2463b96680bb3e9a76e50c38a4d7f1d38d810643)
+
+223.	[bug]		feng
+	If ip address or port isn't usable for name server, name
+	server process won't exist and give end user chance to
+	reconfigure them.
+	(Trac #775, git 572ac2cf62e18f7eb69d670b890e2a3443bfd6e7)
+
+222.	[bug]		jerry
+	src/lib/zonemgr: Fix a bug that xfrin not checking for new copy of
+	zone on startup.  Imposes some random jitters to avoid many zones
+	need to do refresh at the same time.
+	(Trac #387, svn 9140fab9bab5f6502bd15d391fd51ac078b0b89b)
+
 221.	[func]*		jerry
 	src/lib/util: Create C++ utility library.
 	(Trac #749, git 084d1285d038d31067f8cdbb058d626acf03566d)
@@ -7,7 +97,7 @@
 	(potentially) bad packets to a nameserver and prints the responses.
 	(Trac #703, git 1b666838b6c0fe265522b30971e878d9f0d21fde)
 
-219.    [func]          ocean
+219.	[func]		ocean
 	src/lib: move some dns related code out of asiolink library to
 	asiodns library
 	(Trac #751, git 262ac6c6fc61224d54705ed4c700dadb606fcb1c)
@@ -17,9 +107,9 @@
 	(Trac #806, git 4e47d5f6b692c63c907af6681a75024450884a88)
 
 217.	[bug]		jerry
-	src/lib/dns/python: Use a signed version of larger size of integer and
-	perform more strict range checks with PyArg_ParseTuple() in case of
-	overflows.
+	src/lib/dns/python: Use a signed version of larger size of
+	integer and perform more strict range checks with
+	PyArg_ParseTuple() in case of overflows.
 	(Trac #363, git ce281e646be9f0f273229d94ccd75bf7e08d17cf)
 
 216.	[func]		vorner
@@ -1041,7 +1131,7 @@ bind10-devel-20100701 released on July 1, 2010
 55.	[bug]		shane
 	bin/xfrout: xfrout exception on Ctrl-C now no longer generates
 	exception for 'Interrupted system call'
-	(Track #136, svn r2147)
+	(Trac #136, svn r2147)
 
 54.	[bug]		zhanglikun
 	bin/xfrout: Enable b10-xfrout can be launched in source
diff --git a/Makefile.am b/Makefile.am
index e31a1a5..bab6679 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -84,214 +84,310 @@ systest:
 
 #### include external sources in the distributed tarball:
 EXTRA_DIST = ext/asio/README
-EXTRA_DIST += ext/asio/asio/local/stream_protocol.hpp
-EXTRA_DIST += ext/asio/asio/local/basic_endpoint.hpp
-EXTRA_DIST += ext/asio/asio/local/datagram_protocol.hpp
-EXTRA_DIST += ext/asio/asio/local/connect_pair.hpp
-EXTRA_DIST += ext/asio/asio/windows/basic_handle.hpp
-EXTRA_DIST += ext/asio/asio/windows/random_access_handle.hpp
-EXTRA_DIST += ext/asio/asio/windows/random_access_handle_service.hpp
-EXTRA_DIST += ext/asio/asio/windows/basic_random_access_handle.hpp
-EXTRA_DIST += ext/asio/asio/windows/overlapped_ptr.hpp
-EXTRA_DIST += ext/asio/asio/windows/stream_handle.hpp
-EXTRA_DIST += ext/asio/asio/windows/stream_handle_service.hpp
-EXTRA_DIST += ext/asio/asio/windows/basic_stream_handle.hpp
-EXTRA_DIST += ext/asio/asio/impl/write.ipp
-EXTRA_DIST += ext/asio/asio/impl/read.ipp
-EXTRA_DIST += ext/asio/asio/impl/serial_port_base.ipp
-EXTRA_DIST += ext/asio/asio/impl/write_at.ipp
-EXTRA_DIST += ext/asio/asio/impl/read_at.ipp
-EXTRA_DIST += ext/asio/asio/impl/error_code.ipp
-EXTRA_DIST += ext/asio/asio/impl/read_until.ipp
-EXTRA_DIST += ext/asio/asio/impl/io_service.ipp
-EXTRA_DIST += ext/asio/asio/detail/win_iocp_serial_port_service.hpp
-EXTRA_DIST += ext/asio/asio/detail/reactive_socket_service.hpp
-EXTRA_DIST += ext/asio/asio/detail/wince_thread.hpp
-EXTRA_DIST += ext/asio/asio/detail/win_event.hpp
-EXTRA_DIST += ext/asio/asio/detail/descriptor_ops.hpp
-EXTRA_DIST += ext/asio/asio/detail/pipe_select_interrupter.hpp
-EXTRA_DIST += ext/asio/asio/detail/task_io_service_fwd.hpp
-EXTRA_DIST += ext/asio/asio/detail/handler_alloc_helpers.hpp
-EXTRA_DIST += ext/asio/asio/detail/pop_options.hpp
-EXTRA_DIST += ext/asio/asio/detail/strand_service.hpp
-EXTRA_DIST += ext/asio/asio/detail/buffer_resize_guard.hpp
-EXTRA_DIST += ext/asio/asio/detail/win_iocp_io_service_fwd.hpp
-EXTRA_DIST += ext/asio/asio/detail/timer_scheduler.hpp
-EXTRA_DIST += ext/asio/asio/detail/kqueue_reactor_fwd.hpp
-EXTRA_DIST += ext/asio/asio/detail/hash_map.hpp
-EXTRA_DIST += ext/asio/asio/detail/event.hpp
-EXTRA_DIST += ext/asio/asio/detail/buffered_stream_storage.hpp
-EXTRA_DIST += ext/asio/asio/detail/posix_mutex.hpp
-EXTRA_DIST += ext/asio/asio/detail/timer_queue_fwd.hpp
-EXTRA_DIST += ext/asio/asio/detail/deadline_timer_service.hpp
-EXTRA_DIST += ext/asio/asio/detail/posix_fd_set_adapter.hpp
-EXTRA_DIST += ext/asio/asio/detail/service_registry.hpp
+EXTRA_DIST += ext/asio/README
+EXTRA_DIST += ext/asio/asio.hpp
+EXTRA_DIST += ext/asio/asio/basic_socket.hpp
+EXTRA_DIST += ext/asio/asio/streambuf.hpp
+EXTRA_DIST += ext/asio/asio/thread.hpp
+EXTRA_DIST += ext/asio/asio/detail/wait_handler.hpp
+EXTRA_DIST += ext/asio/asio/detail/resolve_op.hpp
+EXTRA_DIST += ext/asio/asio/detail/gcc_hppa_fenced_block.hpp
 EXTRA_DIST += ext/asio/asio/detail/null_fenced_block.hpp
+EXTRA_DIST += ext/asio/asio/detail/noncopyable.hpp
+EXTRA_DIST += ext/asio/asio/detail/eventfd_select_interrupter.hpp
 EXTRA_DIST += ext/asio/asio/detail/task_io_service_operation.hpp
-EXTRA_DIST += ext/asio/asio/detail/epoll_reactor.hpp
+EXTRA_DIST += ext/asio/asio/detail/service_base.hpp
+EXTRA_DIST += ext/asio/asio/detail/task_io_service_fwd.hpp
+EXTRA_DIST += ext/asio/asio/detail/null_buffers_op.hpp
+EXTRA_DIST += ext/asio/asio/detail/win_iocp_handle_write_op.hpp
+EXTRA_DIST += ext/asio/asio/detail/thread.hpp
+EXTRA_DIST += ext/asio/asio/detail/select_reactor_fwd.hpp
+EXTRA_DIST += ext/asio/asio/detail/event.hpp
+EXTRA_DIST += ext/asio/asio/detail/reactive_descriptor_service.hpp
+EXTRA_DIST += ext/asio/asio/detail/win_iocp_overlapped_op.hpp
+EXTRA_DIST += ext/asio/asio/detail/reactive_socket_recv_op.hpp
+EXTRA_DIST += ext/asio/asio/detail/macos_fenced_block.hpp
+EXTRA_DIST += ext/asio/asio/detail/dev_poll_reactor_fwd.hpp
+EXTRA_DIST += ext/asio/asio/detail/reactive_socket_service.hpp
+EXTRA_DIST += ext/asio/asio/detail/posix_tss_ptr.hpp
 EXTRA_DIST += ext/asio/asio/detail/local_free_on_block_exit.hpp
-EXTRA_DIST += ext/asio/asio/detail/socket_select_interrupter.hpp
-EXTRA_DIST += ext/asio/asio/detail/null_mutex.hpp
-EXTRA_DIST += ext/asio/asio/detail/reactor_op.hpp
-EXTRA_DIST += ext/asio/asio/detail/fenced_block.hpp
-EXTRA_DIST += ext/asio/asio/detail/tss_ptr.hpp
-EXTRA_DIST += ext/asio/asio/detail/timer_queue_set.hpp
-EXTRA_DIST += ext/asio/asio/detail/winsock_init.hpp
-EXTRA_DIST += ext/asio/asio/detail/signal_init.hpp
-EXTRA_DIST += ext/asio/asio/detail/call_stack.hpp
-EXTRA_DIST += ext/asio/asio/detail/operation.hpp
-EXTRA_DIST += ext/asio/asio/detail/posix_signal_blocker.hpp
-EXTRA_DIST += ext/asio/asio/detail/win_iocp_handle_service.hpp
-EXTRA_DIST += ext/asio/asio/detail/fd_set_adapter.hpp
-EXTRA_DIST += ext/asio/asio/detail/io_control.hpp
-EXTRA_DIST += ext/asio/asio/detail/null_signal_blocker.hpp
-EXTRA_DIST += ext/asio/asio/detail/socket_ops.hpp
-EXTRA_DIST += ext/asio/asio/detail/bind_handler.hpp
-EXTRA_DIST += ext/asio/asio/detail/win_iocp_overlapped_ptr.hpp
-EXTRA_DIST += ext/asio/asio/detail/timer_scheduler_fwd.hpp
+EXTRA_DIST += ext/asio/asio/detail/timer_scheduler.hpp
 EXTRA_DIST += ext/asio/asio/detail/signal_blocker.hpp
-EXTRA_DIST += ext/asio/asio/detail/consuming_buffers.hpp
-EXTRA_DIST += ext/asio/asio/detail/socket_option.hpp
-EXTRA_DIST += ext/asio/asio/detail/reactor.hpp
-EXTRA_DIST += ext/asio/asio/detail/win_fd_set_adapter.hpp
-EXTRA_DIST += ext/asio/asio/detail/select_interrupter.hpp
-EXTRA_DIST += ext/asio/asio/detail/null_buffers_op.hpp
+EXTRA_DIST += ext/asio/asio/detail/resolver_service_base.hpp
 EXTRA_DIST += ext/asio/asio/detail/socket_holder.hpp
-EXTRA_DIST += ext/asio/asio/detail/scoped_lock.hpp
-EXTRA_DIST += ext/asio/asio/detail/service_registry_fwd.hpp
-EXTRA_DIST += ext/asio/asio/detail/base_from_completion_cond.hpp
-EXTRA_DIST += ext/asio/asio/detail/posix_thread.hpp
-EXTRA_DIST += ext/asio/asio/detail/solaris_fenced_block.hpp
-EXTRA_DIST += ext/asio/asio/detail/epoll_reactor_fwd.hpp
-EXTRA_DIST += ext/asio/asio/detail/push_options.hpp
-EXTRA_DIST += ext/asio/asio/detail/win_signal_blocker.hpp
-EXTRA_DIST += ext/asio/asio/detail/eventfd_select_interrupter.hpp
+EXTRA_DIST += ext/asio/asio/detail/dev_poll_reactor.hpp
 EXTRA_DIST += ext/asio/asio/detail/select_reactor.hpp
-EXTRA_DIST += ext/asio/asio/detail/old_win_sdk_compat.hpp
+EXTRA_DIST += ext/asio/asio/detail/gcc_arm_fenced_block.hpp
+EXTRA_DIST += ext/asio/asio/detail/consuming_buffers.hpp
+EXTRA_DIST += ext/asio/asio/detail/reactor_op.hpp
+EXTRA_DIST += ext/asio/asio/detail/base_from_completion_cond.hpp
+EXTRA_DIST += ext/asio/asio/detail/epoll_reactor.hpp
+EXTRA_DIST += ext/asio/asio/detail/bind_handler.hpp
+EXTRA_DIST += ext/asio/asio/detail/strand_service.hpp
+EXTRA_DIST += ext/asio/asio/detail/op_queue.hpp
+EXTRA_DIST += ext/asio/asio/detail/win_mutex.hpp
+EXTRA_DIST += ext/asio/asio/detail/win_iocp_operation.hpp
+EXTRA_DIST += ext/asio/asio/detail/pipe_select_interrupter.hpp
+EXTRA_DIST += ext/asio/asio/detail/wince_thread.hpp
+EXTRA_DIST += ext/asio/asio/detail/buffered_stream_storage.hpp
+EXTRA_DIST += ext/asio/asio/detail/mutex.hpp
+EXTRA_DIST += ext/asio/asio/detail/posix_mutex.hpp
 EXTRA_DIST += ext/asio/asio/detail/reactor_op_queue.hpp
-EXTRA_DIST += ext/asio/asio/detail/null_thread.hpp
+EXTRA_DIST += ext/asio/asio/detail/win_event.hpp
+EXTRA_DIST += ext/asio/asio/detail/select_interrupter.hpp
+EXTRA_DIST += ext/asio/asio/detail/io_control.hpp
 EXTRA_DIST += ext/asio/asio/detail/buffer_sequence_adapter.hpp
-EXTRA_DIST += ext/asio/asio/detail/posix_event.hpp
-EXTRA_DIST += ext/asio/asio/detail/thread.hpp
-EXTRA_DIST += ext/asio/asio/detail/handler_invoke_helpers.hpp
+EXTRA_DIST += ext/asio/asio/detail/win_iocp_io_service.hpp
+EXTRA_DIST += ext/asio/asio/detail/win_iocp_handle_service.hpp
+EXTRA_DIST += ext/asio/asio/detail/win_iocp_socket_send_op.hpp
+EXTRA_DIST += ext/asio/asio/detail/epoll_reactor_fwd.hpp
+EXTRA_DIST += ext/asio/asio/detail/operation.hpp
+EXTRA_DIST += ext/asio/asio/detail/descriptor_ops.hpp
+EXTRA_DIST += ext/asio/asio/detail/reactor.hpp
+EXTRA_DIST += ext/asio/asio/detail/shared_ptr.hpp
+EXTRA_DIST += ext/asio/asio/detail/winsock_init.hpp
+EXTRA_DIST += ext/asio/asio/detail/timer_queue_set.hpp
+EXTRA_DIST += ext/asio/asio/detail/completion_handler.hpp
+EXTRA_DIST += ext/asio/asio/detail/reactive_serial_port_service.hpp
+EXTRA_DIST += ext/asio/asio/detail/fenced_block.hpp
 EXTRA_DIST += ext/asio/asio/detail/null_event.hpp
+EXTRA_DIST += ext/asio/asio/detail/hash_map.hpp
+EXTRA_DIST += ext/asio/asio/detail/gcc_sync_fenced_block.hpp
+EXTRA_DIST += ext/asio/asio/detail/win_tss_ptr.hpp
+EXTRA_DIST += ext/asio/asio/detail/win_fd_set_adapter.hpp
+EXTRA_DIST += ext/asio/asio/detail/win_iocp_null_buffers_op.hpp
+EXTRA_DIST += ext/asio/asio/detail/timer_queue_fwd.hpp
+EXTRA_DIST += ext/asio/asio/detail/old_win_sdk_compat.hpp
+EXTRA_DIST += ext/asio/asio/detail/call_stack.hpp
+EXTRA_DIST += ext/asio/asio/detail/weak_ptr.hpp
+EXTRA_DIST += ext/asio/asio/detail/win_iocp_socket_accept_op.hpp
+EXTRA_DIST += ext/asio/asio/detail/gcc_x86_fenced_block.hpp
+EXTRA_DIST += ext/asio/asio/detail/gcc_fenced_block.hpp
+EXTRA_DIST += ext/asio/asio/detail/win_iocp_socket_service.hpp
+EXTRA_DIST += ext/asio/asio/detail/null_mutex.hpp
+EXTRA_DIST += ext/asio/asio/detail/reactive_socket_recvfrom_op.hpp
+EXTRA_DIST += ext/asio/asio/detail/posix_event.hpp
 EXTRA_DIST += ext/asio/asio/detail/service_id.hpp
-EXTRA_DIST += ext/asio/asio/detail/socket_types.hpp
+EXTRA_DIST += ext/asio/asio/detail/kqueue_reactor.hpp
+EXTRA_DIST += ext/asio/asio/detail/regex_fwd.hpp
+EXTRA_DIST += ext/asio/asio/detail/reactive_socket_sendto_op.hpp
+EXTRA_DIST += ext/asio/asio/detail/push_options.hpp
+EXTRA_DIST += ext/asio/asio/detail/null_thread.hpp
+EXTRA_DIST += ext/asio/asio/detail/socket_select_interrupter.hpp
+EXTRA_DIST += ext/asio/asio/detail/win_iocp_socket_service_base.hpp
 EXTRA_DIST += ext/asio/asio/detail/throw_error.hpp
-EXTRA_DIST += ext/asio/asio/detail/timer_op.hpp
-EXTRA_DIST += ext/asio/asio/detail/win_mutex.hpp
-EXTRA_DIST += ext/asio/asio/detail/reactive_descriptor_service.hpp
-EXTRA_DIST += ext/asio/asio/detail/resolver_service.hpp
-EXTRA_DIST += ext/asio/asio/detail/op_queue.hpp
-EXTRA_DIST += ext/asio/asio/detail/dev_poll_reactor.hpp
-EXTRA_DIST += ext/asio/asio/detail/win_thread.hpp
-EXTRA_DIST += ext/asio/asio/detail/win_iocp_operation.hpp
-EXTRA_DIST += ext/asio/asio/detail/service_base.hpp
-EXTRA_DIST += ext/asio/asio/detail/select_reactor_fwd.hpp
-EXTRA_DIST += ext/asio/asio/detail/reactor_fwd.hpp
-EXTRA_DIST += ext/asio/asio/detail/win_iocp_socket_service.hpp
+EXTRA_DIST += ext/asio/asio/detail/null_signal_blocker.hpp
+EXTRA_DIST += ext/asio/asio/detail/reactive_socket_accept_op.hpp
 EXTRA_DIST += ext/asio/asio/detail/wrapped_handler.hpp
-EXTRA_DIST += ext/asio/asio/detail/mutex.hpp
-EXTRA_DIST += ext/asio/asio/detail/completion_handler.hpp
-EXTRA_DIST += ext/asio/asio/detail/noncopyable.hpp
-EXTRA_DIST += ext/asio/asio/detail/task_io_service.hpp
-EXTRA_DIST += ext/asio/asio/detail/gcc_fenced_block.hpp
+EXTRA_DIST += ext/asio/asio/detail/object_pool.hpp
+EXTRA_DIST += ext/asio/asio/detail/timer_scheduler_fwd.hpp
+EXTRA_DIST += ext/asio/asio/detail/resolve_endpoint_op.hpp
+EXTRA_DIST += ext/asio/asio/detail/array_fwd.hpp
+EXTRA_DIST += ext/asio/asio/detail/config.hpp
+EXTRA_DIST += ext/asio/asio/detail/socket_option.hpp
+EXTRA_DIST += ext/asio/asio/detail/win_iocp_overlapped_ptr.hpp
 EXTRA_DIST += ext/asio/asio/detail/win_fenced_block.hpp
-EXTRA_DIST += ext/asio/asio/detail/win_tss_ptr.hpp
-EXTRA_DIST += ext/asio/asio/detail/kqueue_reactor.hpp
+EXTRA_DIST += ext/asio/asio/detail/socket_types.hpp
+EXTRA_DIST += ext/asio/asio/detail/null_tss_ptr.hpp
+EXTRA_DIST += ext/asio/asio/detail/handler_invoke_helpers.hpp
+EXTRA_DIST += ext/asio/asio/detail/reactive_socket_send_op.hpp
+EXTRA_DIST += ext/asio/asio/detail/reactive_null_buffers_op.hpp
+EXTRA_DIST += ext/asio/asio/detail/pop_options.hpp
+EXTRA_DIST += ext/asio/asio/detail/resolver_service.hpp
+EXTRA_DIST += ext/asio/asio/detail/reactive_socket_service_base.hpp
+EXTRA_DIST += ext/asio/asio/detail/descriptor_read_op.hpp
+EXTRA_DIST += ext/asio/asio/detail/reactive_socket_connect_op.hpp
 EXTRA_DIST += ext/asio/asio/detail/timer_queue_base.hpp
-EXTRA_DIST += ext/asio/asio/detail/win_iocp_io_service.hpp
-EXTRA_DIST += ext/asio/asio/detail/gcc_x86_fenced_block.hpp
-EXTRA_DIST += ext/asio/asio/detail/posix_tss_ptr.hpp
-EXTRA_DIST += ext/asio/asio/detail/macos_fenced_block.hpp
-EXTRA_DIST += ext/asio/asio/detail/dev_poll_reactor_fwd.hpp
+EXTRA_DIST += ext/asio/asio/detail/reactor_fwd.hpp
+EXTRA_DIST += ext/asio/asio/detail/win_iocp_socket_recvfrom_op.hpp
+EXTRA_DIST += ext/asio/asio/detail/win_iocp_serial_port_service.hpp
+EXTRA_DIST += ext/asio/asio/detail/tss_ptr.hpp
+EXTRA_DIST += ext/asio/asio/detail/buffer_resize_guard.hpp
+EXTRA_DIST += ext/asio/asio/detail/kqueue_reactor_fwd.hpp
+EXTRA_DIST += ext/asio/asio/detail/win_thread.hpp
+EXTRA_DIST += ext/asio/asio/detail/deadline_timer_service.hpp
+EXTRA_DIST += ext/asio/asio/detail/win_iocp_socket_recv_op.hpp
+EXTRA_DIST += ext/asio/asio/detail/timer_op.hpp
+EXTRA_DIST += ext/asio/asio/detail/posix_thread.hpp
+EXTRA_DIST += ext/asio/asio/detail/signal_init.hpp
+EXTRA_DIST += ext/asio/asio/detail/descriptor_write_op.hpp
+EXTRA_DIST += ext/asio/asio/detail/win_signal_blocker.hpp
+EXTRA_DIST += ext/asio/asio/detail/impl/reactive_socket_service_base.ipp
+EXTRA_DIST += ext/asio/asio/detail/impl/win_mutex.ipp
+EXTRA_DIST += ext/asio/asio/detail/impl/posix_event.ipp
+EXTRA_DIST += ext/asio/asio/detail/impl/win_iocp_io_service.ipp
+EXTRA_DIST += ext/asio/asio/detail/impl/select_reactor.ipp
+EXTRA_DIST += ext/asio/asio/detail/impl/posix_tss_ptr.ipp
+EXTRA_DIST += ext/asio/asio/detail/impl/task_io_service.ipp
+EXTRA_DIST += ext/asio/asio/detail/impl/dev_poll_reactor.hpp
+EXTRA_DIST += ext/asio/asio/detail/impl/select_reactor.hpp
+EXTRA_DIST += ext/asio/asio/detail/impl/eventfd_select_interrupter.ipp
+EXTRA_DIST += ext/asio/asio/detail/impl/epoll_reactor.hpp
+EXTRA_DIST += ext/asio/asio/detail/impl/strand_service.hpp
+EXTRA_DIST += ext/asio/asio/detail/impl/winsock_init.ipp
+EXTRA_DIST += ext/asio/asio/detail/impl/pipe_select_interrupter.ipp
+EXTRA_DIST += ext/asio/asio/detail/impl/win_iocp_serial_port_service.ipp
+EXTRA_DIST += ext/asio/asio/detail/impl/dev_poll_reactor.ipp
+EXTRA_DIST += ext/asio/asio/detail/impl/win_iocp_io_service.hpp
+EXTRA_DIST += ext/asio/asio/detail/impl/strand_service.ipp
+EXTRA_DIST += ext/asio/asio/detail/impl/win_iocp_socket_service_base.ipp
+EXTRA_DIST += ext/asio/asio/detail/impl/timer_queue.ipp
+EXTRA_DIST += ext/asio/asio/detail/impl/posix_mutex.ipp
+EXTRA_DIST += ext/asio/asio/detail/impl/reactive_serial_port_service.ipp
+EXTRA_DIST += ext/asio/asio/detail/impl/socket_ops.ipp
+EXTRA_DIST += ext/asio/asio/detail/impl/socket_select_interrupter.ipp
+EXTRA_DIST += ext/asio/asio/detail/impl/posix_thread.ipp
+EXTRA_DIST += ext/asio/asio/detail/impl/reactive_descriptor_service.ipp
+EXTRA_DIST += ext/asio/asio/detail/impl/kqueue_reactor.hpp
+EXTRA_DIST += ext/asio/asio/detail/impl/kqueue_reactor.ipp
+EXTRA_DIST += ext/asio/asio/detail/impl/win_event.ipp
+EXTRA_DIST += ext/asio/asio/detail/impl/timer_queue_set.ipp
+EXTRA_DIST += ext/asio/asio/detail/impl/win_tss_ptr.ipp
+EXTRA_DIST += ext/asio/asio/detail/impl/win_iocp_handle_service.ipp
+EXTRA_DIST += ext/asio/asio/detail/impl/resolver_service_base.ipp
+EXTRA_DIST += ext/asio/asio/detail/impl/win_thread.ipp
+EXTRA_DIST += ext/asio/asio/detail/impl/task_io_service.hpp
+EXTRA_DIST += ext/asio/asio/detail/impl/throw_error.ipp
+EXTRA_DIST += ext/asio/asio/detail/impl/epoll_reactor.ipp
+EXTRA_DIST += ext/asio/asio/detail/impl/service_registry.hpp
+EXTRA_DIST += ext/asio/asio/detail/impl/descriptor_ops.ipp
+EXTRA_DIST += ext/asio/asio/detail/impl/service_registry.ipp
+EXTRA_DIST += ext/asio/asio/detail/win_iocp_io_service_fwd.hpp
+EXTRA_DIST += ext/asio/asio/detail/fd_set_adapter.hpp
+EXTRA_DIST += ext/asio/asio/detail/task_io_service.hpp
+EXTRA_DIST += ext/asio/asio/detail/solaris_fenced_block.hpp
 EXTRA_DIST += ext/asio/asio/detail/timer_queue.hpp
-EXTRA_DIST += ext/asio/asio/detail/reactive_serial_port_service.hpp
-EXTRA_DIST += ext/asio/asio/detail/null_tss_ptr.hpp
-EXTRA_DIST += ext/asio/asio/ssl/detail/openssl_stream_service.hpp
-EXTRA_DIST += ext/asio/asio/ssl/detail/openssl_operation.hpp
-EXTRA_DIST += ext/asio/asio/ssl/detail/openssl_init.hpp
-EXTRA_DIST += ext/asio/asio/ssl/detail/openssl_context_service.hpp
-EXTRA_DIST += ext/asio/asio/ssl/detail/openssl_types.hpp
-EXTRA_DIST += ext/asio/asio/ssl/stream.hpp
-EXTRA_DIST += ext/asio/asio/ssl/stream_service.hpp
+EXTRA_DIST += ext/asio/asio/detail/handler_alloc_helpers.hpp
+EXTRA_DIST += ext/asio/asio/detail/scoped_lock.hpp
+EXTRA_DIST += ext/asio/asio/detail/win_iocp_handle_read_op.hpp
+EXTRA_DIST += ext/asio/asio/detail/service_registry_fwd.hpp
+EXTRA_DIST += ext/asio/asio/detail/service_registry.hpp
+EXTRA_DIST += ext/asio/asio/detail/posix_fd_set_adapter.hpp
+EXTRA_DIST += ext/asio/asio/detail/socket_ops.hpp
+EXTRA_DIST += ext/asio/asio/detail/posix_signal_blocker.hpp
+EXTRA_DIST += ext/asio/asio/serial_port_base.hpp
 EXTRA_DIST += ext/asio/asio/ssl/context_base.hpp
 EXTRA_DIST += ext/asio/asio/ssl/context.hpp
 EXTRA_DIST += ext/asio/asio/ssl/context_service.hpp
+EXTRA_DIST += ext/asio/asio/ssl/detail/openssl_types.hpp
+EXTRA_DIST += ext/asio/asio/ssl/detail/openssl_context_service.hpp
+EXTRA_DIST += ext/asio/asio/ssl/detail/openssl_stream_service.hpp
+EXTRA_DIST += ext/asio/asio/ssl/detail/openssl_operation.hpp
+EXTRA_DIST += ext/asio/asio/ssl/detail/openssl_init.hpp
 EXTRA_DIST += ext/asio/asio/ssl/basic_context.hpp
+EXTRA_DIST += ext/asio/asio/ssl/stream_service.hpp
+EXTRA_DIST += ext/asio/asio/ssl/stream.hpp
 EXTRA_DIST += ext/asio/asio/ssl/stream_base.hpp
-EXTRA_DIST += ext/asio/asio/posix/stream_descriptor.hpp
-EXTRA_DIST += ext/asio/asio/posix/stream_descriptor_service.hpp
+EXTRA_DIST += ext/asio/asio/basic_streambuf.hpp
+EXTRA_DIST += ext/asio/asio/serial_port_service.hpp
+EXTRA_DIST += ext/asio/asio/error.hpp
+EXTRA_DIST += ext/asio/asio/handler_alloc_hook.hpp
+EXTRA_DIST += ext/asio/asio/buffers_iterator.hpp
+EXTRA_DIST += ext/asio/asio/is_read_buffered.hpp
+EXTRA_DIST += ext/asio/asio/buffered_stream_fwd.hpp
+EXTRA_DIST += ext/asio/asio/placeholders.hpp
+EXTRA_DIST += ext/asio/asio/local/stream_protocol.hpp
+EXTRA_DIST += ext/asio/asio/local/detail/impl/endpoint.ipp
+EXTRA_DIST += ext/asio/asio/local/detail/endpoint.hpp
+EXTRA_DIST += ext/asio/asio/local/datagram_protocol.hpp
+EXTRA_DIST += ext/asio/asio/local/connect_pair.hpp
+EXTRA_DIST += ext/asio/asio/local/basic_endpoint.hpp
+EXTRA_DIST += ext/asio/asio/buffered_stream.hpp
+EXTRA_DIST += ext/asio/asio/basic_serial_port.hpp
+EXTRA_DIST += ext/asio/asio/datagram_socket_service.hpp
+EXTRA_DIST += ext/asio/asio/socket_base.hpp
+EXTRA_DIST += ext/asio/asio/io_service.hpp
+EXTRA_DIST += ext/asio/asio/ssl.hpp
+EXTRA_DIST += ext/asio/asio/basic_socket_iostream.hpp
+EXTRA_DIST += ext/asio/asio/basic_io_object.hpp
+EXTRA_DIST += ext/asio/asio/basic_socket_streambuf.hpp
+EXTRA_DIST += ext/asio/asio/error_code.hpp
+EXTRA_DIST += ext/asio/asio/basic_stream_socket.hpp
+EXTRA_DIST += ext/asio/asio/read_until.hpp
+EXTRA_DIST += ext/asio/asio/basic_streambuf_fwd.hpp
+EXTRA_DIST += ext/asio/asio/is_write_buffered.hpp
+EXTRA_DIST += ext/asio/asio/basic_datagram_socket.hpp
+EXTRA_DIST += ext/asio/asio/buffered_write_stream_fwd.hpp
+EXTRA_DIST += ext/asio/asio/basic_deadline_timer.hpp
+EXTRA_DIST += ext/asio/asio/socket_acceptor_service.hpp
+EXTRA_DIST += ext/asio/asio/raw_socket_service.hpp
+EXTRA_DIST += ext/asio/asio/buffered_read_stream.hpp
+EXTRA_DIST += ext/asio/asio/time_traits.hpp
+EXTRA_DIST += ext/asio/asio/completion_condition.hpp
 EXTRA_DIST += ext/asio/asio/posix/basic_stream_descriptor.hpp
 EXTRA_DIST += ext/asio/asio/posix/basic_descriptor.hpp
 EXTRA_DIST += ext/asio/asio/posix/descriptor_base.hpp
+EXTRA_DIST += ext/asio/asio/posix/stream_descriptor_service.hpp
+EXTRA_DIST += ext/asio/asio/posix/stream_descriptor.hpp
+EXTRA_DIST += ext/asio/asio/write.hpp
+EXTRA_DIST += ext/asio/asio/write_at.hpp
+EXTRA_DIST += ext/asio/asio/basic_raw_socket.hpp
+EXTRA_DIST += ext/asio/asio/serial_port.hpp
+EXTRA_DIST += ext/asio/asio/windows/basic_stream_handle.hpp
+EXTRA_DIST += ext/asio/asio/windows/basic_handle.hpp
+EXTRA_DIST += ext/asio/asio/windows/random_access_handle.hpp
+EXTRA_DIST += ext/asio/asio/windows/overlapped_ptr.hpp
+EXTRA_DIST += ext/asio/asio/windows/stream_handle.hpp
+EXTRA_DIST += ext/asio/asio/windows/random_access_handle_service.hpp
+EXTRA_DIST += ext/asio/asio/windows/stream_handle_service.hpp
+EXTRA_DIST += ext/asio/asio/windows/basic_random_access_handle.hpp
+EXTRA_DIST += ext/asio/asio/read.hpp
+EXTRA_DIST += ext/asio/asio/deadline_timer_service.hpp
+EXTRA_DIST += ext/asio/asio/buffered_write_stream.hpp
+EXTRA_DIST += ext/asio/asio/buffer.hpp
+EXTRA_DIST += ext/asio/asio/impl/read_until.ipp
+EXTRA_DIST += ext/asio/asio/impl/serial_port_base.hpp
+EXTRA_DIST += ext/asio/asio/impl/read_at.ipp
+EXTRA_DIST += ext/asio/asio/impl/read.ipp
+EXTRA_DIST += ext/asio/asio/impl/error.ipp
+EXTRA_DIST += ext/asio/asio/impl/io_service.ipp
+EXTRA_DIST += ext/asio/asio/impl/io_service.hpp
+EXTRA_DIST += ext/asio/asio/impl/src.hpp
+EXTRA_DIST += ext/asio/asio/impl/src.cpp
+EXTRA_DIST += ext/asio/asio/impl/read_until.hpp
+EXTRA_DIST += ext/asio/asio/impl/serial_port_base.ipp
+EXTRA_DIST += ext/asio/asio/impl/write.hpp
+EXTRA_DIST += ext/asio/asio/impl/write_at.hpp
+EXTRA_DIST += ext/asio/asio/impl/write.ipp
+EXTRA_DIST += ext/asio/asio/impl/read.hpp
+EXTRA_DIST += ext/asio/asio/impl/write_at.ipp
+EXTRA_DIST += ext/asio/asio/impl/error_code.ipp
+EXTRA_DIST += ext/asio/asio/impl/read_at.hpp
+EXTRA_DIST += ext/asio/asio/strand.hpp
+EXTRA_DIST += ext/asio/asio/version.hpp
+EXTRA_DIST += ext/asio/asio/basic_socket_acceptor.hpp
+EXTRA_DIST += ext/asio/asio/ip/basic_resolver_query.hpp
+EXTRA_DIST += ext/asio/asio/ip/address.hpp
+EXTRA_DIST += ext/asio/asio/ip/host_name.hpp
 EXTRA_DIST += ext/asio/asio/ip/detail/socket_option.hpp
+EXTRA_DIST += ext/asio/asio/ip/detail/impl/endpoint.ipp
+EXTRA_DIST += ext/asio/asio/ip/detail/endpoint.hpp
+EXTRA_DIST += ext/asio/asio/ip/udp.hpp
+EXTRA_DIST += ext/asio/asio/ip/basic_resolver_iterator.hpp
 EXTRA_DIST += ext/asio/asio/ip/v6_only.hpp
 EXTRA_DIST += ext/asio/asio/ip/address_v4.hpp
-EXTRA_DIST += ext/asio/asio/ip/address_v6.hpp
-EXTRA_DIST += ext/asio/asio/ip/basic_resolver.hpp
+EXTRA_DIST += ext/asio/asio/ip/resolver_query_base.hpp
 EXTRA_DIST += ext/asio/asio/ip/multicast.hpp
+EXTRA_DIST += ext/asio/asio/ip/address_v6.hpp
+EXTRA_DIST += ext/asio/asio/ip/tcp.hpp
+EXTRA_DIST += ext/asio/asio/ip/basic_resolver_entry.hpp
 EXTRA_DIST += ext/asio/asio/ip/unicast.hpp
-EXTRA_DIST += ext/asio/asio/ip/basic_resolver_iterator.hpp
-EXTRA_DIST += ext/asio/asio/ip/host_name.hpp
-EXTRA_DIST += ext/asio/asio/ip/resolver_query_base.hpp
-EXTRA_DIST += ext/asio/asio/ip/basic_endpoint.hpp
 EXTRA_DIST += ext/asio/asio/ip/resolver_service.hpp
-EXTRA_DIST += ext/asio/asio/ip/basic_resolver_entry.hpp
-EXTRA_DIST += ext/asio/asio/ip/address.hpp
-EXTRA_DIST += ext/asio/asio/ip/tcp.hpp
-EXTRA_DIST += ext/asio/asio/ip/basic_resolver_query.hpp
-EXTRA_DIST += ext/asio/asio/ip/udp.hpp
 EXTRA_DIST += ext/asio/asio/ip/icmp.hpp
-EXTRA_DIST += ext/asio/asio/error.hpp
-EXTRA_DIST += ext/asio/asio/basic_socket.hpp
-EXTRA_DIST += ext/asio/asio/buffered_stream.hpp
-EXTRA_DIST += ext/asio/asio/system_error.hpp
-EXTRA_DIST += ext/asio/asio/basic_io_object.hpp
-EXTRA_DIST += ext/asio/asio/read_at.hpp
-EXTRA_DIST += ext/asio/asio/basic_raw_socket.hpp
-EXTRA_DIST += ext/asio/asio/serial_port_service.hpp
-EXTRA_DIST += ext/asio/asio/basic_stream_socket.hpp
-EXTRA_DIST += ext/asio/asio/placeholders.hpp
-EXTRA_DIST += ext/asio/asio/basic_deadline_timer.hpp
-EXTRA_DIST += ext/asio/asio/thread.hpp
-EXTRA_DIST += ext/asio/asio/buffered_write_stream_fwd.hpp
-EXTRA_DIST += ext/asio/asio/datagram_socket_service.hpp
+EXTRA_DIST += ext/asio/asio/ip/basic_endpoint.hpp
+EXTRA_DIST += ext/asio/asio/ip/basic_resolver.hpp
+EXTRA_DIST += ext/asio/asio/ip/impl/address.hpp
+EXTRA_DIST += ext/asio/asio/ip/impl/address_v4.hpp
+EXTRA_DIST += ext/asio/asio/ip/impl/address_v4.ipp
+EXTRA_DIST += ext/asio/asio/ip/impl/address_v6.hpp
+EXTRA_DIST += ext/asio/asio/ip/impl/address.ipp
+EXTRA_DIST += ext/asio/asio/ip/impl/host_name.ipp
+EXTRA_DIST += ext/asio/asio/ip/impl/basic_endpoint.hpp
+EXTRA_DIST += ext/asio/asio/ip/impl/address_v6.ipp
 EXTRA_DIST += ext/asio/asio/handler_invoke_hook.hpp
-EXTRA_DIST += ext/asio/asio/is_read_buffered.hpp
-EXTRA_DIST += ext/asio/asio/buffer.hpp
-EXTRA_DIST += ext/asio/asio/basic_socket_acceptor.hpp
-EXTRA_DIST += ext/asio/asio/write_at.hpp
-EXTRA_DIST += ext/asio/asio/completion_condition.hpp
-EXTRA_DIST += ext/asio/asio/raw_socket_service.hpp
-EXTRA_DIST += ext/asio/asio/socket_base.hpp
-EXTRA_DIST += ext/asio/asio/serial_port.hpp
-EXTRA_DIST += ext/asio/asio/error_code.hpp
-EXTRA_DIST += ext/asio/asio/basic_serial_port.hpp
-EXTRA_DIST += ext/asio/asio/version.hpp
-EXTRA_DIST += ext/asio/asio/deadline_timer_service.hpp
-EXTRA_DIST += ext/asio/asio/io_service.hpp
-EXTRA_DIST += ext/asio/asio/buffered_read_stream.hpp
-EXTRA_DIST += ext/asio/asio/streambuf.hpp
-EXTRA_DIST += ext/asio/asio/basic_datagram_socket.hpp
-EXTRA_DIST += ext/asio/asio/basic_streambuf.hpp
-EXTRA_DIST += ext/asio/asio/write.hpp
-EXTRA_DIST += ext/asio/asio/strand.hpp
-EXTRA_DIST += ext/asio/asio/basic_socket_iostream.hpp
-EXTRA_DIST += ext/asio/asio/buffered_stream_fwd.hpp
-EXTRA_DIST += ext/asio/asio/basic_socket_streambuf.hpp
-EXTRA_DIST += ext/asio/asio/ssl.hpp
+EXTRA_DIST += ext/asio/asio/read_at.hpp
+EXTRA_DIST += ext/asio/asio/buffered_read_stream_fwd.hpp
+EXTRA_DIST += ext/asio/asio/system_error.hpp
 EXTRA_DIST += ext/asio/asio/deadline_timer.hpp
-EXTRA_DIST += ext/asio/asio/buffers_iterator.hpp
-EXTRA_DIST += ext/asio/asio/handler_alloc_hook.hpp
-EXTRA_DIST += ext/asio/asio/buffered_write_stream.hpp
-EXTRA_DIST += ext/asio/asio/read.hpp
-EXTRA_DIST += ext/asio/asio/serial_port_base.hpp
 EXTRA_DIST += ext/asio/asio/stream_socket_service.hpp
-EXTRA_DIST += ext/asio/asio/time_traits.hpp
-EXTRA_DIST += ext/asio/asio/read_until.hpp
-EXTRA_DIST += ext/asio/asio/is_write_buffered.hpp
-EXTRA_DIST += ext/asio/asio/buffered_read_stream_fwd.hpp
-EXTRA_DIST += ext/asio/asio/socket_acceptor_service.hpp
-EXTRA_DIST += ext/asio/asio.hpp
 EXTRA_DIST += ext/coroutine/coroutine.h
diff --git a/configure.ac b/configure.ac
index 81df476..d76500d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -374,6 +374,79 @@ if test "$lcov" != "no"; then
 fi
 AC_SUBST(USE_LCOV)
 
+# Check for Botan
+botan_path="yes"
+AC_ARG_WITH([botan],
+  AC_HELP_STRING([--with-botan=PATH],
+    [specify exact directory of Botan library]),
+    [botan_path="$withval"])
+if test "${botan_path}" == "no" ; then
+    AC_MSG_ERROR([Need botan for libcryptolink])
+fi
+if test "${botan_path}" != "yes" ; then
+    if test -x "${botan_path}/bin/botan-config" ; then
+        BOTAN_CONFIG="${botan_path}/bin/botan-config"
+    else
+        AC_MSG_ERROR([${botan_path}/bin/botan-config not found])
+    fi
+else
+        AC_PATH_PROG([BOTAN_CONFIG], [botan-config])
+fi
+
+if test -x "${BOTAN_CONFIG}" ; then
+    BOTAN_LDFLAGS=`${BOTAN_CONFIG} --libs`
+    # We expect botan-config --libs to contain -L<path_to_libbotan>, but
+    # this is not always the case.  As a heuristics workaround we add
+    # -L`botan-config --prefix/lib` in this case.  Same for BOTAN_INCLUDES
+    # (but using include instead of lib) below.
+    echo ${BOTAN_LDFLAGS} | grep -- -L > /dev/null || \
+	    BOTAN_LDFLAGS="-L`${BOTAN_CONFIG} --prefix`/lib ${BOTAN_LDFLAGS}"
+    BOTAN_INCLUDES=`${BOTAN_CONFIG} --cflags`
+    echo ${BOTAN_INCLUDES} | grep -- -I > /dev/null || \
+	    BOTAN_INCLUDES="-I`${BOTAN_CONFIG} --prefix`/include ${BOTAN_INCLUDES}"
+    # See python_rpath for some info on why we do this
+    if test $rpath_available = yes; then
+        BOTAN_RPATH=
+        for flag in ${BOTAN_LDFLAGS}; do
+                BOTAN_RPATH="${BOTAN_RPATH} `echo $flag | sed -ne 's/^\(\-L\)/-R/p'`"
+        done
+	AC_SUBST(BOTAN_RPATH)
+
+	# According to the libtool manual, it should be sufficient if we
+	# specify the "-R libdir" in our wrapper library of botan (no other
+	# programs will need libbotan directly); "libdir" should be added to
+	# the program's binary image.  But we've seen in our build environments
+	# that (some versions of?) libtool doesn't propagate -R as documented,
+	# and it caused a linker error at run time.  To work around this, we
+	# also add the rpath to the global LDFLAGS.
+        LDFLAGS="$BOTAN_RPATH $LDFLAGS"
+    fi
+
+    AC_SUBST(BOTAN_LDFLAGS)
+    AC_SUBST(BOTAN_INCLUDES)
+fi
+
+CPPFLAGS_SAVED=$CPPFLAGS
+CPPFLAGS="$BOTAN_INCLUDES $CPPFLAGS"
+LDFLAGS_SAVED="$LDFLAGS"
+LDFLAGS="$BOTAN_LDFLAGS $LDFLAGS"
+
+AC_CHECK_HEADERS([botan/botan.h],,AC_MSG_ERROR([Missing required header files.]))
+AC_LINK_IFELSE(
+        [AC_LANG_PROGRAM([#include <botan/botan.h>
+                          #include <botan/hash.h>
+                         ],
+                         [using namespace Botan;
+                          LibraryInitializer::initialize();
+                          HashFunction *h = get_hash("MD5");
+                         ])],
+        [AC_MSG_RESULT([checking for Botan library... yes])],
+        [AC_MSG_RESULT([checking for Botan library... no])
+         AC_MSG_ERROR([Needs Botan library 1.8 or higher])]
+)
+CPPFLAGS=$CPPFLAGS_SAVED
+LDFLAGS=$LDFLAGS_SAVED
+
 #
 # Configure Boost header path
 #
@@ -640,6 +713,7 @@ AC_CONFIG_FILES([Makefile
                  src/bin/stats/tests/isc/config/Makefile
                  src/bin/stats/tests/isc/util/Makefile
                  src/bin/stats/tests/testdata/Makefile
+                 src/bin/stats/tests/http/Makefile
                  src/bin/usermgr/Makefile
                  src/bin/tests/Makefile
                  src/lib/Makefile
@@ -672,11 +746,8 @@ AC_CONFIG_FILES([Makefile
                  src/lib/config/Makefile
                  src/lib/config/tests/Makefile
                  src/lib/config/tests/testdata/Makefile
-                 src/lib/util/Makefile
-                 src/lib/util/io/Makefile
-                 src/lib/util/io/tests/Makefile
-                 src/lib/util/unittests/Makefile
-                 src/lib/util/tests/Makefile
+                 src/lib/cryptolink/Makefile
+                 src/lib/cryptolink/tests/Makefile
                  src/lib/dns/Makefile
                  src/lib/dns/tests/Makefile
                  src/lib/dns/tests/testdata/Makefile
@@ -701,6 +772,11 @@ AC_CONFIG_FILES([Makefile
                  src/lib/cache/tests/Makefile
                  src/lib/server_common/Makefile
                  src/lib/server_common/tests/Makefile
+                 src/lib/util/Makefile
+                 src/lib/util/io/Makefile
+                 src/lib/util/io/tests/Makefile
+                 src/lib/util/unittests/Makefile
+                 src/lib/util/tests/Makefile
                  tests/Makefile
                  tests/system/Makefile
                  tests/tools/Makefile
@@ -729,11 +805,12 @@ AC_OUTPUT([doc/version.ent
            src/bin/zonemgr/tests/zonemgr_test
            src/bin/zonemgr/run_b10-zonemgr.sh
            src/bin/stats/stats.py
-           src/bin/stats/stats_stub.py
-           src/bin/stats/stats.spec.pre
-           src/bin/stats/run_b10-stats.sh
-           src/bin/stats/run_b10-stats_stub.sh
-           src/bin/stats/tests/stats_test
+           src/bin/stats/stats_httpd.py
+           src/bin/stats/stats.spec
+           src/bin/stats/stats-httpd.spec
+           src/bin/stats/stats-httpd-xml.tpl
+           src/bin/stats/stats-httpd-xsd.tpl
+           src/bin/stats/stats-httpd-xsl.tpl
            src/bin/bind10/bind10.py
            src/bin/bind10/run_bind10.sh
            src/bin/bind10/tests/bind10_test.py
@@ -772,9 +849,6 @@ AC_OUTPUT([doc/version.ent
            chmod +x src/bin/xfrin/run_b10-xfrin.sh
            chmod +x src/bin/xfrout/run_b10-xfrout.sh
            chmod +x src/bin/zonemgr/run_b10-zonemgr.sh
-           chmod +x src/bin/stats/tests/stats_test
-           chmod +x src/bin/stats/run_b10-stats.sh
-           chmod +x src/bin/stats/run_b10-stats_stub.sh
            chmod +x src/bin/bind10/run_bind10.sh
            chmod +x src/bin/cmdctl/tests/cmdctl_test
            chmod +x src/bin/xfrin/tests/xfrin_test
@@ -813,12 +887,15 @@ Flags:
   DEFS:          $DEFS
   CPPFLAGS:      $CPPFLAGS
   CXXFLAGS:      $CXXFLAGS
+  LDFLAGS:       $LDFLAGS
   B10_CXXFLAGS:  $B10_CXXFLAGS
 dnl includes too
   Python:        ${PYTHON_INCLUDES}
                  ${PYTHON_LDFLAGS}
                  ${PYTHON_LIB}
   Boost:         ${BOOST_INCLUDES}
+  Botan:         ${BOTAN_INCLUDES}
+                 ${BOTAN_LDFLAGS}
   SQLite:        $SQLITE_CFLAGS
                  $SQLITE_LIBS
 
diff --git a/doc/Doxyfile b/doc/Doxyfile
index 5b609ad..783e63a 100644
--- a/doc/Doxyfile
+++ b/doc/Doxyfile
@@ -568,11 +568,12 @@ WARN_LOGFILE           =
 # directories like "/usr/src/myproject". Separate the files or directories
 # with spaces.
 
-INPUT                  = ../src/lib/cc ../src/lib/config ../src/lib/dns \
-    ../src/lib/exceptions ../src/lib/datasrc ../src/bin/auth \
-    ../src/bin/resolver ../src/lib/bench ../src/lib/log ../src/lib/asiolink/ \
-    ../src/lib/nsas ../src/lib/testutils ../src/lib/cache \
-    ../src/lib/server_common/ ../src/bin/sockcreator/ ../src/lib/util/ \
+INPUT                  = ../src/lib/cc ../src/lib/config \
+    ../src/lib/cryptolink ../src/lib/dns ../src/lib/datasrc \
+    ../src/bin/auth ../src/bin/resolver ../src/lib/bench \
+    ../src/lib/log ../src/lib/asiolink/ ../src/lib/nsas \
+    ../src/lib/testutils ../src/lib/cache ../src/lib/server_common/ \
+    ../src/bin/sockcreator/ ../src/lib/util/
     ../src/lib/resolve
 
 # This tag can be used to specify the character encoding of the source files
diff --git a/ext/asio/README b/ext/asio/README
index c581e8e..da12a9d 100644
--- a/ext/asio/README
+++ b/ext/asio/README
@@ -1,5 +1,10 @@
 ASIO library header files
-Version 1.4.5 (2010-05-12)
+Version 1.4.8 (2011-04-19)
 Downloaded from http://sourceforge.net/projects/asio/files
 Project page: http://think-async.com/Asio
-No local modifications.
+
+Local modifications:
+Added ASIO_DECL to a number of function definitions
+git commit c32718be9f5409b6f72d98ddcd0b1ccd4c5c2293
+See also the bug report at:
+http://sourceforge.net/tracker/?func=detail&aid=3291113&group_id=122478&atid=694037
diff --git a/ext/asio/asio.hpp b/ext/asio/asio.hpp
index d8acd58..b0ebc96 100644
--- a/ext/asio/asio.hpp
+++ b/ext/asio/asio.hpp
@@ -2,7 +2,7 @@
 // asio.hpp
 // ~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/ext/asio/asio/basic_datagram_socket.hpp b/ext/asio/asio/basic_datagram_socket.hpp
index cb149f9..2cbb354 100644
--- a/ext/asio/asio/basic_datagram_socket.hpp
+++ b/ext/asio/asio/basic_datagram_socket.hpp
@@ -2,7 +2,7 @@
 // basic_datagram_socket.hpp
 // ~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,17 +15,14 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 #include <cstddef>
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
-
 #include "asio/basic_socket.hpp"
 #include "asio/datagram_socket_service.hpp"
-#include "asio/error.hpp"
 #include "asio/detail/throw_error.hpp"
+#include "asio/error.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 
diff --git a/ext/asio/asio/basic_deadline_timer.hpp b/ext/asio/asio/basic_deadline_timer.hpp
index 0d183f7..27781e7 100644
--- a/ext/asio/asio/basic_deadline_timer.hpp
+++ b/ext/asio/asio/basic_deadline_timer.hpp
@@ -2,7 +2,7 @@
 // basic_deadline_timer.hpp
 // ~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,17 +15,14 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 #include <cstddef>
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
-
 #include "asio/basic_io_object.hpp"
 #include "asio/deadline_timer_service.hpp"
-#include "asio/error.hpp"
 #include "asio/detail/throw_error.hpp"
+#include "asio/error.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 
diff --git a/ext/asio/asio/basic_io_object.hpp b/ext/asio/asio/basic_io_object.hpp
index 092170d..da35462 100644
--- a/ext/asio/asio/basic_io_object.hpp
+++ b/ext/asio/asio/basic_io_object.hpp
@@ -2,7 +2,7 @@
 // basic_io_object.hpp
 // ~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,10 +15,11 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/io_service.hpp"
+#include "asio/detail/config.hpp"
 #include "asio/detail/noncopyable.hpp"
+#include "asio/io_service.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 
diff --git a/ext/asio/asio/basic_raw_socket.hpp b/ext/asio/asio/basic_raw_socket.hpp
index 9d93b97..7a55c4a 100644
--- a/ext/asio/asio/basic_raw_socket.hpp
+++ b/ext/asio/asio/basic_raw_socket.hpp
@@ -2,7 +2,7 @@
 // basic_raw_socket.hpp
 // ~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,17 +15,14 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 #include <cstddef>
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
-
 #include "asio/basic_socket.hpp"
-#include "asio/raw_socket_service.hpp"
-#include "asio/error.hpp"
 #include "asio/detail/throw_error.hpp"
+#include "asio/error.hpp"
+#include "asio/raw_socket_service.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 
diff --git a/ext/asio/asio/basic_serial_port.hpp b/ext/asio/asio/basic_serial_port.hpp
index edb7bb0..38fe5e9 100644
--- a/ext/asio/asio/basic_serial_port.hpp
+++ b/ext/asio/asio/basic_serial_port.hpp
@@ -2,7 +2,7 @@
 // basic_serial_port.hpp
 // ~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 // Copyright (c) 2008 Rep Invariant Systems, Inc. (info at repinvariant.com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
@@ -16,21 +16,19 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 
-#include "asio/detail/push_options.hpp"
-#include <string>
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
+#if defined(ASIO_HAS_SERIAL_PORT) \
+  || defined(GENERATING_DOCUMENTATION)
 
+#include <string>
 #include "asio/basic_io_object.hpp"
+#include "asio/detail/throw_error.hpp"
 #include "asio/error.hpp"
 #include "asio/serial_port_base.hpp"
 #include "asio/serial_port_service.hpp"
-#include "asio/detail/throw_error.hpp"
 
-#if defined(ASIO_HAS_SERIAL_PORT) \
-  || defined(GENERATING_DOCUMENTATION)
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 
@@ -614,9 +612,9 @@ public:
 
 } // namespace asio
 
+#include "asio/detail/pop_options.hpp"
+
 #endif // defined(ASIO_HAS_SERIAL_PORT)
        //   || defined(GENERATING_DOCUMENTATION)
 
-#include "asio/detail/pop_options.hpp"
-
 #endif // ASIO_BASIC_SERIAL_PORT_HPP
diff --git a/ext/asio/asio/basic_socket.hpp b/ext/asio/asio/basic_socket.hpp
index 8b3f1d7..5c66b4a 100644
--- a/ext/asio/asio/basic_socket.hpp
+++ b/ext/asio/asio/basic_socket.hpp
@@ -2,7 +2,7 @@
 // basic_socket.hpp
 // ~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,16 +15,13 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
-
+#include "asio/detail/config.hpp"
 #include "asio/basic_io_object.hpp"
+#include "asio/detail/throw_error.hpp"
 #include "asio/error.hpp"
 #include "asio/socket_base.hpp"
-#include "asio/detail/throw_error.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 
diff --git a/ext/asio/asio/basic_socket_acceptor.hpp b/ext/asio/asio/basic_socket_acceptor.hpp
index 97fa56b..15f9220 100644
--- a/ext/asio/asio/basic_socket_acceptor.hpp
+++ b/ext/asio/asio/basic_socket_acceptor.hpp
@@ -2,7 +2,7 @@
 // basic_socket_acceptor.hpp
 // ~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,14 +15,15 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
+#include "asio/detail/config.hpp"
 #include "asio/basic_io_object.hpp"
 #include "asio/basic_socket.hpp"
+#include "asio/detail/throw_error.hpp"
 #include "asio/error.hpp"
 #include "asio/socket_acceptor_service.hpp"
 #include "asio/socket_base.hpp"
-#include "asio/detail/throw_error.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 
diff --git a/ext/asio/asio/basic_socket_iostream.hpp b/ext/asio/asio/basic_socket_iostream.hpp
index 361ecb8..efcd51e 100644
--- a/ext/asio/asio/basic_socket_iostream.hpp
+++ b/ext/asio/asio/basic_socket_iostream.hpp
@@ -2,7 +2,7 @@
 // basic_socket_iostream.hpp
 // ~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,22 +15,15 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
+#include "asio/detail/config.hpp"
 
 #if !defined(BOOST_NO_IOSTREAM)
 
-#include "asio/detail/push_options.hpp"
 #include <boost/preprocessor/arithmetic/inc.hpp>
 #include <boost/preprocessor/repetition/enum_binary_params.hpp>
 #include <boost/preprocessor/repetition/enum_params.hpp>
 #include <boost/preprocessor/repetition/repeat_from_to.hpp>
 #include <boost/utility/base_from_member.hpp>
-#include "asio/detail/pop_options.hpp"
-
 #include "asio/basic_socket_streambuf.hpp"
 #include "asio/stream_socket_service.hpp"
 
@@ -79,6 +72,8 @@
   } \
   /**/
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 
 /// Iostream interface for a socket.
@@ -146,11 +141,11 @@ public:
 
 } // namespace asio
 
+#include "asio/detail/pop_options.hpp"
+
 #undef ASIO_PRIVATE_CTR_DEF
 #undef ASIO_PRIVATE_CONNECT_DEF
 
 #endif // defined(BOOST_NO_IOSTREAM)
 
-#include "asio/detail/pop_options.hpp"
-
 #endif // ASIO_BASIC_SOCKET_IOSTREAM_HPP
diff --git a/ext/asio/asio/basic_socket_streambuf.hpp b/ext/asio/asio/basic_socket_streambuf.hpp
index ae0264e..05fc865 100644
--- a/ext/asio/asio/basic_socket_streambuf.hpp
+++ b/ext/asio/asio/basic_socket_streambuf.hpp
@@ -2,7 +2,7 @@
 // basic_socket_streambuf.hpp
 // ~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,15 +15,10 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
+#include "asio/detail/config.hpp"
 
 #if !defined(BOOST_NO_IOSTREAM)
 
-#include "asio/detail/push_options.hpp"
 #include <streambuf>
 #include <boost/array.hpp>
 #include <boost/preprocessor/arithmetic/inc.hpp>
@@ -31,12 +26,10 @@
 #include <boost/preprocessor/repetition/enum_params.hpp>
 #include <boost/preprocessor/repetition/repeat_from_to.hpp>
 #include <boost/utility/base_from_member.hpp>
-#include "asio/detail/pop_options.hpp"
-
 #include "asio/basic_socket.hpp"
+#include "asio/detail/throw_error.hpp"
 #include "asio/io_service.hpp"
 #include "asio/stream_socket_service.hpp"
-#include "asio/detail/throw_error.hpp"
 
 #if !defined(ASIO_SOCKET_STREAMBUF_MAX_ARITY)
 #define ASIO_SOCKET_STREAMBUF_MAX_ARITY 5
@@ -74,6 +67,8 @@
   } \
   /**/
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 
 /// Iostream streambuf for a socket.
@@ -286,10 +281,10 @@ private:
 
 } // namespace asio
 
+#include "asio/detail/pop_options.hpp"
+
 #undef ASIO_PRIVATE_CONNECT_DEF
 
 #endif // !defined(BOOST_NO_IOSTREAM)
 
-#include "asio/detail/pop_options.hpp"
-
 #endif // ASIO_BASIC_SOCKET_STREAMBUF_HPP
diff --git a/ext/asio/asio/basic_stream_socket.hpp b/ext/asio/asio/basic_stream_socket.hpp
index b7b4f06..41543fc 100644
--- a/ext/asio/asio/basic_stream_socket.hpp
+++ b/ext/asio/asio/basic_stream_socket.hpp
@@ -2,7 +2,7 @@
 // basic_stream_socket.hpp
 // ~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,17 +15,14 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 #include <cstddef>
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
-
 #include "asio/basic_socket.hpp"
+#include "asio/detail/throw_error.hpp"
 #include "asio/error.hpp"
 #include "asio/stream_socket_service.hpp"
-#include "asio/detail/throw_error.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 
diff --git a/ext/asio/asio/basic_streambuf.hpp b/ext/asio/asio/basic_streambuf.hpp
index b34b3fe..17157da 100644
--- a/ext/asio/asio/basic_streambuf.hpp
+++ b/ext/asio/asio/basic_streambuf.hpp
@@ -2,7 +2,7 @@
 // basic_streambuf.hpp
 // ~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,28 +15,23 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
+#include "asio/detail/config.hpp"
 
 #if !defined(BOOST_NO_IOSTREAM)
 
-#include "asio/detail/push_options.hpp"
 #include <algorithm>
 #include <cstring>
-#include <memory>
 #include <stdexcept>
 #include <streambuf>
 #include <vector>
 #include <boost/limits.hpp>
 #include <boost/throw_exception.hpp>
-#include "asio/detail/pop_options.hpp"
-
+#include "asio/basic_streambuf_fwd.hpp"
 #include "asio/buffer.hpp"
 #include "asio/detail/noncopyable.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 
 /// Automatically resizable buffer class based on std::streambuf.
@@ -107,7 +102,11 @@ namespace asio {
  * is >> s;
  * @endcode
  */
+#if defined(GENERATING_DOCUMENTATION)
 template <typename Allocator = std::allocator<char> >
+#else
+template <typename Allocator>
+#endif
 class basic_streambuf
   : public std::streambuf,
     private noncopyable
@@ -337,8 +336,27 @@ protected:
 private:
   std::size_t max_size_;
   std::vector<char_type, Allocator> buffer_;
+
+  // Helper function to get the preferred size for reading data.
+  friend std::size_t read_size_helper(
+      basic_streambuf& sb, std::size_t max_size)
+  {
+    return std::min<std::size_t>(
+        std::max<std::size_t>(512, sb.buffer_.capacity() - sb.size()),
+        std::min<std::size_t>(max_size, sb.max_size() - sb.size()));
+  }
 };
 
+// Helper function to get the preferred size for reading data. Used for any
+// user-provided specialisations of basic_streambuf.
+template <typename Allocator>
+inline std::size_t read_size_helper(
+    basic_streambuf<Allocator>& sb, std::size_t max_size)
+{
+  return std::min<std::size_t>(512,
+      std::min<std::size_t>(max_size, sb.max_size() - sb.size()));
+}
+
 } // namespace asio
 
 #include "asio/detail/pop_options.hpp"
diff --git a/ext/asio/asio/basic_streambuf_fwd.hpp b/ext/asio/asio/basic_streambuf_fwd.hpp
new file mode 100644
index 0000000..e1d81ac
--- /dev/null
+++ b/ext/asio/asio/basic_streambuf_fwd.hpp
@@ -0,0 +1,33 @@
+//
+// basic_streambuf_fwd.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_BASIC_STREAMBUF_FWD_HPP
+#define ASIO_BASIC_STREAMBUF_FWD_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if !defined(BOOST_NO_IOSTREAM)
+
+#include <memory>
+
+namespace asio {
+
+template <typename Allocator = std::allocator<char> >
+class basic_streambuf;
+
+} // namespace asio
+
+#endif // !defined(BOOST_NO_IOSTREAM)
+
+#endif // ASIO_BASIC_STREAMBUF_FWD_HPP
diff --git a/ext/asio/asio/buffer.hpp b/ext/asio/asio/buffer.hpp
index 43b475c..6810fca 100644
--- a/ext/asio/asio/buffer.hpp
+++ b/ext/asio/asio/buffer.hpp
@@ -2,7 +2,7 @@
 // buffer.hpp
 // ~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,16 +15,12 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 #include <cstddef>
-#include <boost/config.hpp>
-#include <boost/array.hpp>
-#include <boost/type_traits/is_const.hpp>
 #include <string>
 #include <vector>
-#include "asio/detail/pop_options.hpp"
+#include <boost/detail/workaround.hpp>
+#include "asio/detail/array_fwd.hpp"
 
 #if defined(BOOST_MSVC)
 # if defined(_HAS_ITERATOR_DEBUGGING) && (_HAS_ITERATOR_DEBUGGING != 0)
@@ -43,11 +39,17 @@
 #endif // defined(__GNUC__)
 
 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
-# include "asio/detail/push_options.hpp"
 # include <boost/function.hpp>
-# include "asio/detail/pop_options.hpp"
 #endif // ASIO_ENABLE_BUFFER_DEBUGGING
 
+#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582)) \
+  || BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590))
+# include <boost/type_traits/is_const.hpp>
+#endif // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
+       // || BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590))
+
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 
 class mutable_buffer;
diff --git a/ext/asio/asio/buffered_read_stream.hpp b/ext/asio/asio/buffered_read_stream.hpp
index afd22ce..d9dc311 100644
--- a/ext/asio/asio/buffered_read_stream.hpp
+++ b/ext/asio/asio/buffered_read_stream.hpp
@@ -2,7 +2,7 @@
 // buffered_read_stream.hpp
 // ~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,23 +15,20 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 #include <cstddef>
 #include <cstring>
-#include <boost/config.hpp>
 #include <boost/type_traits/remove_reference.hpp>
-#include "asio/detail/pop_options.hpp"
-
 #include "asio/buffered_read_stream_fwd.hpp"
 #include "asio/buffer.hpp"
-#include "asio/error.hpp"
-#include "asio/io_service.hpp"
 #include "asio/detail/bind_handler.hpp"
 #include "asio/detail/buffer_resize_guard.hpp"
 #include "asio/detail/buffered_stream_storage.hpp"
 #include "asio/detail/noncopyable.hpp"
+#include "asio/error.hpp"
+#include "asio/io_service.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 
diff --git a/ext/asio/asio/buffered_read_stream_fwd.hpp b/ext/asio/asio/buffered_read_stream_fwd.hpp
index 5078775..0e8495a 100644
--- a/ext/asio/asio/buffered_read_stream_fwd.hpp
+++ b/ext/asio/asio/buffered_read_stream_fwd.hpp
@@ -2,7 +2,7 @@
 // buffered_read_stream_fwd.hpp
 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,8 +15,6 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
 namespace asio {
 
 template <typename Stream>
@@ -24,6 +22,4 @@ class buffered_read_stream;
 
 } // namespace asio
 
-#include "asio/detail/pop_options.hpp"
-
 #endif // ASIO_BUFFERED_READ_STREAM_FWD_HPP
diff --git a/ext/asio/asio/buffered_stream.hpp b/ext/asio/asio/buffered_stream.hpp
index 23dc9c3..11b99f6 100644
--- a/ext/asio/asio/buffered_stream.hpp
+++ b/ext/asio/asio/buffered_stream.hpp
@@ -2,7 +2,7 @@
 // buffered_stream.hpp
 // ~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,19 +15,16 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 #include <cstddef>
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
-
 #include "asio/buffered_read_stream.hpp"
 #include "asio/buffered_write_stream.hpp"
 #include "asio/buffered_stream_fwd.hpp"
+#include "asio/detail/noncopyable.hpp"
 #include "asio/error.hpp"
 #include "asio/io_service.hpp"
-#include "asio/detail/noncopyable.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 
diff --git a/ext/asio/asio/buffered_stream_fwd.hpp b/ext/asio/asio/buffered_stream_fwd.hpp
index f26cd43..a8e958e 100644
--- a/ext/asio/asio/buffered_stream_fwd.hpp
+++ b/ext/asio/asio/buffered_stream_fwd.hpp
@@ -2,7 +2,7 @@
 // buffered_stream_fwd.hpp
 // ~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,8 +15,6 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
 namespace asio {
 
 template <typename Stream>
@@ -24,6 +22,4 @@ class buffered_stream;
 
 } // namespace asio
 
-#include "asio/detail/pop_options.hpp"
-
 #endif // ASIO_BUFFERED_STREAM_FWD_HPP
diff --git a/ext/asio/asio/buffered_write_stream.hpp b/ext/asio/asio/buffered_write_stream.hpp
index 30a92ce..ee0ec77 100644
--- a/ext/asio/asio/buffered_write_stream.hpp
+++ b/ext/asio/asio/buffered_write_stream.hpp
@@ -2,7 +2,7 @@
 // buffered_write_stream.hpp
 // ~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,24 +15,21 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 #include <cstddef>
 #include <cstring>
-#include <boost/config.hpp>
 #include <boost/type_traits/remove_reference.hpp>
-#include "asio/detail/pop_options.hpp"
-
 #include "asio/buffered_write_stream_fwd.hpp"
 #include "asio/buffer.hpp"
 #include "asio/completion_condition.hpp"
-#include "asio/error.hpp"
-#include "asio/io_service.hpp"
-#include "asio/write.hpp"
 #include "asio/detail/bind_handler.hpp"
 #include "asio/detail/buffered_stream_storage.hpp"
 #include "asio/detail/noncopyable.hpp"
+#include "asio/error.hpp"
+#include "asio/io_service.hpp"
+#include "asio/write.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 
diff --git a/ext/asio/asio/buffered_write_stream_fwd.hpp b/ext/asio/asio/buffered_write_stream_fwd.hpp
index dc0e014..cb09fe8 100644
--- a/ext/asio/asio/buffered_write_stream_fwd.hpp
+++ b/ext/asio/asio/buffered_write_stream_fwd.hpp
@@ -2,7 +2,7 @@
 // buffered_write_stream_fwd.hpp
 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,8 +15,6 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
 namespace asio {
 
 template <typename Stream>
@@ -24,6 +22,4 @@ class buffered_write_stream;
 
 } // namespace asio
 
-#include "asio/detail/pop_options.hpp"
-
 #endif // ASIO_BUFFERED_WRITE_STREAM_FWD_HPP
diff --git a/ext/asio/asio/buffers_iterator.hpp b/ext/asio/asio/buffers_iterator.hpp
index 7da55f2..dcca2d3 100644
--- a/ext/asio/asio/buffers_iterator.hpp
+++ b/ext/asio/asio/buffers_iterator.hpp
@@ -2,7 +2,7 @@
 // buffers_iterator.hpp
 // ~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,20 +15,17 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 #include <cstddef>
 #include <boost/assert.hpp>
-#include <boost/config.hpp>
 #include <boost/detail/workaround.hpp>
 #include <boost/iterator.hpp>
 #include <boost/type_traits/is_convertible.hpp>
 #include <boost/type_traits/add_const.hpp>
-#include "asio/detail/pop_options.hpp"
-
 #include "asio/buffer.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 
 namespace detail
@@ -210,6 +207,15 @@ public:
     return tmp;
   }
 
+  /// Addition operator.
+  friend buffers_iterator operator+(std::ptrdiff_t difference,
+      const buffers_iterator& iter)
+  {
+    buffers_iterator tmp(iter);
+    tmp.advance(difference);
+    return tmp;
+  }
+
   /// Subtraction operator.
   friend buffers_iterator operator-(const buffers_iterator& iter,
       std::ptrdiff_t difference)
diff --git a/ext/asio/asio/completion_condition.hpp b/ext/asio/asio/completion_condition.hpp
index d4e631d..dd1fb27 100644
--- a/ext/asio/asio/completion_condition.hpp
+++ b/ext/asio/asio/completion_condition.hpp
@@ -2,7 +2,7 @@
 // completion_condition.hpp
 // ~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,12 +15,10 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
+#include <cstddef>
 
 #include "asio/detail/push_options.hpp"
-#include <cstddef>
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
 
 namespace asio {
 
diff --git a/ext/asio/asio/datagram_socket_service.hpp b/ext/asio/asio/datagram_socket_service.hpp
index 7d135ee..87821c3 100644
--- a/ext/asio/asio/datagram_socket_service.hpp
+++ b/ext/asio/asio/datagram_socket_service.hpp
@@ -2,7 +2,7 @@
 // datagram_socket_service.hpp
 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,16 +15,10 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 #include <cstddef>
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
-
 #include "asio/error.hpp"
 #include "asio/io_service.hpp"
-#include "asio/detail/service_base.hpp"
 
 #if defined(ASIO_HAS_IOCP)
 # include "asio/detail/win_iocp_socket_service.hpp"
@@ -32,6 +26,8 @@
 # include "asio/detail/reactive_socket_service.hpp"
 #endif
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 
 /// Default service implementation for a datagram socket.
diff --git a/ext/asio/asio/deadline_timer.hpp b/ext/asio/asio/deadline_timer.hpp
index e0905f2..fd0d5dc 100644
--- a/ext/asio/asio/deadline_timer.hpp
+++ b/ext/asio/asio/deadline_timer.hpp
@@ -2,7 +2,7 @@
 // deadline_timer.hpp
 // ~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,16 +15,14 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
+#include "asio/detail/config.hpp"
 #include "asio/detail/socket_types.hpp" // Must come before posix_time.
+#include "asio/basic_deadline_timer.hpp"
 
 #include "asio/detail/push_options.hpp"
 #include <boost/date_time/posix_time/posix_time_types.hpp>
 #include "asio/detail/pop_options.hpp"
 
-#include "asio/basic_deadline_timer.hpp"
-
 namespace asio {
 
 /// Typedef for the typical usage of timer. Uses a UTC clock.
@@ -32,6 +30,4 @@ typedef basic_deadline_timer<boost::posix_time::ptime> deadline_timer;
 
 } // namespace asio
 
-#include "asio/detail/pop_options.hpp"
-
 #endif // ASIO_DEADLINE_TIMER_HPP
diff --git a/ext/asio/asio/deadline_timer_service.hpp b/ext/asio/asio/deadline_timer_service.hpp
index 284a690..60d898b 100644
--- a/ext/asio/asio/deadline_timer_service.hpp
+++ b/ext/asio/asio/deadline_timer_service.hpp
@@ -2,7 +2,7 @@
 // deadline_timer_service.hpp
 // ~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,17 +15,13 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 #include <cstddef>
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
-
+#include "asio/detail/deadline_timer_service.hpp"
 #include "asio/io_service.hpp"
 #include "asio/time_traits.hpp"
-#include "asio/detail/deadline_timer_service.hpp"
-#include "asio/detail/service_base.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 
diff --git a/ext/asio/asio/detail/array_fwd.hpp b/ext/asio/asio/detail/array_fwd.hpp
new file mode 100644
index 0000000..12c295c
--- /dev/null
+++ b/ext/asio/asio/detail/array_fwd.hpp
@@ -0,0 +1,25 @@
+//
+// detail/array_fwd.hpp
+// ~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_ARRAY_FWD_HPP
+#define ASIO_DETAIL_ARRAY_FWD_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+namespace boost {
+
+template<class T, std::size_t N>
+class array;
+
+} // namespace boost
+
+#endif // ASIO_DETAIL_ARRAY_FWD_HPP
diff --git a/ext/asio/asio/detail/base_from_completion_cond.hpp b/ext/asio/asio/detail/base_from_completion_cond.hpp
index 90a11f9..93cc8c4 100644
--- a/ext/asio/asio/detail/base_from_completion_cond.hpp
+++ b/ext/asio/asio/detail/base_from_completion_cond.hpp
@@ -1,8 +1,8 @@
 //
-// base_from_completion_cond.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// detail/base_from_completion_cond.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,10 +15,11 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
+#include "asio/detail/config.hpp"
 #include "asio/completion_condition.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 namespace detail {
 
@@ -31,7 +32,8 @@ protected:
   {
   }
 
-  std::size_t check(const asio::error_code& ec,
+  std::size_t check_for_completion(
+      const asio::error_code& ec,
       std::size_t total_transferred)
   {
     return detail::adapt_completion_condition_result(
@@ -50,7 +52,8 @@ protected:
   {
   }
 
-  static std::size_t check(const asio::error_code& ec,
+  static std::size_t check_for_completion(
+      const asio::error_code& ec,
       std::size_t total_transferred)
   {
     return transfer_all_t()(ec, total_transferred);
diff --git a/ext/asio/asio/detail/bind_handler.hpp b/ext/asio/asio/detail/bind_handler.hpp
index 5d9eb00..f663a5b 100644
--- a/ext/asio/asio/detail/bind_handler.hpp
+++ b/ext/asio/asio/detail/bind_handler.hpp
@@ -1,8 +1,8 @@
 //
-// bind_handler.hpp
-// ~~~~~~~~~~~~~~~~
+// detail/bind_handler.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,11 +15,12 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
+#include "asio/detail/config.hpp"
 #include "asio/detail/handler_alloc_helpers.hpp"
 #include "asio/detail/handler_invoke_helpers.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 namespace detail {
 
@@ -35,7 +36,7 @@ public:
 
   void operator()()
   {
-    handler_(arg1_);
+    handler_(static_cast<const Arg1&>(arg1_));
   }
 
   void operator()() const
@@ -92,7 +93,8 @@ public:
 
   void operator()()
   {
-    handler_(arg1_, arg2_);
+    handler_(static_cast<const Arg1&>(arg1_),
+        static_cast<const Arg2&>(arg2_));
   }
 
   void operator()() const
@@ -152,7 +154,9 @@ public:
 
   void operator()()
   {
-    handler_(arg1_, arg2_, arg3_);
+    handler_(static_cast<const Arg1&>(arg1_),
+        static_cast<const Arg2&>(arg2_),
+        static_cast<const Arg3&>(arg3_));
   }
 
   void operator()() const
@@ -216,7 +220,10 @@ public:
 
   void operator()()
   {
-    handler_(arg1_, arg2_, arg3_, arg4_);
+    handler_(static_cast<const Arg1&>(arg1_),
+        static_cast<const Arg2&>(arg2_),
+        static_cast<const Arg3&>(arg3_),
+        static_cast<const Arg4&>(arg4_));
   }
 
   void operator()() const
@@ -287,7 +294,11 @@ public:
 
   void operator()()
   {
-    handler_(arg1_, arg2_, arg3_, arg4_, arg5_);
+    handler_(static_cast<const Arg1&>(arg1_),
+        static_cast<const Arg2&>(arg2_),
+        static_cast<const Arg3&>(arg3_),
+        static_cast<const Arg4&>(arg4_),
+        static_cast<const Arg5&>(arg5_));
   }
 
   void operator()() const
diff --git a/ext/asio/asio/detail/buffer_resize_guard.hpp b/ext/asio/asio/detail/buffer_resize_guard.hpp
index 368de32..4bf6a8e 100644
--- a/ext/asio/asio/detail/buffer_resize_guard.hpp
+++ b/ext/asio/asio/detail/buffer_resize_guard.hpp
@@ -1,8 +1,8 @@
 //
-// buffer_resize_guard.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~
+// detail/buffer_resize_guard.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,12 +15,10 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
+#include <boost/limits.hpp>
 
 #include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include <boost/limits.hpp>
-#include "asio/detail/pop_options.hpp"
 
 namespace asio {
 namespace detail {
diff --git a/ext/asio/asio/detail/buffer_sequence_adapter.hpp b/ext/asio/asio/detail/buffer_sequence_adapter.hpp
index 6269d6a..17044b7 100644
--- a/ext/asio/asio/detail/buffer_sequence_adapter.hpp
+++ b/ext/asio/asio/detail/buffer_sequence_adapter.hpp
@@ -1,8 +1,8 @@
 //
-// buffer_sequence_adapter.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// detail/buffer_sequence_adapter.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,9 +15,11 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
+#include "asio/detail/config.hpp"
 #include "asio/buffer.hpp"
+#include "asio/detail/socket_types.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 namespace detail {
@@ -32,14 +34,14 @@ protected:
       const asio::mutable_buffer& buffer)
   {
     buf.buf = asio::buffer_cast<char*>(buffer);
-    buf.len = asio::buffer_size(buffer);
+    buf.len = static_cast<ULONG>(asio::buffer_size(buffer));
   }
 
   static void init_native_buffer(WSABUF& buf,
       const asio::const_buffer& buffer)
   {
     buf.buf = const_cast<char*>(asio::buffer_cast<const char*>(buffer));
-    buf.len = asio::buffer_size(buffer);
+    buf.len = static_cast<ULONG>(asio::buffer_size(buffer));
   }
 #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
   typedef iovec native_buffer_type;
@@ -158,7 +160,7 @@ public:
   explicit buffer_sequence_adapter(
       const asio::mutable_buffers_1& buffers)
   {
-    init_native_buffer(buffer_, buffers);
+    init_native_buffer(buffer_, Buffer(buffers));
     total_buffer_size_ = asio::buffer_size(buffers);
   }
 
@@ -205,7 +207,7 @@ public:
   explicit buffer_sequence_adapter(
       const asio::const_buffers_1& buffers)
   {
-    init_native_buffer(buffer_, buffers);
+    init_native_buffer(buffer_, Buffer(buffers));
     total_buffer_size_ = asio::buffer_size(buffers);
   }
 
diff --git a/ext/asio/asio/detail/buffered_stream_storage.hpp b/ext/asio/asio/detail/buffered_stream_storage.hpp
index 51f6556..7e1b746 100644
--- a/ext/asio/asio/detail/buffered_stream_storage.hpp
+++ b/ext/asio/asio/detail/buffered_stream_storage.hpp
@@ -1,8 +1,8 @@
 //
-// buffered_stream_storage.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// detail/buffered_stream_storage.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,15 +15,13 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
+#include "asio/detail/config.hpp"
 #include <cassert>
 #include <cstddef>
 #include <cstring>
 #include <vector>
-#include "asio/detail/pop_options.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 namespace detail {
diff --git a/ext/asio/asio/detail/call_stack.hpp b/ext/asio/asio/detail/call_stack.hpp
index 0e9ddaf..7ad5dc5 100644
--- a/ext/asio/asio/detail/call_stack.hpp
+++ b/ext/asio/asio/detail/call_stack.hpp
@@ -1,8 +1,8 @@
 //
-// call_stack.hpp
-// ~~~~~~~~~~~~~~
+// detail/call_stack.hpp
+// ~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,11 +15,12 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
+#include "asio/detail/config.hpp"
 #include "asio/detail/noncopyable.hpp"
 #include "asio/detail/tss_ptr.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 namespace detail {
 
diff --git a/ext/asio/asio/detail/completion_handler.hpp b/ext/asio/asio/detail/completion_handler.hpp
index 16167df..0224d7e 100644
--- a/ext/asio/asio/detail/completion_handler.hpp
+++ b/ext/asio/asio/detail/completion_handler.hpp
@@ -1,8 +1,8 @@
 //
-// completion_handler.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~
+// detail/completion_handler.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,13 +15,14 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
+#include "asio/detail/config.hpp"
 #include "asio/detail/fenced_block.hpp"
 #include "asio/detail/handler_alloc_helpers.hpp"
 #include "asio/detail/handler_invoke_helpers.hpp"
 #include "asio/detail/operation.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 namespace detail {
 
@@ -29,6 +30,8 @@ template <typename Handler>
 class completion_handler : public operation
 {
 public:
+  ASIO_DEFINE_HANDLER_PTR(completion_handler);
+
   completion_handler(Handler h)
     : operation(&completion_handler::do_complete),
       handler_(h)
@@ -40,20 +43,21 @@ public:
   {
     // Take ownership of the handler object.
     completion_handler* h(static_cast<completion_handler*>(base));
-    typedef handler_alloc_traits<Handler, completion_handler> alloc_traits;
-    handler_ptr<alloc_traits> ptr(h->handler_, h);
+    ptr p = { boost::addressof(h->handler_), h, h };
+
+    // Make a copy of the handler so that the memory can be deallocated before
+    // the upcall is made. Even if we're not about to make an upcall, a
+    // sub-object of the handler may be the true owner of the memory associated
+    // with the handler. Consequently, a local copy of the handler is required
+    // to ensure that any owning sub-object remains valid until after we have
+    // deallocated the memory here.
+    Handler handler(h->handler_);
+    p.h = boost::addressof(handler);
+    p.reset();
 
     // Make the upcall if required.
     if (owner)
     {
-      // Make a copy of the handler so that the memory can be deallocated
-      // before the upcall is made. Even if we're not about to make an
-      // upcall, a sub-object of the handler may be the true owner of the
-      // memory associated with the handler. Consequently, a local copy of
-      // the handler is required to ensure that any owning sub-object remains
-      // valid until after we have deallocated the memory here.
-      Handler handler(h->handler_);
-      ptr.reset();
       asio::detail::fenced_block b;
       asio_handler_invoke_helpers::invoke(handler, handler);
     }
diff --git a/ext/asio/asio/detail/config.hpp b/ext/asio/asio/detail/config.hpp
new file mode 100644
index 0000000..8328d76
--- /dev/null
+++ b/ext/asio/asio/detail/config.hpp
@@ -0,0 +1,205 @@
+//
+// detail/config.hpp
+// ~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_CONFIG_HPP
+#define ASIO_DETAIL_CONFIG_HPP
+
+#include <boost/config.hpp>
+
+// Default to a header-only implementation. The user must specifically request
+// separate compilation by defining either ASIO_SEPARATE_COMPILATION or
+// ASIO_DYN_LINK (as a DLL/shared library implies separate compilation).
+#if !defined(ASIO_HEADER_ONLY)
+# if !defined(ASIO_SEPARATE_COMPILATION)
+#  if !defined(ASIO_DYN_LINK)
+#   define ASIO_HEADER_ONLY
+#  endif // !defined(ASIO_DYN_LINK)
+# endif // !defined(ASIO_SEPARATE_COMPILATION)
+#endif // !defined(ASIO_HEADER_ONLY)
+
+#if defined(ASIO_HEADER_ONLY)
+# define ASIO_DECL inline
+#else // defined(ASIO_HEADER_ONLY)
+# if defined(BOOST_HAS_DECLSPEC)
+// We need to import/export our code only if the user has specifically asked
+// for it by defining ASIO_DYN_LINK.
+#  if defined(ASIO_DYN_LINK)
+// Export if this is our own source, otherwise import.
+#   if defined(ASIO_SOURCE)
+#    define ASIO_DECL __declspec(dllexport)
+#   else // defined(ASIO_SOURCE)
+#    define ASIO_DECL __declspec(dllimport)
+#   endif // defined(ASIO_SOURCE)
+#  endif // defined(ASIO_DYN_LINK)
+# endif // defined(BOOST_HAS_DECLSPEC)
+#endif // defined(ASIO_HEADER_ONLY)
+
+// If ASIO_DECL isn't defined yet define it now.
+#if !defined(ASIO_DECL)
+# define ASIO_DECL
+#endif // !defined(ASIO_DECL)
+
+// Windows: target OS version.
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+# if !defined(_WIN32_WINNT) && !defined(_WIN32_WINDOWS)
+#  if defined(_MSC_VER) || defined(__BORLANDC__)
+#   pragma message( \
+  "Please define _WIN32_WINNT or _WIN32_WINDOWS appropriately. For example:\n"\
+  "- add -D_WIN32_WINNT=0x0501 to the compiler command line; or\n"\
+  "- add _WIN32_WINNT=0x0501 to your project's Preprocessor Definitions.\n"\
+  "Assuming _WIN32_WINNT=0x0501 (i.e. Windows XP target).")
+#  else // defined(_MSC_VER) || defined(__BORLANDC__)
+#   warning Please define _WIN32_WINNT or _WIN32_WINDOWS appropriately.
+#   warning For example, add -D_WIN32_WINNT=0x0501 to the compiler command line.
+#   warning Assuming _WIN32_WINNT=0x0501 (i.e. Windows XP target).
+#  endif // defined(_MSC_VER) || defined(__BORLANDC__)
+#  define _WIN32_WINNT 0x0501
+# endif // !defined(_WIN32_WINNT) && !defined(_WIN32_WINDOWS)
+# if defined(_MSC_VER)
+#  if defined(_WIN32) && !defined(WIN32)
+#   if !defined(_WINSOCK2API_)
+#    define WIN32 // Needed for correct types in winsock2.h
+#   else // !defined(_WINSOCK2API_)
+#    error Please define the macro WIN32 in your compiler options
+#   endif // !defined(_WINSOCK2API_)
+#  endif // defined(_WIN32) && !defined(WIN32)
+# endif // defined(_MSC_VER)
+# if defined(__BORLANDC__)
+#  if defined(__WIN32__) && !defined(WIN32)
+#   if !defined(_WINSOCK2API_)
+#    define WIN32 // Needed for correct types in winsock2.h
+#   else // !defined(_WINSOCK2API_)
+#    error Please define the macro WIN32 in your compiler options
+#   endif // !defined(_WINSOCK2API_)
+#  endif // defined(__WIN32__) && !defined(WIN32)
+# endif // defined(__BORLANDC__)
+# if defined(__CYGWIN__)
+#  if !defined(__USE_W32_SOCKETS)
+#   error You must add -D__USE_W32_SOCKETS to your compiler options.
+#  endif // !defined(__USE_W32_SOCKETS)
+# endif // defined(__CYGWIN__)
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+
+// Windows: minimise header inclusion.
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+# if !defined(ASIO_NO_WIN32_LEAN_AND_MEAN)
+#  if !defined(WIN32_LEAN_AND_MEAN)
+#   define WIN32_LEAN_AND_MEAN
+#  endif // !defined(WIN32_LEAN_AND_MEAN)
+# endif // !defined(ASIO_NO_WIN32_LEAN_AND_MEAN)
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+
+// Windows: suppress definition of "min" and "max" macros.
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+# if !defined(ASIO_NO_NOMINMAX)
+#  if !defined(NOMINMAX)
+#   define NOMINMAX 1
+#  endif // !defined(NOMINMAX)
+# endif // !defined(ASIO_NO_NOMINMAX)
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+
+// Windows: IO Completion Ports.
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+# if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0400)
+#  if !defined(UNDER_CE)
+#   if !defined(ASIO_DISABLE_IOCP)
+#    define ASIO_HAS_IOCP 1
+#   endif // !defined(ASIO_DISABLE_IOCP)
+#  endif // !defined(UNDER_CE)
+# endif // defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0400)
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+
+// Linux: epoll, eventfd and timerfd.
+#if defined(__linux__)
+# include <linux/version.h>
+# if !defined(ASIO_DISABLE_EPOLL)
+#  if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,45)
+#   define ASIO_HAS_EPOLL 1
+#  endif // LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,45)
+# endif // !defined(ASIO_DISABLE_EVENTFD)
+# if !defined(ASIO_DISABLE_EVENTFD)
+#  if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
+#   define ASIO_HAS_EVENTFD 1
+#  endif // LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
+# endif // !defined(ASIO_DISABLE_EVENTFD)
+# if defined(ASIO_HAS_EPOLL)
+#  if (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 8)
+#   define ASIO_HAS_TIMERFD 1
+#  endif // (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 8)
+# endif // defined(ASIO_HAS_EPOLL)
+#endif // defined(__linux__)
+
+// Mac OS X, FreeBSD, NetBSD, OpenBSD: kqueue.
+#if (defined(__MACH__) && defined(__APPLE__)) \
+  || defined(__FreeBSD__) \
+  || defined(__NetBSD__) \
+  || defined(__OpenBSD__)
+# if !defined(ASIO_DISABLE_KQUEUE)
+#  define ASIO_HAS_KQUEUE 1
+# endif // !defined(ASIO_DISABLE_KQUEUE)
+#endif // (defined(__MACH__) && defined(__APPLE__))
+       //   || defined(__FreeBSD__)
+       //   || defined(__NetBSD__)
+       //   || defined(__OpenBSD__)
+
+// Solaris: /dev/poll.
+#if defined(__sun)
+# if !defined(ASIO_DISABLE_DEV_POLL)
+#  define ASIO_HAS_DEV_POLL 1
+# endif // !defined(ASIO_DISABLE_DEV_POLL)
+#endif // defined(__sun)
+
+// Serial ports.
+#if defined(ASIO_HAS_IOCP) \
+   || !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+# if !defined(__SYMBIAN32__)
+#  if !defined(ASIO_DISABLE_SERIAL_PORT)
+#   define ASIO_HAS_SERIAL_PORT 1
+#  endif // !defined(ASIO_DISABLE_SERIAL_PORT)
+# endif // !defined(__SYMBIAN32__)
+#endif // defined(ASIO_HAS_IOCP)
+       //   || !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
+// Windows: stream handles.
+#if !defined(ASIO_DISABLE_WINDOWS_STREAM_HANDLE)
+# if defined(ASIO_HAS_IOCP)
+#  define ASIO_HAS_WINDOWS_STREAM_HANDLE 1
+# endif // defined(ASIO_HAS_IOCP)
+#endif // !defined(ASIO_DISABLE_WINDOWS_STREAM_HANDLE)
+
+// Windows: random access handles.
+#if !defined(ASIO_DISABLE_WINDOWS_RANDOM_ACCESS_HANDLE)
+# if defined(ASIO_HAS_IOCP)
+#  define ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE 1
+# endif // defined(ASIO_HAS_IOCP)
+#endif // !defined(ASIO_DISABLE_WINDOWS_RANDOM_ACCESS_HANDLE)
+
+// Windows: OVERLAPPED wrapper.
+#if !defined(ASIO_DISABLE_WINDOWS_OVERLAPPED_PTR)
+# if defined(ASIO_HAS_IOCP)
+#  define ASIO_HAS_WINDOWS_OVERLAPPED_PTR 1
+# endif // defined(ASIO_HAS_IOCP)
+#endif // !defined(ASIO_DISABLE_WINDOWS_OVERLAPPED_PTR)
+
+// POSIX: stream-oriented file descriptors.
+#if !defined(ASIO_DISABLE_POSIX_STREAM_DESCRIPTOR)
+# if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+#  define ASIO_HAS_POSIX_STREAM_DESCRIPTOR 1
+# endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+#endif // !defined(ASIO_DISABLE_POSIX_STREAM_DESCRIPTOR)
+
+// UNIX domain sockets.
+#if !defined(ASIO_DISABLE_LOCAL_SOCKETS)
+# if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+#  define ASIO_HAS_LOCAL_SOCKETS 1
+# endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+#endif // !defined(ASIO_DISABLE_LOCAL_SOCKETS)
+
+#endif // ASIO_DETAIL_CONFIG_HPP
diff --git a/ext/asio/asio/detail/consuming_buffers.hpp b/ext/asio/asio/detail/consuming_buffers.hpp
index 80b6a8e..8969ae4 100644
--- a/ext/asio/asio/detail/consuming_buffers.hpp
+++ b/ext/asio/asio/detail/consuming_buffers.hpp
@@ -1,8 +1,8 @@
 //
-// consuming_buffers.hpp
-// ~~~~~~~~~~~~~~~~~~~~~
+// detail/consuming_buffers.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,18 +15,14 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <algorithm>
+#include "asio/detail/config.hpp"
 #include <cstddef>
-#include <boost/config.hpp>
 #include <boost/iterator.hpp>
 #include <boost/limits.hpp>
-#include "asio/detail/pop_options.hpp"
-
 #include "asio/buffer.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 namespace detail {
 
@@ -156,12 +152,14 @@ public:
   consuming_buffers(const Buffers& buffers)
     : buffers_(buffers),
       at_end_(buffers_.begin() == buffers_.end()),
-      first_(*buffers_.begin()),
       begin_remainder_(buffers_.begin()),
       max_size_((std::numeric_limits<std::size_t>::max)())
   {
     if (!at_end_)
+    {
+      first_ = *buffers_.begin();
       ++begin_remainder_;
+    }
   }
 
   // Copy constructor.
diff --git a/ext/asio/asio/detail/deadline_timer_service.hpp b/ext/asio/asio/detail/deadline_timer_service.hpp
index 6daf7ac..782f5c3 100644
--- a/ext/asio/asio/detail/deadline_timer_service.hpp
+++ b/ext/asio/asio/detail/deadline_timer_service.hpp
@@ -1,8 +1,8 @@
 //
-// deadline_timer_service.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~
+// detail/deadline_timer_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,14 +15,8 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 #include <cstddef>
-#include <boost/config.hpp>
-#include <boost/date_time/posix_time/posix_time_types.hpp>
-#include "asio/detail/pop_options.hpp"
-
 #include "asio/error.hpp"
 #include "asio/io_service.hpp"
 #include "asio/detail/bind_handler.hpp"
@@ -33,6 +27,13 @@
 #include "asio/detail/timer_op.hpp"
 #include "asio/detail/timer_queue.hpp"
 #include "asio/detail/timer_scheduler.hpp"
+#include "asio/detail/wait_handler.hpp"
+
+#include "asio/detail/push_options.hpp"
+#include <boost/date_time/posix_time/posix_time_types.hpp>
+#include "asio/detail/pop_options.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 namespace detail {
@@ -54,6 +55,7 @@ public:
   {
     time_type expiry;
     bool might_have_pending_waits;
+    typename timer_queue<Time_Traits>::per_timer_data timer_data;
   };
 
   // Constructor.
@@ -97,7 +99,7 @@ public:
       ec = asio::error_code();
       return 0;
     }
-    std::size_t count = scheduler_.cancel_timer(timer_queue_, &impl);
+    std::size_t count = scheduler_.cancel_timer(timer_queue_, impl.timer_data);
     impl.might_have_pending_waits = false;
     ec = asio::error_code();
     return count;
@@ -151,59 +153,21 @@ public:
     ec = asio::error_code();
   }
 
-  template <typename Handler>
-  class wait_handler : public timer_op
-  {
-  public:
-    wait_handler(Handler handler)
-      : timer_op(&wait_handler::do_complete),
-        handler_(handler)
-    {
-    }
-
-    static void do_complete(io_service_impl* owner, operation* base,
-        asio::error_code /*ec*/, std::size_t /*bytes_transferred*/)
-    {
-      // Take ownership of the handler object.
-      wait_handler* h(static_cast<wait_handler*>(base));
-      typedef handler_alloc_traits<Handler, wait_handler> alloc_traits;
-      handler_ptr<alloc_traits> ptr(h->handler_, h);
-
-      // Make the upcall if required.
-      if (owner)
-      {
-        // Make a copy of the handler so that the memory can be deallocated
-        // before the upcall is made. Even if we're not about to make an
-        // upcall, a sub-object of the handler may be the true owner of the
-        // memory associated with the handler. Consequently, a local copy of
-        // the handler is required to ensure that any owning sub-object remains
-        // valid until after we have deallocated the memory here.
-        detail::binder1<Handler, asio::error_code>
-          handler(h->handler_, h->ec_);
-        ptr.reset();
-        asio::detail::fenced_block b;
-        asio_handler_invoke_helpers::invoke(handler, handler);
-      }
-    }
-
-  private:
-    Handler handler_;
-  };
-
   // Start an asynchronous wait on the timer.
   template <typename Handler>
   void async_wait(implementation_type& impl, Handler handler)
   {
     // Allocate and construct an operation to wrap the handler.
-    typedef wait_handler<Handler> value_type;
-    typedef handler_alloc_traits<Handler, value_type> alloc_traits;
-    raw_handler_ptr<alloc_traits> raw_ptr(handler);
-    handler_ptr<alloc_traits> ptr(raw_ptr, handler);
+    typedef wait_handler<Handler> op;
+    typename op::ptr p = { boost::addressof(handler),
+      asio_handler_alloc_helpers::allocate(
+        sizeof(op), handler), 0 };
+    p.p = new (p.v) op(handler);
 
     impl.might_have_pending_waits = true;
 
-    scheduler_.schedule_timer(timer_queue_, impl.expiry, ptr.get(), &impl);
-    ptr.release();
+    scheduler_.schedule_timer(timer_queue_, impl.expiry, impl.timer_data, p.p);
+    p.v = p.p = 0;
   }
 
 private:
diff --git a/ext/asio/asio/detail/descriptor_ops.hpp b/ext/asio/asio/detail/descriptor_ops.hpp
index ea3731e..5cac91d 100644
--- a/ext/asio/asio/detail/descriptor_ops.hpp
+++ b/ext/asio/asio/detail/descriptor_ops.hpp
@@ -1,8 +1,8 @@
 //
-// descriptor_ops.hpp
-// ~~~~~~~~~~~~~~~~~~
+// detail/descriptor_ops.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,27 +15,34 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include <cerrno>
-#include "asio/detail/pop_options.hpp"
+#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
 
-#include "asio/error.hpp"
+#include <cstddef>
+#include "asio/error_code.hpp"
 #include "asio/detail/socket_types.hpp"
 
-#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 namespace detail {
 namespace descriptor_ops {
 
-inline void clear_error(asio::error_code& ec)
+// Descriptor state bits.
+enum
 {
-  errno = 0;
-  ec = asio::error_code();
-}
+  // The user wants a non-blocking descriptor.
+  user_set_non_blocking = 1,
+
+  // The descriptor has been set non-blocking.
+  internal_non_blocking = 2,
+
+  // Helper "state" used to determine whether the descriptor is non-blocking.
+  non_blocking = user_set_non_blocking | internal_non_blocking
+};
+
+typedef unsigned char state_type;
 
 template <typename ReturnType>
 inline ReturnType error_wrapper(ReturnType return_value,
@@ -46,131 +53,53 @@ inline ReturnType error_wrapper(ReturnType return_value,
   return return_value;
 }
 
-inline int open(const char* path, int flags, asio::error_code& ec)
-{
-  clear_error(ec);
-  int result = error_wrapper(::open(path, flags), ec);
-  if (result >= 0)
-    clear_error(ec);
-  return result;
-}
+ASIO_DECL int open(const char* path, int flags,
+    asio::error_code& ec);
 
-inline int close(int d, asio::error_code& ec)
-{
-  clear_error(ec);
-  int result = error_wrapper(::close(d), ec);
-  if (result == 0)
-    clear_error(ec);
-  return result;
-}
+ASIO_DECL int close(int d, state_type& state,
+    asio::error_code& ec);
 
-inline void init_buf_iov_base(void*& base, void* addr)
-{
-  base = addr;
-}
-
-template <typename T>
-inline void init_buf_iov_base(T& base, void* addr)
-{
-  base = static_cast<T>(addr);
-}
+ASIO_DECL bool set_internal_non_blocking(int d,
+    state_type& state, asio::error_code& ec);
 
 typedef iovec buf;
 
-inline void init_buf(buf& b, void* data, size_t size)
-{
-  init_buf_iov_base(b.iov_base, data);
-  b.iov_len = size;
-}
+ASIO_DECL std::size_t sync_read(int d, state_type state, buf* bufs,
+    std::size_t count, bool all_empty, asio::error_code& ec);
 
-inline void init_buf(buf& b, const void* data, size_t size)
-{
-  init_buf_iov_base(b.iov_base, const_cast<void*>(data));
-  b.iov_len = size;
-}
+ASIO_DECL bool non_blocking_read(int d, buf* bufs, std::size_t count,
+    asio::error_code& ec, std::size_t& bytes_transferred);
 
-inline int scatter_read(int d, buf* bufs, size_t count,
-    asio::error_code& ec)
-{
-  clear_error(ec);
-  int result = error_wrapper(::readv(d, bufs, static_cast<int>(count)), ec);
-  if (result >= 0)
-    clear_error(ec);
-  return result;
-}
+ASIO_DECL std::size_t sync_write(int d, state_type state,
+    const buf* bufs, std::size_t count, bool all_empty,
+    asio::error_code& ec);
 
-inline int gather_write(int d, const buf* bufs, size_t count,
-    asio::error_code& ec)
-{
-  clear_error(ec);
-  int result = error_wrapper(::writev(d, bufs, static_cast<int>(count)), ec);
-  if (result >= 0)
-    clear_error(ec);
-  return result;
-}
+ASIO_DECL bool non_blocking_write(int d,
+    const buf* bufs, std::size_t count,
+    asio::error_code& ec, std::size_t& bytes_transferred);
 
-inline int ioctl(int d, long cmd, ioctl_arg_type* arg,
-    asio::error_code& ec)
-{
-  clear_error(ec);
-  int result = error_wrapper(::ioctl(d, cmd, arg), ec);
-  if (result >= 0)
-    clear_error(ec);
-  return result;
-}
+ASIO_DECL int ioctl(int d, state_type& state, long cmd,
+    ioctl_arg_type* arg, asio::error_code& ec);
 
-inline int fcntl(int d, long cmd, asio::error_code& ec)
-{
-  clear_error(ec);
-  int result = error_wrapper(::fcntl(d, cmd), ec);
-  if (result != -1)
-    clear_error(ec);
-  return result;
-}
+ASIO_DECL int fcntl(int d, long cmd, asio::error_code& ec);
 
-inline int fcntl(int d, long cmd, long arg, asio::error_code& ec)
-{
-  clear_error(ec);
-  int result = error_wrapper(::fcntl(d, cmd, arg), ec);
-  if (result != -1)
-    clear_error(ec);
-  return result;
-}
+ASIO_DECL int fcntl(int d, long cmd,
+    long arg, asio::error_code& ec);
 
-inline int poll_read(int d, asio::error_code& ec)
-{
-  clear_error(ec);
-  pollfd fds;
-  fds.fd = d;
-  fds.events = POLLIN;
-  fds.revents = 0;
-  clear_error(ec);
-  int result = error_wrapper(::poll(&fds, 1, -1), ec);
-  if (result >= 0)
-    clear_error(ec);
-  return result;
-}
+ASIO_DECL int poll_read(int d, asio::error_code& ec);
 
-inline int poll_write(int d, asio::error_code& ec)
-{
-  clear_error(ec);
-  pollfd fds;
-  fds.fd = d;
-  fds.events = POLLOUT;
-  fds.revents = 0;
-  clear_error(ec);
-  int result = error_wrapper(::poll(&fds, 1, -1), ec);
-  if (result >= 0)
-    clear_error(ec);
-  return result;
-}
+ASIO_DECL int poll_write(int d, asio::error_code& ec);
 
 } // namespace descriptor_ops
 } // namespace detail
 } // namespace asio
 
-#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
-
 #include "asio/detail/pop_options.hpp"
 
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/detail/impl/descriptor_ops.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
+#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
 #endif // ASIO_DETAIL_DESCRIPTOR_OPS_HPP
diff --git a/ext/asio/asio/detail/descriptor_read_op.hpp b/ext/asio/asio/detail/descriptor_read_op.hpp
new file mode 100644
index 0000000..0d45167
--- /dev/null
+++ b/ext/asio/asio/detail/descriptor_read_op.hpp
@@ -0,0 +1,114 @@
+//
+// detail/descriptor_read_op.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_DESCRIPTOR_READ_OP_HPP
+#define ASIO_DETAIL_DESCRIPTOR_READ_OP_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
+#include <boost/utility/addressof.hpp>
+#include "asio/detail/bind_handler.hpp"
+#include "asio/detail/buffer_sequence_adapter.hpp"
+#include "asio/detail/descriptor_ops.hpp"
+#include "asio/detail/fenced_block.hpp"
+#include "asio/detail/reactor_op.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename MutableBufferSequence>
+class descriptor_read_op_base : public reactor_op
+{
+public:
+  descriptor_read_op_base(int descriptor,
+      const MutableBufferSequence& buffers, func_type complete_func)
+    : reactor_op(&descriptor_read_op_base::do_perform, complete_func),
+      descriptor_(descriptor),
+      buffers_(buffers)
+  {
+  }
+
+  static bool do_perform(reactor_op* base)
+  {
+    descriptor_read_op_base* o(static_cast<descriptor_read_op_base*>(base));
+
+    buffer_sequence_adapter<asio::mutable_buffer,
+        MutableBufferSequence> bufs(o->buffers_);
+
+    return descriptor_ops::non_blocking_read(o->descriptor_,
+        bufs.buffers(), bufs.count(), o->ec_, o->bytes_transferred_);
+  }
+
+private:
+  int descriptor_;
+  MutableBufferSequence buffers_;
+};
+
+template <typename MutableBufferSequence, typename Handler>
+class descriptor_read_op
+  : public descriptor_read_op_base<MutableBufferSequence>
+{
+public:
+  ASIO_DEFINE_HANDLER_PTR(descriptor_read_op);
+
+  descriptor_read_op(int descriptor,
+      const MutableBufferSequence& buffers, Handler handler)
+    : descriptor_read_op_base<MutableBufferSequence>(
+        descriptor, buffers, &descriptor_read_op::do_complete),
+      handler_(handler)
+  {
+  }
+
+  static void do_complete(io_service_impl* owner, operation* base,
+      asio::error_code /*ec*/, std::size_t /*bytes_transferred*/)
+  {
+    // Take ownership of the handler object.
+    descriptor_read_op* o(static_cast<descriptor_read_op*>(base));
+    ptr p = { boost::addressof(o->handler_), o, o };
+
+    // Make a copy of the handler so that the memory can be deallocated before
+    // the upcall is made. Even if we're not about to make an upcall, a
+    // sub-object of the handler may be the true owner of the memory associated
+    // with the handler. Consequently, a local copy of the handler is required
+    // to ensure that any owning sub-object remains valid until after we have
+    // deallocated the memory here.
+    detail::binder2<Handler, asio::error_code, std::size_t>
+      handler(o->handler_, o->ec_, o->bytes_transferred_);
+    p.h = boost::addressof(handler.handler_);
+    p.reset();
+
+    // Make the upcall if required.
+    if (owner)
+    {
+      asio::detail::fenced_block b;
+      asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+    }
+  }
+
+private:
+  Handler handler_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
+#endif // ASIO_DETAIL_DESCRIPTOR_READ_OP_HPP
diff --git a/ext/asio/asio/detail/descriptor_write_op.hpp b/ext/asio/asio/detail/descriptor_write_op.hpp
new file mode 100644
index 0000000..9caa283
--- /dev/null
+++ b/ext/asio/asio/detail/descriptor_write_op.hpp
@@ -0,0 +1,114 @@
+//
+// detail/descriptor_write_op.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_DESCRIPTOR_WRITE_OP_HPP
+#define ASIO_DETAIL_DESCRIPTOR_WRITE_OP_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
+#include <boost/utility/addressof.hpp>
+#include "asio/detail/bind_handler.hpp"
+#include "asio/detail/buffer_sequence_adapter.hpp"
+#include "asio/detail/descriptor_ops.hpp"
+#include "asio/detail/fenced_block.hpp"
+#include "asio/detail/reactor_op.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename ConstBufferSequence>
+class descriptor_write_op_base : public reactor_op
+{
+public:
+  descriptor_write_op_base(int descriptor,
+      const ConstBufferSequence& buffers, func_type complete_func)
+    : reactor_op(&descriptor_write_op_base::do_perform, complete_func),
+      descriptor_(descriptor),
+      buffers_(buffers)
+  {
+  }
+
+  static bool do_perform(reactor_op* base)
+  {
+    descriptor_write_op_base* o(static_cast<descriptor_write_op_base*>(base));
+
+    buffer_sequence_adapter<asio::const_buffer,
+        ConstBufferSequence> bufs(o->buffers_);
+
+    return descriptor_ops::non_blocking_write(o->descriptor_,
+        bufs.buffers(), bufs.count(), o->ec_, o->bytes_transferred_);
+  }
+
+private:
+  int descriptor_;
+  ConstBufferSequence buffers_;
+};
+
+template <typename ConstBufferSequence, typename Handler>
+class descriptor_write_op
+  : public descriptor_write_op_base<ConstBufferSequence>
+{
+public:
+  ASIO_DEFINE_HANDLER_PTR(descriptor_write_op);
+
+  descriptor_write_op(int descriptor,
+      const ConstBufferSequence& buffers, Handler handler)
+    : descriptor_write_op_base<ConstBufferSequence>(
+        descriptor, buffers, &descriptor_write_op::do_complete),
+      handler_(handler)
+  {
+  }
+
+  static void do_complete(io_service_impl* owner, operation* base,
+      asio::error_code /*ec*/, std::size_t /*bytes_transferred*/)
+  {
+    // Take ownership of the handler object.
+    descriptor_write_op* o(static_cast<descriptor_write_op*>(base));
+    ptr p = { boost::addressof(o->handler_), o, o };
+
+    // Make a copy of the handler so that the memory can be deallocated before
+    // the upcall is made. Even if we're not about to make an upcall, a
+    // sub-object of the handler may be the true owner of the memory associated
+    // with the handler. Consequently, a local copy of the handler is required
+    // to ensure that any owning sub-object remains valid until after we have
+    // deallocated the memory here.
+    detail::binder2<Handler, asio::error_code, std::size_t>
+      handler(o->handler_, o->ec_, o->bytes_transferred_);
+    p.h = boost::addressof(handler.handler_);
+    p.reset();
+
+    // Make the upcall if required.
+    if (owner)
+    {
+      asio::detail::fenced_block b;
+      asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+    }
+  }
+
+private:
+  Handler handler_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
+#endif // ASIO_DETAIL_DESCRIPTOR_WRITE_OP_HPP
diff --git a/ext/asio/asio/detail/dev_poll_reactor.hpp b/ext/asio/asio/detail/dev_poll_reactor.hpp
index 1367b71..6bbf1b2 100644
--- a/ext/asio/asio/detail/dev_poll_reactor.hpp
+++ b/ext/asio/asio/detail/dev_poll_reactor.hpp
@@ -1,8 +1,8 @@
 //
-// dev_poll_reactor.hpp
-// ~~~~~~~~~~~~~~~~~~~~
+// detail/dev_poll_reactor.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,36 +15,28 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/dev_poll_reactor_fwd.hpp"
+#include "asio/detail/config.hpp"
 
 #if defined(ASIO_HAS_DEV_POLL)
 
-#include "asio/detail/push_options.hpp"
 #include <cstddef>
 #include <vector>
-#include <boost/config.hpp>
-#include <boost/date_time/posix_time/posix_time_types.hpp>
-#include <boost/throw_exception.hpp>
 #include <sys/devpoll.h>
-#include "asio/detail/pop_options.hpp"
-
-#include "asio/error.hpp"
-#include "asio/io_service.hpp"
-#include "asio/system_error.hpp"
+#include "asio/detail/dev_poll_reactor_fwd.hpp"
 #include "asio/detail/hash_map.hpp"
 #include "asio/detail/mutex.hpp"
 #include "asio/detail/op_queue.hpp"
 #include "asio/detail/reactor_op.hpp"
 #include "asio/detail/reactor_op_queue.hpp"
 #include "asio/detail/select_interrupter.hpp"
-#include "asio/detail/service_base.hpp"
 #include "asio/detail/socket_types.hpp"
 #include "asio/detail/timer_op.hpp"
 #include "asio/detail/timer_queue_base.hpp"
 #include "asio/detail/timer_queue_fwd.hpp"
 #include "asio/detail/timer_queue_set.hpp"
+#include "asio/io_service.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 namespace detail {
@@ -62,358 +54,93 @@ public:
   };
 
   // Constructor.
-  dev_poll_reactor(asio::io_service& io_service)
-    : asio::detail::service_base<dev_poll_reactor>(io_service),
-      io_service_(use_service<io_service_impl>(io_service)),
-      mutex_(),
-      dev_poll_fd_(do_dev_poll_create()),
-      interrupter_(),
-      shutdown_(false)
-  {
-    // Add the interrupter's descriptor to /dev/poll.
-    ::pollfd ev = { 0 };
-    ev.fd = interrupter_.read_descriptor();
-    ev.events = POLLIN | POLLERR;
-    ev.revents = 0;
-    ::write(dev_poll_fd_, &ev, sizeof(ev));
-  }
+  ASIO_DECL dev_poll_reactor(asio::io_service& io_service);
 
   // Destructor.
-  ~dev_poll_reactor()
-  {
-    shutdown_service();
-    ::close(dev_poll_fd_);
-  }
+  ASIO_DECL ~dev_poll_reactor();
 
   // Destroy all user-defined handler objects owned by the service.
-  void shutdown_service()
-  {
-    asio::detail::mutex::scoped_lock lock(mutex_);
-    shutdown_ = true;
-    lock.unlock();
-
-    op_queue<operation> ops;
-
-    for (int i = 0; i < max_ops; ++i)
-      op_queue_[i].get_all_operations(ops);
-
-    timer_queues_.get_all_timers(ops);
-  } 
+  ASIO_DECL void shutdown_service();
 
   // Initialise the task.
-  void init_task()
-  {
-    io_service_.init_task();
-  }
+  ASIO_DECL void init_task();
 
   // Register a socket with the reactor. Returns 0 on success, system error
   // code on failure.
-  int register_descriptor(socket_type, per_descriptor_data&)
+  ASIO_DECL int register_descriptor(socket_type, per_descriptor_data&);
+
+  // Post a reactor operation for immediate completion.
+  void post_immediate_completion(reactor_op* op)
   {
-    return 0;
+    io_service_.post_immediate_completion(op);
   }
 
   // Start a new operation. The reactor operation will be performed when the
   // given descriptor is flagged as ready, or an error has occurred.
-  void start_op(int op_type, socket_type descriptor,
-      per_descriptor_data&, reactor_op* op, bool allow_speculative)
-  {
-    asio::detail::mutex::scoped_lock lock(mutex_);
-
-    if (shutdown_)
-      return;
-
-    if (allow_speculative)
-    {
-      if (op_type != read_op || !op_queue_[except_op].has_operation(descriptor))
-      {
-        if (!op_queue_[op_type].has_operation(descriptor))
-        {
-          if (op->perform())
-          {
-            lock.unlock();
-            io_service_.post_immediate_completion(op);
-            return;
-          }
-        }
-      }
-    }
-
-    bool first = op_queue_[op_type].enqueue_operation(descriptor, op);
-    io_service_.work_started();
-    if (first)
-    {
-      ::pollfd& ev = add_pending_event_change(descriptor);
-      ev.events = POLLERR | POLLHUP;
-      if (op_type == read_op
-          || op_queue_[read_op].has_operation(descriptor))
-        ev.events |= POLLIN;
-      if (op_type == write_op
-          || op_queue_[write_op].has_operation(descriptor))
-        ev.events |= POLLOUT;
-      if (op_type == except_op
-          || op_queue_[except_op].has_operation(descriptor))
-        ev.events |= POLLPRI;
-      interrupter_.interrupt();
-    }
-  }
+  ASIO_DECL void start_op(int op_type, socket_type descriptor,
+      per_descriptor_data&, reactor_op* op, bool allow_speculative);
 
   // Cancel all operations associated with the given descriptor. The
   // handlers associated with the descriptor will be invoked with the
   // operation_aborted error.
-  void cancel_ops(socket_type descriptor, per_descriptor_data&)
-  {
-    asio::detail::mutex::scoped_lock lock(mutex_);
-    cancel_ops_unlocked(descriptor, asio::error::operation_aborted);
-  }
+  ASIO_DECL void cancel_ops(socket_type descriptor, per_descriptor_data&);
 
   // Cancel any operations that are running against the descriptor and remove
   // its registration from the reactor.
-  void close_descriptor(socket_type descriptor, per_descriptor_data&)
-  {
-    asio::detail::mutex::scoped_lock lock(mutex_);
-
-    // Remove the descriptor from /dev/poll.
-    ::pollfd& ev = add_pending_event_change(descriptor);
-    ev.events = POLLREMOVE;
-    interrupter_.interrupt();
-
-    // Cancel any outstanding operations associated with the descriptor.
-    cancel_ops_unlocked(descriptor, asio::error::operation_aborted);
-  }
+  ASIO_DECL void close_descriptor(
+      socket_type descriptor, per_descriptor_data&);
 
   // Add a new timer queue to the reactor.
   template <typename Time_Traits>
-  void add_timer_queue(timer_queue<Time_Traits>& timer_queue)
-  {
-    asio::detail::mutex::scoped_lock lock(mutex_);
-    timer_queues_.insert(&timer_queue);
-  }
+  void add_timer_queue(timer_queue<Time_Traits>& queue);
 
   // Remove a timer queue from the reactor.
   template <typename Time_Traits>
-  void remove_timer_queue(timer_queue<Time_Traits>& timer_queue)
-  {
-    asio::detail::mutex::scoped_lock lock(mutex_);
-    timer_queues_.erase(&timer_queue);
-  }
+  void remove_timer_queue(timer_queue<Time_Traits>& queue);
 
   // Schedule a new operation in the given timer queue to expire at the
   // specified absolute time.
   template <typename Time_Traits>
-  void schedule_timer(timer_queue<Time_Traits>& timer_queue,
-      const typename Time_Traits::time_type& time, timer_op* op, void* token)
-  {
-    asio::detail::mutex::scoped_lock lock(mutex_);
-    if (!shutdown_)
-    {
-      bool earliest = timer_queue.enqueue_timer(time, op, token);
-      io_service_.work_started();
-      if (earliest)
-        interrupter_.interrupt();
-    }
-  }
+  void schedule_timer(timer_queue<Time_Traits>& queue,
+      const typename Time_Traits::time_type& time,
+      typename timer_queue<Time_Traits>::per_timer_data& timer, timer_op* op);
 
   // Cancel the timer operations associated with the given token. Returns the
   // number of operations that have been posted or dispatched.
   template <typename Time_Traits>
-  std::size_t cancel_timer(timer_queue<Time_Traits>& timer_queue, void* token)
-  {
-    asio::detail::mutex::scoped_lock lock(mutex_);
-    op_queue<operation> ops;
-    std::size_t n = timer_queue.cancel_timer(token, ops);
-    lock.unlock();
-    io_service_.post_deferred_completions(ops);
-    return n;
-  }
+  std::size_t cancel_timer(timer_queue<Time_Traits>& queue,
+      typename timer_queue<Time_Traits>::per_timer_data& timer);
 
   // Run /dev/poll once until interrupted or events are ready to be dispatched.
-  void run(bool block, op_queue<operation>& ops)
-  {
-    asio::detail::mutex::scoped_lock lock(mutex_);
-
-    // We can return immediately if there's no work to do and the reactor is
-    // not supposed to block.
-    if (!block && op_queue_[read_op].empty() && op_queue_[write_op].empty()
-        && op_queue_[except_op].empty() && timer_queues_.all_empty())
-      return;
-
-    // Write the pending event registration changes to the /dev/poll descriptor.
-    std::size_t events_size = sizeof(::pollfd) * pending_event_changes_.size();
-    if (events_size > 0)
-    {
-      errno = 0;
-      int result = ::write(dev_poll_fd_,
-          &pending_event_changes_[0], events_size);
-      if (result != static_cast<int>(events_size))
-      {
-        asio::error_code ec = asio::error_code(
-            errno, asio::error::get_system_category());
-        for (std::size_t i = 0; i < pending_event_changes_.size(); ++i)
-        {
-          int descriptor = pending_event_changes_[i].fd;
-          for (int j = 0; j < max_ops; ++j)
-            op_queue_[j].cancel_operations(descriptor, ops, ec);
-        }
-      }
-      pending_event_changes_.clear();
-      pending_event_change_index_.clear();
-    }
-
-    int timeout = block ? get_timeout() : 0;
-    lock.unlock();
-
-    // Block on the /dev/poll descriptor.
-    ::pollfd events[128] = { { 0 } };
-    ::dvpoll dp = { 0 };
-    dp.dp_fds = events;
-    dp.dp_nfds = 128;
-    dp.dp_timeout = timeout;
-    int num_events = ::ioctl(dev_poll_fd_, DP_POLL, &dp);
-
-    lock.lock();
-
-    // Dispatch the waiting events.
-    for (int i = 0; i < num_events; ++i)
-    {
-      int descriptor = events[i].fd;
-      if (descriptor == interrupter_.read_descriptor())
-      {
-        interrupter_.reset();
-      }
-      else
-      {
-        bool more_reads = false;
-        bool more_writes = false;
-        bool more_except = false;
-
-        // Exception operations must be processed first to ensure that any
-        // out-of-band data is read before normal data.
-        if (events[i].events & (POLLPRI | POLLERR | POLLHUP))
-          more_except =
-            op_queue_[except_op].perform_operations(descriptor, ops);
-        else
-          more_except = op_queue_[except_op].has_operation(descriptor);
-
-        if (events[i].events & (POLLIN | POLLERR | POLLHUP))
-          more_reads = op_queue_[read_op].perform_operations(descriptor, ops);
-        else
-          more_reads = op_queue_[read_op].has_operation(descriptor);
-
-        if (events[i].events & (POLLOUT | POLLERR | POLLHUP))
-          more_writes = op_queue_[write_op].perform_operations(descriptor, ops);
-        else
-          more_writes = op_queue_[write_op].has_operation(descriptor);
-
-        if ((events[i].events & (POLLERR | POLLHUP)) != 0
-              && !more_except && !more_reads && !more_writes)
-        {
-          // If we have an event and no operations associated with the
-          // descriptor then we need to delete the descriptor from /dev/poll.
-          // The poll operation can produce POLLHUP or POLLERR events when there
-          // is no operation pending, so if we do not remove the descriptor we
-          // can end up in a tight polling loop.
-          ::pollfd ev = { 0 };
-          ev.fd = descriptor;
-          ev.events = POLLREMOVE;
-          ev.revents = 0;
-          ::write(dev_poll_fd_, &ev, sizeof(ev));
-        }
-        else
-        {
-          ::pollfd ev = { 0 };
-          ev.fd = descriptor;
-          ev.events = POLLERR | POLLHUP;
-          if (more_reads)
-            ev.events |= POLLIN;
-          if (more_writes)
-            ev.events |= POLLOUT;
-          if (more_except)
-            ev.events |= POLLPRI;
-          ev.revents = 0;
-          int result = ::write(dev_poll_fd_, &ev, sizeof(ev));
-          if (result != sizeof(ev))
-          {
-            asio::error_code ec(errno,
-                asio::error::get_system_category());
-            for (int j = 0; j < max_ops; ++j)
-              op_queue_[j].cancel_operations(descriptor, ops, ec);
-          }
-        }
-      }
-    }
-    timer_queues_.get_ready_timers(ops);
-  }
+  ASIO_DECL void run(bool block, op_queue<operation>& ops);
 
   // Interrupt the select loop.
-  void interrupt()
-  {
-    interrupter_.interrupt();
-  }
+  ASIO_DECL void interrupt();
 
 private:
   // Create the /dev/poll file descriptor. Throws an exception if the descriptor
   // cannot be created.
-  static int do_dev_poll_create()
-  {
-    int fd = ::open("/dev/poll", O_RDWR);
-    if (fd == -1)
-    {
-      boost::throw_exception(
-          asio::system_error(
-            asio::error_code(errno,
-              asio::error::get_system_category()),
-            "/dev/poll"));
-    }
-    return fd;
-  }
+  ASIO_DECL static int do_dev_poll_create();
+
+  // Helper function to add a new timer queue.
+  ASIO_DECL void do_add_timer_queue(timer_queue_base& queue);
+
+  // Helper function to remove a timer queue.
+  ASIO_DECL void do_remove_timer_queue(timer_queue_base& queue);
 
   // Get the timeout value for the /dev/poll DP_POLL operation. The timeout
   // value is returned as a number of milliseconds. A return value of -1
   // indicates that the poll should block indefinitely.
-  int get_timeout()
-  {
-    // By default we will wait no longer than 5 minutes. This will ensure that
-    // any changes to the system clock are detected after no longer than this.
-    return timer_queues_.wait_duration_msec(5 * 60 * 1000);
-  }
+  ASIO_DECL int get_timeout();
 
   // Cancel all operations associated with the given descriptor. The do_cancel
   // function of the handler objects will be invoked. This function does not
   // acquire the dev_poll_reactor's mutex.
-  void cancel_ops_unlocked(socket_type descriptor,
-      const asio::error_code& ec)
-  {
-    bool need_interrupt = false;
-    op_queue<operation> ops;
-    for (int i = 0; i < max_ops; ++i)
-      need_interrupt = op_queue_[i].cancel_operations(
-          descriptor, ops, ec) || need_interrupt;
-    io_service_.post_deferred_completions(ops);
-    if (need_interrupt)
-      interrupter_.interrupt();
-  }
+  ASIO_DECL void cancel_ops_unlocked(socket_type descriptor,
+      const asio::error_code& ec);
 
   // Add a pending event entry for the given descriptor.
-  ::pollfd& add_pending_event_change(int descriptor)
-  {
-    hash_map<int, std::size_t>::iterator iter
-      = pending_event_change_index_.find(descriptor);
-    if (iter == pending_event_change_index_.end())
-    {
-      std::size_t index = pending_event_changes_.size();
-      pending_event_changes_.reserve(pending_event_changes_.size() + 1);
-      pending_event_change_index_.insert(std::make_pair(descriptor, index));
-      pending_event_changes_.push_back(::pollfd());
-      pending_event_changes_[index].fd = descriptor;
-      pending_event_changes_[index].revents = 0;
-      return pending_event_changes_[index];
-    }
-    else
-    {
-      return pending_event_changes_[iter->second];
-    }
-  }
+  ASIO_DECL ::pollfd& add_pending_event_change(int descriptor);
 
   // The io_service implementation used to post completions.
   io_service_impl& io_service_;
@@ -446,8 +173,13 @@ private:
 } // namespace detail
 } // namespace asio
 
-#endif // defined(ASIO_HAS_DEV_POLL)
-
 #include "asio/detail/pop_options.hpp"
 
+#include "asio/detail/impl/dev_poll_reactor.hpp"
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/detail/impl/dev_poll_reactor.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
+#endif // defined(ASIO_HAS_DEV_POLL)
+
 #endif // ASIO_DETAIL_DEV_POLL_REACTOR_HPP
diff --git a/ext/asio/asio/detail/dev_poll_reactor_fwd.hpp b/ext/asio/asio/detail/dev_poll_reactor_fwd.hpp
index f7f1aeb..c54f5e1 100644
--- a/ext/asio/asio/detail/dev_poll_reactor_fwd.hpp
+++ b/ext/asio/asio/detail/dev_poll_reactor_fwd.hpp
@@ -1,8 +1,8 @@
 //
-// dev_poll_reactor_fwd.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~
+// detail/dev_poll_reactor_fwd.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,13 +15,9 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 
-#if !defined(ASIO_DISABLE_DEV_POLL)
-#if defined(__sun) // This service is only supported on Solaris.
-
-// Define this to indicate that /dev/poll is supported on the target platform.
-#define ASIO_HAS_DEV_POLL 1
+#if defined(ASIO_HAS_DEV_POLL)
 
 namespace asio {
 namespace detail {
@@ -31,9 +27,6 @@ class dev_poll_reactor;
 } // namespace detail
 } // namespace asio
 
-#endif // defined(__sun)
-#endif // !defined(ASIO_DISABLE_DEV_POLL)
-
-#include "asio/detail/pop_options.hpp"
+#endif // defined(ASIO_HAS_DEV_POLL)
 
 #endif // ASIO_DETAIL_DEV_POLL_REACTOR_FWD_HPP
diff --git a/ext/asio/asio/detail/epoll_reactor.hpp b/ext/asio/asio/detail/epoll_reactor.hpp
index 0a1eac0..a085766 100644
--- a/ext/asio/asio/detail/epoll_reactor.hpp
+++ b/ext/asio/asio/detail/epoll_reactor.hpp
@@ -1,8 +1,8 @@
 //
-// epoll_reactor.hpp
-// ~~~~~~~~~~~~~~~~~
+// detail/epoll_reactor.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,43 +15,24 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/epoll_reactor_fwd.hpp"
+#include "asio/detail/config.hpp"
 
 #if defined(ASIO_HAS_EPOLL)
 
-#include "asio/detail/push_options.hpp"
-#include <cstddef>
-#include <sys/epoll.h>
-#include <boost/config.hpp>
-#include <boost/throw_exception.hpp>
-#include "asio/detail/pop_options.hpp"
-
-#include "asio/error.hpp"
 #include "asio/io_service.hpp"
-#include "asio/system_error.hpp"
-#include "asio/detail/hash_map.hpp"
+#include "asio/detail/epoll_reactor_fwd.hpp"
 #include "asio/detail/mutex.hpp"
+#include "asio/detail/object_pool.hpp"
 #include "asio/detail/op_queue.hpp"
 #include "asio/detail/reactor_op.hpp"
 #include "asio/detail/select_interrupter.hpp"
-#include "asio/detail/service_base.hpp"
 #include "asio/detail/socket_types.hpp"
 #include "asio/detail/timer_op.hpp"
 #include "asio/detail/timer_queue_base.hpp"
 #include "asio/detail/timer_queue_fwd.hpp"
 #include "asio/detail/timer_queue_set.hpp"
 
-#if (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 8)
-# define ASIO_HAS_TIMERFD 1
-#endif // (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 8)
-
-#if defined(ASIO_HAS_TIMERFD)
-# include "asio/detail/push_options.hpp"
-# include <sys/timerfd.h>
-# include "asio/detail/pop_options.hpp"
-#endif // defined(ASIO_HAS_TIMERFD)
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 namespace detail {
@@ -64,357 +45,86 @@ public:
     connect_op = 1, except_op = 2, max_ops = 3 };
 
   // Per-descriptor queues.
-  struct descriptor_state
+  class descriptor_state
   {
-    descriptor_state() {}
-    descriptor_state(const descriptor_state&) {}
-    void operator=(const descriptor_state&) {}
-
+    friend class epoll_reactor;
+    friend class object_pool_access;
     mutex mutex_;
     op_queue<reactor_op> op_queue_[max_ops];
     bool shutdown_;
+    descriptor_state* next_;
+    descriptor_state* prev_;
   };
 
   // Per-descriptor data.
   typedef descriptor_state* per_descriptor_data;
 
   // Constructor.
-  epoll_reactor(asio::io_service& io_service)
-    : asio::detail::service_base<epoll_reactor>(io_service),
-      io_service_(use_service<io_service_impl>(io_service)),
-      mutex_(),
-      epoll_fd_(do_epoll_create()),
-#if defined(ASIO_HAS_TIMERFD)
-      timer_fd_(timerfd_create(CLOCK_MONOTONIC, 0)),
-#else // defined(ASIO_HAS_TIMERFD)
-      timer_fd_(-1),
-#endif // defined(ASIO_HAS_TIMERFD)
-      interrupter_(),
-      shutdown_(false)
-  {
-    // Add the interrupter's descriptor to epoll.
-    epoll_event ev = { 0, { 0 } };
-    ev.events = EPOLLIN | EPOLLERR | EPOLLET;
-    ev.data.ptr = &interrupter_;
-    epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, interrupter_.read_descriptor(), &ev);
-    interrupter_.interrupt();
-
-    // Add the timer descriptor to epoll.
-    if (timer_fd_ != -1)
-    {
-      ev.events = EPOLLIN | EPOLLERR;
-      ev.data.ptr = &timer_fd_;
-      epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, timer_fd_, &ev);
-    }
-  }
+  ASIO_DECL epoll_reactor(asio::io_service& io_service);
 
   // Destructor.
-  ~epoll_reactor()
-  {
-    close(epoll_fd_);
-    if (timer_fd_ != -1)
-      close(timer_fd_);
-  }
+  ASIO_DECL ~epoll_reactor();
 
   // Destroy all user-defined handler objects owned by the service.
-  void shutdown_service()
-  {
-    mutex::scoped_lock lock(mutex_);
-    shutdown_ = true;
-    lock.unlock();
-
-    op_queue<operation> ops;
-
-    descriptor_map::iterator iter = registered_descriptors_.begin();
-    descriptor_map::iterator end = registered_descriptors_.end();
-    while (iter != end)
-    {
-      for (int i = 0; i < max_ops; ++i)
-        ops.push(iter->second.op_queue_[i]);
-      iter->second.shutdown_ = true;
-      ++iter;
-    }
-
-    timer_queues_.get_all_timers(ops);
-  }
+  ASIO_DECL void shutdown_service();
 
   // Initialise the task.
-  void init_task()
-  {
-    io_service_.init_task();
-  }
+  ASIO_DECL void init_task();
 
   // Register a socket with the reactor. Returns 0 on success, system error
   // code on failure.
-  int register_descriptor(socket_type descriptor,
-      per_descriptor_data& descriptor_data)
-  {
-    mutex::scoped_lock lock(registered_descriptors_mutex_);
-
-    descriptor_map::iterator new_entry = registered_descriptors_.insert(
-          std::make_pair(descriptor, descriptor_state())).first;
-    descriptor_data = &new_entry->second;
-
-    epoll_event ev = { 0, { 0 } };
-    ev.events = EPOLLIN | EPOLLERR | EPOLLHUP | EPOLLOUT | EPOLLPRI | EPOLLET;
-    ev.data.ptr = descriptor_data;
-    int result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, descriptor, &ev);
-    if (result != 0)
-      return errno;
-
-    descriptor_data->shutdown_ = false;
+  ASIO_DECL int register_descriptor(socket_type descriptor,
+      per_descriptor_data& descriptor_data);
 
-    return 0;
+  // Post a reactor operation for immediate completion.
+  void post_immediate_completion(reactor_op* op)
+  {
+    io_service_.post_immediate_completion(op);
   }
 
   // Start a new operation. The reactor operation will be performed when the
   // given descriptor is flagged as ready, or an error has occurred.
-  void start_op(int op_type, socket_type descriptor,
+  ASIO_DECL void start_op(int op_type, socket_type descriptor,
       per_descriptor_data& descriptor_data,
-      reactor_op* op, bool allow_speculative)
-  {
-    mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
-    if (descriptor_data->shutdown_)
-      return;
-
-    if (descriptor_data->op_queue_[op_type].empty())
-    {
-      if (allow_speculative
-          && (op_type != read_op
-            || descriptor_data->op_queue_[except_op].empty()))
-      {
-        if (op->perform())
-        {
-          descriptor_lock.unlock();
-          io_service_.post_immediate_completion(op);
-          return;
-        }
-      }
-      else
-      {
-        epoll_event ev = { 0, { 0 } };
-        ev.events = EPOLLIN | EPOLLERR | EPOLLHUP
-          | EPOLLOUT | EPOLLPRI | EPOLLET;
-        ev.data.ptr = descriptor_data;
-        epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev);
-      }
-    }
-
-    descriptor_data->op_queue_[op_type].push(op);
-    io_service_.work_started();
-  }
+      reactor_op* op, bool allow_speculative);
 
   // Cancel all operations associated with the given descriptor. The
   // handlers associated with the descriptor will be invoked with the
   // operation_aborted error.
-  void cancel_ops(socket_type, per_descriptor_data& descriptor_data)
-  {
-    mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
-
-    op_queue<operation> ops;
-    for (int i = 0; i < max_ops; ++i)
-    {
-      while (reactor_op* op = descriptor_data->op_queue_[i].front())
-      {
-        op->ec_ = asio::error::operation_aborted;
-        descriptor_data->op_queue_[i].pop();
-        ops.push(op);
-      }
-    }
-
-    descriptor_lock.unlock();
-
-    io_service_.post_deferred_completions(ops);
-  }
+  ASIO_DECL void cancel_ops(socket_type descriptor,
+      per_descriptor_data& descriptor_data);
 
   // Cancel any operations that are running against the descriptor and remove
   // its registration from the reactor.
-  void close_descriptor(socket_type descriptor,
-      per_descriptor_data& descriptor_data)
-  {
-    mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
-    mutex::scoped_lock descriptors_lock(registered_descriptors_mutex_);
-
-    // Remove the descriptor from the set of known descriptors. The descriptor
-    // will be automatically removed from the epoll set when it is closed.
-    descriptor_data->shutdown_ = true;
-
-    op_queue<operation> ops;
-    for (int i = 0; i < max_ops; ++i)
-    {
-      while (reactor_op* op = descriptor_data->op_queue_[i].front())
-      {
-        op->ec_ = asio::error::operation_aborted;
-        descriptor_data->op_queue_[i].pop();
-        ops.push(op);
-      }
-    }
-
-    descriptor_lock.unlock();
-
-    registered_descriptors_.erase(descriptor);
-
-    descriptors_lock.unlock();
-
-    io_service_.post_deferred_completions(ops);
-  }
+  ASIO_DECL void close_descriptor(socket_type descriptor,
+      per_descriptor_data& descriptor_data);
 
   // Add a new timer queue to the reactor.
   template <typename Time_Traits>
-  void add_timer_queue(timer_queue<Time_Traits>& timer_queue)
-  {
-    mutex::scoped_lock lock(mutex_);
-    timer_queues_.insert(&timer_queue);
-  }
+  void add_timer_queue(timer_queue<Time_Traits>& timer_queue);
 
   // Remove a timer queue from the reactor.
   template <typename Time_Traits>
-  void remove_timer_queue(timer_queue<Time_Traits>& timer_queue)
-  {
-    mutex::scoped_lock lock(mutex_);
-    timer_queues_.erase(&timer_queue);
-  }
+  void remove_timer_queue(timer_queue<Time_Traits>& timer_queue);
 
   // Schedule a new operation in the given timer queue to expire at the
   // specified absolute time.
   template <typename Time_Traits>
-  void schedule_timer(timer_queue<Time_Traits>& timer_queue,
-      const typename Time_Traits::time_type& time, timer_op* op, void* token)
-  {
-    mutex::scoped_lock lock(mutex_);
-    if (!shutdown_)
-    {
-      bool earliest = timer_queue.enqueue_timer(time, op, token);
-      io_service_.work_started();
-      if (earliest)
-      {
-#if defined(ASIO_HAS_TIMERFD)
-        if (timer_fd_ != -1)
-        {
-          itimerspec new_timeout;
-          itimerspec old_timeout;
-          int flags = get_timeout(new_timeout);
-          timerfd_settime(timer_fd_, flags, &new_timeout, &old_timeout);
-          return;
-        }
-#endif // defined(ASIO_HAS_TIMERFD)
-        interrupter_.interrupt();
-      }
-    }
-  }
+  void schedule_timer(timer_queue<Time_Traits>& queue,
+      const typename Time_Traits::time_type& time,
+      typename timer_queue<Time_Traits>::per_timer_data& timer, timer_op* op);
 
   // Cancel the timer operations associated with the given token. Returns the
   // number of operations that have been posted or dispatched.
   template <typename Time_Traits>
-  std::size_t cancel_timer(timer_queue<Time_Traits>& timer_queue, void* token)
-  {
-    mutex::scoped_lock lock(mutex_);
-    op_queue<operation> ops;
-    std::size_t n = timer_queue.cancel_timer(token, ops);
-    lock.unlock();
-    io_service_.post_deferred_completions(ops);
-    return n;
-  }
+  std::size_t cancel_timer(timer_queue<Time_Traits>& queue,
+      typename timer_queue<Time_Traits>::per_timer_data& timer);
 
   // Run epoll once until interrupted or events are ready to be dispatched.
-  void run(bool block, op_queue<operation>& ops)
-  {
-    // Calculate a timeout only if timerfd is not used.
-    int timeout;
-    if (timer_fd_ != -1)
-      timeout = block ? -1 : 0;
-    else
-    {
-      mutex::scoped_lock lock(mutex_);
-      timeout = block ? get_timeout() : 0;
-    }
-
-    // Block on the epoll descriptor.
-    epoll_event events[128];
-    int num_events = epoll_wait(epoll_fd_, events, 128, timeout);
-
-#if defined(ASIO_HAS_TIMERFD)
-    bool check_timers = (timer_fd_ == -1);
-#else // defined(ASIO_HAS_TIMERFD)
-    bool check_timers = true;
-#endif // defined(ASIO_HAS_TIMERFD)
-
-    // Dispatch the waiting events.
-    for (int i = 0; i < num_events; ++i)
-    {
-      void* ptr = events[i].data.ptr;
-      if (ptr == &interrupter_)
-      {
-        // No need to reset the interrupter since we're leaving the descriptor
-        // in a ready-to-read state and relying on edge-triggered notifications
-        // to make it so that we only get woken up when the descriptor's epoll
-        // registration is updated.
-
-#if defined(ASIO_HAS_TIMERFD)
-        if (timer_fd_ == -1)
-          check_timers = true;
-#else // defined(ASIO_HAS_TIMERFD)
-        check_timers = true;
-#endif // defined(ASIO_HAS_TIMERFD)
-      }
-#if defined(ASIO_HAS_TIMERFD)
-      else if (ptr == &timer_fd_)
-      {
-        check_timers = true;
-      }
-#endif // defined(ASIO_HAS_TIMERFD)
-      else
-      {
-        descriptor_state* descriptor_data = static_cast<descriptor_state*>(ptr);
-        mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
-
-        // Exception operations must be processed first to ensure that any
-        // out-of-band data is read before normal data.
-        static const int flag[max_ops] = { EPOLLIN, EPOLLOUT, EPOLLPRI };
-        for (int j = max_ops - 1; j >= 0; --j)
-        {
-          if (events[i].events & (flag[j] | EPOLLERR | EPOLLHUP))
-          {
-            while (reactor_op* op = descriptor_data->op_queue_[j].front())
-            {
-              if (op->perform())
-              {
-                descriptor_data->op_queue_[j].pop();
-                ops.push(op);
-              }
-              else
-                break;
-            }
-          }
-        }
-      }
-    }
-
-    if (check_timers)
-    {
-      mutex::scoped_lock common_lock(mutex_);
-      timer_queues_.get_ready_timers(ops);
-
-#if defined(ASIO_HAS_TIMERFD)
-      if (timer_fd_ != -1)
-      {
-        itimerspec new_timeout;
-        itimerspec old_timeout;
-        int flags = get_timeout(new_timeout);
-        timerfd_settime(timer_fd_, flags, &new_timeout, &old_timeout);
-      }
-#endif // defined(ASIO_HAS_TIMERFD)
-    }
-  }
+  ASIO_DECL void run(bool block, op_queue<operation>& ops);
 
   // Interrupt the select loop.
-  void interrupt()
-  {
-    epoll_event ev = { 0, { 0 } };
-    ev.events = EPOLLIN | EPOLLERR | EPOLLET;
-    ev.data.ptr = &interrupter_;
-    epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, interrupter_.read_descriptor(), &ev);
-  }
+  ASIO_DECL void interrupt();
 
 private:
   // The hint to pass to epoll_create to size its data structures.
@@ -422,44 +132,26 @@ private:
 
   // Create the epoll file descriptor. Throws an exception if the descriptor
   // cannot be created.
-  static int do_epoll_create()
-  {
-    int fd = epoll_create(epoll_size);
-    if (fd == -1)
-    {
-      boost::throw_exception(
-          asio::system_error(
-            asio::error_code(errno,
-              asio::error::get_system_category()),
-            "epoll"));
-    }
-    return fd;
-  }
+  ASIO_DECL static int do_epoll_create();
+
+  // Helper function to add a new timer queue.
+  ASIO_DECL void do_add_timer_queue(timer_queue_base& queue);
+
+  // Helper function to remove a timer queue.
+  ASIO_DECL void do_remove_timer_queue(timer_queue_base& queue);
+
+  // Called to recalculate and update the timeout.
+  ASIO_DECL void update_timeout();
 
   // Get the timeout value for the epoll_wait call. The timeout value is
   // returned as a number of milliseconds. A return value of -1 indicates
   // that epoll_wait should block indefinitely.
-  int get_timeout()
-  {
-    // By default we will wait no longer than 5 minutes. This will ensure that
-    // any changes to the system clock are detected after no longer than this.
-    return timer_queues_.wait_duration_msec(5 * 60 * 1000);
-  }
+  ASIO_DECL int get_timeout();
 
 #if defined(ASIO_HAS_TIMERFD)
   // Get the timeout value for the timer descriptor. The return value is the
   // flag argument to be used when calling timerfd_settime.
-  int get_timeout(itimerspec& ts)
-  {
-    ts.it_interval.tv_sec = 0;
-    ts.it_interval.tv_nsec = 0;
-
-    long usec = timer_queues_.wait_duration_usec(5 * 60 * 1000 * 1000);
-    ts.it_value.tv_sec = usec / 1000000;
-    ts.it_value.tv_nsec = usec ? (usec % 1000000) * 1000 : 1;
-
-    return usec ? 0 : TFD_TIMER_ABSTIME;
-  }
+  ASIO_DECL int get_timeout(itimerspec& ts);
 #endif // defined(ASIO_HAS_TIMERFD)
 
   // The io_service implementation used to post completions.
@@ -486,22 +178,20 @@ private:
   // Mutex to protect access to the registered descriptors.
   mutex registered_descriptors_mutex_;
 
-  // Keep track of all registered descriptors. This code relies on the fact that
-  // the hash_map implementation pools deleted nodes, meaning that we can assume
-  // our descriptor_state pointer remains valid even after the entry is removed.
-  // Technically this is not true for C++98, as that standard says that spliced
-  // elements in a list are invalidated. However, C++0x fixes this shortcoming
-  // so we'll just assume that C++98 std::list implementations will do the right
-  // thing anyway.
-  typedef detail::hash_map<socket_type, descriptor_state> descriptor_map;
-  descriptor_map registered_descriptors_;
+  // Keep track of all registered descriptors.
+  object_pool<descriptor_state> registered_descriptors_;
 };
 
 } // namespace detail
 } // namespace asio
 
-#endif // defined(ASIO_HAS_EPOLL)
-
 #include "asio/detail/pop_options.hpp"
 
+#include "asio/detail/impl/epoll_reactor.hpp"
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/detail/impl/epoll_reactor.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
+#endif // defined(ASIO_HAS_EPOLL)
+
 #endif // ASIO_DETAIL_EPOLL_REACTOR_HPP
diff --git a/ext/asio/asio/detail/epoll_reactor_fwd.hpp b/ext/asio/asio/detail/epoll_reactor_fwd.hpp
index 266bccd..49df6ed 100644
--- a/ext/asio/asio/detail/epoll_reactor_fwd.hpp
+++ b/ext/asio/asio/detail/epoll_reactor_fwd.hpp
@@ -1,8 +1,8 @@
 //
-// epoll_reactor_fwd.hpp
-// ~~~~~~~~~~~~~~~~~~~~~
+// detail/epoll_reactor_fwd.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,19 +15,9 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 
-#if !defined(ASIO_DISABLE_EPOLL)
-#if defined(__linux__) // This service is only supported on Linux.
-
-#include "asio/detail/push_options.hpp"
-#include <linux/version.h>
-#include "asio/detail/pop_options.hpp"
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION (2,5,45) // Only kernels >= 2.5.45.
-
-// Define this to indicate that epoll is supported on the target platform.
-#define ASIO_HAS_EPOLL 1
+#if defined(ASIO_HAS_EPOLL)
 
 namespace asio {
 namespace detail {
@@ -37,10 +27,6 @@ class epoll_reactor;
 } // namespace detail
 } // namespace asio
 
-#endif // LINUX_VERSION_CODE >= KERNEL_VERSION (2,5,45)
-#endif // defined(__linux__)
-#endif // !defined(ASIO_DISABLE_EPOLL)
-
-#include "asio/detail/pop_options.hpp"
+#endif // defined(ASIO_HAS_EPOLL)
 
 #endif // ASIO_DETAIL_EPOLL_REACTOR_FWD_HPP
diff --git a/ext/asio/asio/detail/event.hpp b/ext/asio/asio/detail/event.hpp
index 65aa4cb..46ee8a6 100644
--- a/ext/asio/asio/detail/event.hpp
+++ b/ext/asio/asio/detail/event.hpp
@@ -1,8 +1,8 @@
 //
-// event.hpp
-// ~~~~~~~~~
+// detail/event.hpp
+// ~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,11 +15,7 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
+#include "asio/detail/config.hpp"
 
 #if !defined(BOOST_HAS_THREADS) || defined(ASIO_DISABLE_THREADS)
 # include "asio/detail/null_event.hpp"
@@ -45,6 +41,4 @@ typedef posix_event event;
 } // namespace detail
 } // namespace asio
 
-#include "asio/detail/pop_options.hpp"
-
 #endif // ASIO_DETAIL_EVENT_HPP
diff --git a/ext/asio/asio/detail/eventfd_select_interrupter.hpp b/ext/asio/asio/detail/eventfd_select_interrupter.hpp
index 63b7ac4..0d3b958 100644
--- a/ext/asio/asio/detail/eventfd_select_interrupter.hpp
+++ b/ext/asio/asio/detail/eventfd_select_interrupter.hpp
@@ -1,8 +1,8 @@
 //
-// eventfd_select_interrupter.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// detail/eventfd_select_interrupter.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 // Copyright (c) 2008 Roelof Naude (roelof.naude at gmail dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
@@ -16,36 +16,11 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include <boost/throw_exception.hpp>
-#include "asio/detail/pop_options.hpp"
-
-#if defined(__linux__)
-# if !defined(ASIO_DISABLE_EVENTFD)
-#  include <linux/version.h>
-#  if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
-#   define ASIO_HAS_EVENTFD
-#  endif // LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
-# endif // !defined(ASIO_DISABLE_EVENTFD)
-#endif // defined(__linux__)
+#include "asio/detail/config.hpp"
 
 #if defined(ASIO_HAS_EVENTFD)
 
 #include "asio/detail/push_options.hpp"
-#include <fcntl.h>
-#if __GLIBC__ == 2 && __GLIBC_MINOR__ < 8
-# include <asm/unistd.h>
-#else // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8
-# include <sys/eventfd.h>
-#endif // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8
-#include "asio/detail/pop_options.hpp"
-
-#include "asio/error.hpp"
-#include "asio/system_error.hpp"
-#include "asio/detail/socket_types.hpp"
 
 namespace asio {
 namespace detail {
@@ -54,87 +29,16 @@ class eventfd_select_interrupter
 {
 public:
   // Constructor.
-  eventfd_select_interrupter()
-  {
-#if __GLIBC__ == 2 && __GLIBC_MINOR__ < 8
-    write_descriptor_ = read_descriptor_ = syscall(__NR_eventfd, 0);
-#else // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8
-    write_descriptor_ = read_descriptor_ = ::eventfd(0, 0);
-#endif // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8
-    if (read_descriptor_ != -1)
-    {
-      ::fcntl(read_descriptor_, F_SETFL, O_NONBLOCK);
-    }
-    else
-    {
-      int pipe_fds[2];
-      if (pipe(pipe_fds) == 0)
-      {
-        read_descriptor_ = pipe_fds[0];
-        ::fcntl(read_descriptor_, F_SETFL, O_NONBLOCK);
-        write_descriptor_ = pipe_fds[1];
-        ::fcntl(write_descriptor_, F_SETFL, O_NONBLOCK);
-      }
-      else
-      {
-        asio::error_code ec(errno,
-            asio::error::get_system_category());
-        asio::system_error e(ec, "eventfd_select_interrupter");
-        boost::throw_exception(e);
-      }
-    }
-  }
+  ASIO_DECL eventfd_select_interrupter();
 
   // Destructor.
-  ~eventfd_select_interrupter()
-  {
-    if (write_descriptor_ != -1 && write_descriptor_ != read_descriptor_)
-      ::close(write_descriptor_);
-    if (read_descriptor_ != -1)
-      ::close(read_descriptor_);
-  }
+  ASIO_DECL ~eventfd_select_interrupter();
 
   // Interrupt the select call.
-  void interrupt()
-  {
-    uint64_t counter(1UL);
-    int result = ::write(write_descriptor_, &counter, sizeof(uint64_t));
-    (void)result;
-  }
+  ASIO_DECL void interrupt();
 
   // Reset the select interrupt. Returns true if the call was interrupted.
-  bool reset()
-  {
-    if (write_descriptor_ == read_descriptor_)
-    {
-      for (;;)
-      {
-        // Only perform one read. The kernel maintains an atomic counter.
-        uint64_t counter(0);
-        errno = 0;
-        int bytes_read = ::read(read_descriptor_, &counter, sizeof(uint64_t));
-        if (bytes_read < 0 && errno == EINTR)
-          continue;
-        bool was_interrupted = (bytes_read > 0);
-        return was_interrupted;
-      }
-    }
-    else
-    {
-      for (;;)
-      {
-        // Clear all data from the pipe.
-        char data[1024];
-        int bytes_read = ::read(read_descriptor_, data, sizeof(data));
-        if (bytes_read < 0 && errno == EINTR)
-          continue;
-        bool was_interrupted = (bytes_read > 0);
-        while (bytes_read == sizeof(data))
-          bytes_read = ::read(read_descriptor_, data, sizeof(data));
-        return was_interrupted;
-      }
-    }
-  }
+  ASIO_DECL bool reset();
 
   // Get the read descriptor to be passed to select.
   int read_descriptor() const
@@ -159,8 +63,12 @@ private:
 } // namespace detail
 } // namespace asio
 
-#endif // defined(ASIO_HAS_EVENTFD)
-
 #include "asio/detail/pop_options.hpp"
 
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/detail/impl/eventfd_select_interrupter.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
+#endif // defined(ASIO_HAS_EVENTFD)
+
 #endif // ASIO_DETAIL_EVENTFD_SELECT_INTERRUPTER_HPP
diff --git a/ext/asio/asio/detail/fd_set_adapter.hpp b/ext/asio/asio/detail/fd_set_adapter.hpp
index a575491..953cad1 100644
--- a/ext/asio/asio/detail/fd_set_adapter.hpp
+++ b/ext/asio/asio/detail/fd_set_adapter.hpp
@@ -1,8 +1,8 @@
 //
-// fd_set_adapter.hpp
-// ~~~~~~~~~~~~~~~~~~
+// detail/fd_set_adapter.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,12 +15,7 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
-
+#include "asio/detail/config.hpp"
 #include "asio/detail/posix_fd_set_adapter.hpp"
 #include "asio/detail/win_fd_set_adapter.hpp"
 
@@ -36,6 +31,4 @@ typedef posix_fd_set_adapter fd_set_adapter;
 } // namespace detail
 } // namespace asio
 
-#include "asio/detail/pop_options.hpp"
-
 #endif // ASIO_DETAIL_FD_SET_ADAPTER_HPP
diff --git a/ext/asio/asio/detail/fenced_block.hpp b/ext/asio/asio/detail/fenced_block.hpp
index 60198bc..70c47e1 100644
--- a/ext/asio/asio/detail/fenced_block.hpp
+++ b/ext/asio/asio/detail/fenced_block.hpp
@@ -1,8 +1,8 @@
 //
-// fenced_block.hpp
-// ~~~~~~~~~~~~~~~~
+// detail/fenced_block.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,23 +15,25 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
-
-#if !defined(BOOST_HAS_THREADS) || defined(ASIO_DISABLE_THREADS)
+#if !defined(BOOST_HAS_THREADS) \
+  || defined(ASIO_DISABLE_THREADS) \
+  || defined(ASIO_DISABLE_FENCED_BLOCK)
 # include "asio/detail/null_fenced_block.hpp"
 #elif defined(__MACH__) && defined(__APPLE__)
 # include "asio/detail/macos_fenced_block.hpp"
 #elif defined(__sun)
 # include "asio/detail/solaris_fenced_block.hpp"
+#elif defined(__GNUC__) && defined(__arm__)
+# include "asio/detail/gcc_arm_fenced_block.hpp"
+#elif defined(__GNUC__) && (defined(__hppa) || defined(__hppa__))
+# include "asio/detail/gcc_hppa_fenced_block.hpp"
 #elif defined(__GNUC__) \
   && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)) \
   && !defined(__INTEL_COMPILER) && !defined(__ICL) \
   && !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__)
-# include "asio/detail/gcc_fenced_block.hpp"
+# include "asio/detail/gcc_sync_fenced_block.hpp"
 #elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
 # include "asio/detail/gcc_x86_fenced_block.hpp"
 #elif defined(BOOST_WINDOWS) && !defined(UNDER_CE)
@@ -43,17 +45,23 @@
 namespace asio {
 namespace detail {
 
-#if !defined(BOOST_HAS_THREADS) || defined(ASIO_DISABLE_THREADS)
+#if !defined(BOOST_HAS_THREADS) \
+  || defined(ASIO_DISABLE_THREADS) \
+  || defined(ASIO_DISABLE_FENCED_BLOCK)
 typedef null_fenced_block fenced_block;
 #elif defined(__MACH__) && defined(__APPLE__)
 typedef macos_fenced_block fenced_block;
 #elif defined(__sun)
 typedef solaris_fenced_block fenced_block;
+#elif defined(__GNUC__) && defined(__arm__)
+typedef gcc_arm_fenced_block fenced_block;
+#elif defined(__GNUC__) && (defined(__hppa) || defined(__hppa__))
+typedef gcc_hppa_fenced_block fenced_block;
 #elif defined(__GNUC__) \
   && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)) \
   && !defined(__INTEL_COMPILER) && !defined(__ICL) \
   && !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__)
-typedef gcc_fenced_block fenced_block;
+typedef gcc_sync_fenced_block fenced_block;
 #elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
 typedef gcc_x86_fenced_block fenced_block;
 #elif defined(BOOST_WINDOWS) && !defined(UNDER_CE)
@@ -65,6 +73,4 @@ typedef null_fenced_block fenced_block;
 } // namespace detail
 } // namespace asio
 
-#include "asio/detail/pop_options.hpp"
-
 #endif // ASIO_DETAIL_FENCED_BLOCK_HPP
diff --git a/ext/asio/asio/detail/gcc_arm_fenced_block.hpp b/ext/asio/asio/detail/gcc_arm_fenced_block.hpp
new file mode 100644
index 0000000..76c4d99
--- /dev/null
+++ b/ext/asio/asio/detail/gcc_arm_fenced_block.hpp
@@ -0,0 +1,76 @@
+//
+// detail/gcc_arm_fenced_block.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_GCC_ARM_FENCED_BLOCK_HPP
+#define ASIO_DETAIL_GCC_ARM_FENCED_BLOCK_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(__GNUC__) && defined(__arm__)
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+class gcc_arm_fenced_block
+  : private noncopyable
+{
+public:
+  // Constructor.
+  gcc_arm_fenced_block()
+  {
+    barrier();
+  }
+
+  // Destructor.
+  ~gcc_arm_fenced_block()
+  {
+    barrier();
+  }
+
+private:
+  static void barrier()
+  {
+#if defined(__ARM_ARCH_4__) \
+    || defined(__ARM_ARCH_4T__) \
+    || defined(__ARM_ARCH_5__) \
+    || defined(__ARM_ARCH_5E__) \
+    || defined(__ARM_ARCH_5T__) \
+    || defined(__ARM_ARCH_5TE__) \
+    || defined(__ARM_ARCH_5TEJ__) \
+    || defined(__ARM_ARCH_6__) \
+    || defined(__ARM_ARCH_6J__) \
+    || defined(__ARM_ARCH_6K__) \
+    || defined(__ARM_ARCH_6Z__) \
+    || defined(__ARM_ARCH_6ZK__) \
+    || defined(__ARM_ARCH_6T2__)
+    int a = 0, b = 0;
+    __asm__ __volatile__ ("swp %0, %1, [%2]"
+        : "=&r"(a) : "r"(1), "r"(&b) : "memory", "cc");
+#else
+    // ARMv7 and later.
+    __asm__ __volatile__ ("dmb" : : : "memory");
+#endif
+  }
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(__GNUC__) && defined(__arm__)
+
+#endif // ASIO_DETAIL_GCC_ARM_FENCED_BLOCK_HPP
diff --git a/ext/asio/asio/detail/gcc_hppa_fenced_block.hpp b/ext/asio/asio/detail/gcc_hppa_fenced_block.hpp
new file mode 100644
index 0000000..215086a
--- /dev/null
+++ b/ext/asio/asio/detail/gcc_hppa_fenced_block.hpp
@@ -0,0 +1,58 @@
+//
+// detail/gcc_hppa_fenced_block.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_GCC_HPPA_FENCED_BLOCK_HPP
+#define ASIO_DETAIL_GCC_HPPA_FENCED_BLOCK_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(__GNUC__) && (defined(__hppa) || defined(__hppa__))
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+class gcc_hppa_fenced_block
+  : private noncopyable
+{
+public:
+  // Constructor.
+  gcc_hppa_fenced_block()
+  {
+    barrier();
+  }
+
+  // Destructor.
+  ~gcc_hppa_fenced_block()
+  {
+    barrier();
+  }
+
+private:
+  static void barrier()
+  {
+    // This is just a placeholder and almost certainly not sufficient.
+    __asm__ __volatile__ ("" : : : "memory");
+  }
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(__GNUC__) && (defined(__hppa) || defined(__hppa__))
+
+#endif // ASIO_DETAIL_GCC_HPPA_FENCED_BLOCK_HPP
diff --git a/ext/asio/asio/detail/gcc_sync_fenced_block.hpp b/ext/asio/asio/detail/gcc_sync_fenced_block.hpp
new file mode 100644
index 0000000..569b559
--- /dev/null
+++ b/ext/asio/asio/detail/gcc_sync_fenced_block.hpp
@@ -0,0 +1,61 @@
+//
+// detail/gcc_sync_fenced_block.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_GCC_SYNC_FENCED_BLOCK_HPP
+#define ASIO_DETAIL_GCC_SYNC_FENCED_BLOCK_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(__GNUC__) \
+  && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)) \
+  && !defined(__INTEL_COMPILER) && !defined(__ICL) \
+  && !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__)
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+class gcc_sync_fenced_block
+  : private noncopyable
+{
+public:
+  // Constructor.
+  gcc_sync_fenced_block()
+    : value_(0)
+  {
+    __sync_lock_test_and_set(&value_, 1);
+  }
+
+  // Destructor.
+  ~gcc_sync_fenced_block()
+  {
+    __sync_lock_release(&value_);
+  }
+
+private:
+  int value_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(__GNUC__)
+       // && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4))
+       // && !defined(__INTEL_COMPILER) && !defined(__ICL)
+       // && !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__)
+
+#endif // ASIO_DETAIL_GCC_SYNC_FENCED_BLOCK_HPP
diff --git a/ext/asio/asio/detail/gcc_x86_fenced_block.hpp b/ext/asio/asio/detail/gcc_x86_fenced_block.hpp
index 48119f4..3e2e5bc 100644
--- a/ext/asio/asio/detail/gcc_x86_fenced_block.hpp
+++ b/ext/asio/asio/detail/gcc_x86_fenced_block.hpp
@@ -1,8 +1,8 @@
 //
-// gcc_x86_fenced_block.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~
+// detail/gcc_x86_fenced_block.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,14 +15,12 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
+#include "asio/detail/config.hpp"
 
 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 namespace detail {
 
@@ -54,8 +52,8 @@ private:
 } // namespace detail
 } // namespace asio
 
-#endif // defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
-
 #include "asio/detail/pop_options.hpp"
 
+#endif // defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
+
 #endif // ASIO_DETAIL_GCC_X86_FENCED_BLOCK_HPP
diff --git a/ext/asio/asio/detail/handler_alloc_helpers.hpp b/ext/asio/asio/detail/handler_alloc_helpers.hpp
index 0ac42a7..9ae80de 100644
--- a/ext/asio/asio/detail/handler_alloc_helpers.hpp
+++ b/ext/asio/asio/detail/handler_alloc_helpers.hpp
@@ -1,8 +1,8 @@
 //
-// handler_alloc_helpers.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~
+// detail/handler_alloc_helpers.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,15 +15,13 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 #include <boost/detail/workaround.hpp>
 #include <boost/utility/addressof.hpp>
-#include "asio/detail/pop_options.hpp"
-
-#include "asio/handler_alloc_hook.hpp"
 #include "asio/detail/noncopyable.hpp"
+#include "asio/handler_alloc_hook.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 // Calls to asio_handler_allocate and asio_handler_deallocate must be made from
 // a namespace that does not contain any overloads of these functions. The
@@ -56,203 +54,31 @@ inline void deallocate(void* p, std::size_t s, Handler& h)
 
 } // namespace asio_handler_alloc_helpers
 
-namespace asio {
-namespace detail {
-
-// Traits for handler allocation.
-template <typename Handler, typename Object>
-struct handler_alloc_traits
-{
-  typedef Handler handler_type;
-  typedef Object value_type;
-  typedef Object* pointer_type;
-  BOOST_STATIC_CONSTANT(std::size_t, value_size = sizeof(Object));
-};
-
-template <typename Alloc_Traits>
-class handler_ptr;
-
-// Helper class to provide RAII on uninitialised handler memory.
-template <typename Alloc_Traits>
-class raw_handler_ptr
-  : private noncopyable
-{
-public:
-  typedef typename Alloc_Traits::handler_type handler_type;
-  typedef typename Alloc_Traits::value_type value_type;
-  typedef typename Alloc_Traits::pointer_type pointer_type;
-  BOOST_STATIC_CONSTANT(std::size_t, value_size = Alloc_Traits::value_size);
-
-  // Constructor allocates the memory.
-  raw_handler_ptr(handler_type& handler)
-    : handler_(handler),
-      pointer_(static_cast<pointer_type>(
-            asio_handler_alloc_helpers::allocate(value_size, handler_)))
-  {
-  }
-
-  // Destructor automatically deallocates memory, unless it has been stolen by
-  // a handler_ptr object.
-  ~raw_handler_ptr()
-  {
-    if (pointer_)
-      asio_handler_alloc_helpers::deallocate(
-          pointer_, value_size, handler_);
-  }
-
-private:
-  friend class handler_ptr<Alloc_Traits>;
-  handler_type& handler_;
-  pointer_type pointer_;
-};
-
-// Helper class to provide RAII on uninitialised handler memory.
-template <typename Alloc_Traits>
-class handler_ptr
-  : private noncopyable
-{
-public:
-  typedef typename Alloc_Traits::handler_type handler_type;
-  typedef typename Alloc_Traits::value_type value_type;
-  typedef typename Alloc_Traits::pointer_type pointer_type;
-  BOOST_STATIC_CONSTANT(std::size_t, value_size = Alloc_Traits::value_size);
-  typedef raw_handler_ptr<Alloc_Traits> raw_ptr_type;
-
-  // Take ownership of existing memory.
-  handler_ptr(handler_type& handler, pointer_type pointer)
-    : handler_(handler),
-      pointer_(pointer)
-  {
-  }
-
-  // Construct object in raw memory and take ownership if construction succeeds.
-  handler_ptr(raw_ptr_type& raw_ptr)
-    : handler_(raw_ptr.handler_),
-      pointer_(new (raw_ptr.pointer_) value_type)
-  {
-    raw_ptr.pointer_ = 0;
-  }
-
-  // Construct object in raw memory and take ownership if construction succeeds.
-  template <typename Arg1>
-  handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1)
-    : handler_(raw_ptr.handler_),
-      pointer_(new (raw_ptr.pointer_) value_type(a1))
-  {
-    raw_ptr.pointer_ = 0;
-  }
-
-  // Construct object in raw memory and take ownership if construction succeeds.
-  template <typename Arg1, typename Arg2>
-  handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1, Arg2& a2)
-    : handler_(raw_ptr.handler_),
-      pointer_(new (raw_ptr.pointer_) value_type(a1, a2))
-  {
-    raw_ptr.pointer_ = 0;
-  }
-
-  // Construct object in raw memory and take ownership if construction succeeds.
-  template <typename Arg1, typename Arg2, typename Arg3>
-  handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1, Arg2& a2, Arg3& a3)
-    : handler_(raw_ptr.handler_),
-      pointer_(new (raw_ptr.pointer_) value_type(a1, a2, a3))
-  {
-    raw_ptr.pointer_ = 0;
-  }
-
-  // Construct object in raw memory and take ownership if construction succeeds.
-  template <typename Arg1, typename Arg2, typename Arg3, typename Arg4>
-  handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1, Arg2& a2, Arg3& a3, Arg4& a4)
-    : handler_(raw_ptr.handler_),
-      pointer_(new (raw_ptr.pointer_) value_type(a1, a2, a3, a4))
-  {
-    raw_ptr.pointer_ = 0;
-  }
-
-  // Construct object in raw memory and take ownership if construction succeeds.
-  template <typename Arg1, typename Arg2, typename Arg3, typename Arg4,
-      typename Arg5>
-  handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1, Arg2& a2, Arg3& a3, Arg4& a4,
-      Arg5& a5)
-    : handler_(raw_ptr.handler_),
-      pointer_(new (raw_ptr.pointer_) value_type(a1, a2, a3, a4, a5))
-  {
-    raw_ptr.pointer_ = 0;
-  }
-
-  // Construct object in raw memory and take ownership if construction succeeds.
-  template <typename Arg1, typename Arg2, typename Arg3, typename Arg4,
-      typename Arg5, typename Arg6>
-  handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1, Arg2& a2, Arg3& a3, Arg4& a4,
-      Arg5& a5, Arg6& a6)
-    : handler_(raw_ptr.handler_),
-      pointer_(new (raw_ptr.pointer_) value_type(a1, a2, a3, a4, a5, a6))
-  {
-    raw_ptr.pointer_ = 0;
-  }
-
-  // Construct object in raw memory and take ownership if construction succeeds.
-  template <typename Arg1, typename Arg2, typename Arg3, typename Arg4,
-      typename Arg5, typename Arg6, typename Arg7>
-  handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1, Arg2& a2, Arg3& a3, Arg4& a4,
-      Arg5& a5, Arg6& a6, Arg7& a7)
-    : handler_(raw_ptr.handler_),
-      pointer_(new (raw_ptr.pointer_) value_type(a1, a2, a3, a4, a5, a6, a7))
-  {
-    raw_ptr.pointer_ = 0;
-  }
-
-  // Construct object in raw memory and take ownership if construction succeeds.
-  template <typename Arg1, typename Arg2, typename Arg3, typename Arg4,
-      typename Arg5, typename Arg6, typename Arg7, typename Arg8>
-  handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1, Arg2& a2, Arg3& a3, Arg4& a4,
-      Arg5& a5, Arg6& a6, Arg7& a7, Arg8& a8)
-    : handler_(raw_ptr.handler_),
-      pointer_(new (raw_ptr.pointer_) value_type(
-            a1, a2, a3, a4, a5, a6, a7, a8))
-  {
-    raw_ptr.pointer_ = 0;
-  }
-
-  // Destructor automatically deallocates memory, unless it has been released.
-  ~handler_ptr()
-  {
-    reset();
-  }
-
-  // Get the memory.
-  pointer_type get() const
-  {
-    return pointer_;
-  }
-
-  // Release ownership of the memory.
-  pointer_type release()
-  {
-    pointer_type tmp = pointer_;
-    pointer_ = 0;
-    return tmp;
-  }
-
-  // Explicitly destroy and deallocate the memory.
-  void reset()
-  {
-    if (pointer_)
-    {
-      pointer_->value_type::~value_type();
-      asio_handler_alloc_helpers::deallocate(
-          pointer_, value_size, handler_);
-      pointer_ = 0;
-    }
-  }
-
-private:
-  handler_type& handler_;
-  pointer_type pointer_;
-};
-
-} // namespace detail
-} // namespace asio
+#define ASIO_DEFINE_HANDLER_PTR(op) \
+  struct ptr \
+  { \
+    Handler* h; \
+    void* v; \
+    op* p; \
+    ~ptr() \
+    { \
+      reset(); \
+    } \
+    void reset() \
+    { \
+      if (p) \
+      { \
+        p->~op(); \
+        p = 0; \
+      } \
+      if (v) \
+      { \
+        asio_handler_alloc_helpers::deallocate(v, sizeof(op), *h); \
+        v = 0; \
+      } \
+    } \
+  } \
+  /**/
 
 #include "asio/detail/pop_options.hpp"
 
diff --git a/ext/asio/asio/detail/handler_invoke_helpers.hpp b/ext/asio/asio/detail/handler_invoke_helpers.hpp
index 8332567..5b122d9 100644
--- a/ext/asio/asio/detail/handler_invoke_helpers.hpp
+++ b/ext/asio/asio/detail/handler_invoke_helpers.hpp
@@ -1,8 +1,8 @@
 //
-// handler_invoke_helpers.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~
+// detail/handler_invoke_helpers.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,15 +15,13 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 #include <boost/detail/workaround.hpp>
 #include <boost/utility/addressof.hpp>
-#include "asio/detail/pop_options.hpp"
-
 #include "asio/handler_invoke_hook.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 // Calls to asio_handler_invoke must be made from a namespace that does not
 // contain overloads of this function. The asio_handler_invoke_helpers
 // namespace is defined here for that purpose.
diff --git a/ext/asio/asio/detail/hash_map.hpp b/ext/asio/asio/detail/hash_map.hpp
index b2a1517..a3957df 100644
--- a/ext/asio/asio/detail/hash_map.hpp
+++ b/ext/asio/asio/detail/hash_map.hpp
@@ -1,8 +1,8 @@
 //
-// hash_map.hpp
-// ~~~~~~~~~~~~
+// detail/hash_map.hpp
+// ~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,33 +15,38 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 #include <cassert>
 #include <list>
 #include <utility>
-#include <boost/functional/hash.hpp>
-#include "asio/detail/pop_options.hpp"
-
 #include "asio/detail/noncopyable.hpp"
-#include "asio/detail/socket_types.hpp"
+
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+# include "asio/detail/socket_types.hpp"
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 namespace detail {
 
-template <typename T>
-inline std::size_t calculate_hash_value(const T& t)
+inline std::size_t calculate_hash_value(int i)
+{
+  return static_cast<std::size_t>(i);
+}
+
+inline std::size_t calculate_hash_value(void* p)
 {
-  return boost::hash_value(t);
+  return reinterpret_cast<std::size_t>(p)
+    + (reinterpret_cast<std::size_t>(p) >> 3);
 }
 
-#if defined(_WIN64)
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
 inline std::size_t calculate_hash_value(SOCKET s)
 {
   return static_cast<std::size_t>(s);
 }
-#endif // defined(_WIN64)
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
 
 // Note: assumes K and V are POD types.
 template <typename K, typename V>
diff --git a/ext/asio/asio/detail/impl/descriptor_ops.ipp b/ext/asio/asio/detail/impl/descriptor_ops.ipp
new file mode 100644
index 0000000..8e0c27d
--- /dev/null
+++ b/ext/asio/asio/detail/impl/descriptor_ops.ipp
@@ -0,0 +1,382 @@
+//
+// detail/impl/descriptor_ops.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_IMPL_DESCRIPTOR_OPS_IPP
+#define ASIO_DETAIL_IMPL_DESCRIPTOR_OPS_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+#include <cerrno>
+#include "asio/detail/descriptor_ops.hpp"
+#include "asio/error.hpp"
+
+#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+namespace descriptor_ops {
+
+ASIO_DECL
+int open(const char* path, int flags, asio::error_code& ec)
+{
+  errno = 0;
+  int result = error_wrapper(::open(path, flags), ec);
+  if (result >= 0)
+    ec = asio::error_code();
+  return result;
+}
+
+ASIO_DECL
+int close(int d, state_type& state, asio::error_code& ec)
+{
+  int result = 0;
+  if (d != -1)
+  {
+    if (state & internal_non_blocking)
+    {
+#if defined(__SYMBIAN32__)
+      int flags = ::fcntl(d, F_GETFL, 0);
+      if (flags >= 0)
+        ::fcntl(d, F_SETFL, flags & ~O_NONBLOCK);
+#else // defined(__SYMBIAN32__)
+      ioctl_arg_type arg = 0;
+      ::ioctl(d, FIONBIO, &arg);
+#endif // defined(__SYMBIAN32__)
+      state &= ~internal_non_blocking;
+    }
+
+    errno = 0;
+    result = error_wrapper(::close(d), ec);
+  }
+
+  if (result == 0)
+    ec = asio::error_code();
+  return result;
+}
+
+ASIO_DECL
+bool set_internal_non_blocking(int d,
+    state_type& state, asio::error_code& ec)
+{
+  if (d == -1)
+  {
+    ec = asio::error::bad_descriptor;
+    return false;
+  }
+
+  errno = 0;
+#if defined(__SYMBIAN32__)
+  int result = error_wrapper(::fcntl(d, F_GETFL, 0), ec);
+  if (result >= 0)
+  {
+    errno = 0;
+    result = error_wrapper(::fcntl(d, F_SETFL, result | O_NONBLOCK), ec);
+  }
+#else // defined(__SYMBIAN32__)
+  ioctl_arg_type arg = 1;
+  int result = error_wrapper(::ioctl(d, FIONBIO, &arg), ec);
+#endif // defined(__SYMBIAN32__)
+
+  if (result >= 0)
+  {
+    ec = asio::error_code();
+    state |= internal_non_blocking;
+    return true;
+  }
+
+  return false;
+}
+
+ASIO_DECL
+std::size_t sync_read(int d, state_type state, buf* bufs,
+    std::size_t count, bool all_empty, asio::error_code& ec)
+{
+  if (d == -1)
+  {
+    ec = asio::error::bad_descriptor;
+    return 0;
+  }
+
+  // A request to read 0 bytes on a stream is a no-op.
+  if (all_empty)
+  {
+    ec = asio::error_code();
+    return 0;
+  }
+
+  // Read some data.
+  for (;;)
+  {
+    // Try to complete the operation without blocking.
+    errno = 0;
+    int bytes = error_wrapper(::readv(d, bufs, static_cast<int>(count)), ec);
+
+    // Check if operation succeeded.
+    if (bytes > 0)
+      return bytes;
+
+    // Check for EOF.
+    if (bytes == 0)
+    {
+      ec = asio::error::eof;
+      return 0;
+    }
+
+    // Operation failed.
+    if ((state & user_set_non_blocking)
+        || (ec != asio::error::would_block
+          && ec != asio::error::try_again))
+      return 0;
+
+    // Wait for descriptor to become ready.
+    if (descriptor_ops::poll_read(d, ec) < 0)
+      return 0;
+  }
+}
+
+ASIO_DECL
+bool non_blocking_read(int d, buf* bufs, std::size_t count,
+    asio::error_code& ec, std::size_t& bytes_transferred)
+{
+  for (;;)
+  {
+    // Read some data.
+    errno = 0;
+    int bytes = error_wrapper(::readv(d, bufs, static_cast<int>(count)), ec);
+
+    // Check for end of stream.
+    if (bytes == 0)
+    {
+      ec = asio::error::eof;
+      return true;
+    }
+
+    // Retry operation if interrupted by signal.
+    if (ec == asio::error::interrupted)
+      continue;
+
+    // Check if we need to run the operation again.
+    if (ec == asio::error::would_block
+        || ec == asio::error::try_again)
+      return false;
+
+    // Operation is complete.
+    if (bytes > 0)
+    {
+      ec = asio::error_code();
+      bytes_transferred = bytes;
+    }
+    else
+      bytes_transferred = 0;
+
+    return true;
+  }
+}
+
+ASIO_DECL
+std::size_t sync_write(int d, state_type state, const buf* bufs,
+    std::size_t count, bool all_empty, asio::error_code& ec)
+{
+  if (d == -1)
+  {
+    ec = asio::error::bad_descriptor;
+    return 0;
+  }
+
+  // A request to write 0 bytes on a stream is a no-op.
+  if (all_empty)
+  {
+    ec = asio::error_code();
+    return 0;
+  }
+
+  // Write some data.
+  for (;;)
+  {
+    // Try to complete the operation without blocking.
+    errno = 0;
+    int bytes = error_wrapper(::writev(d, bufs, static_cast<int>(count)), ec);
+
+    // Check if operation succeeded.
+    if (bytes > 0)
+      return bytes;
+
+    // Operation failed.
+    if ((state & user_set_non_blocking)
+        || (ec != asio::error::would_block
+          && ec != asio::error::try_again))
+      return 0;
+
+    // Wait for descriptor to become ready.
+    if (descriptor_ops::poll_write(d, ec) < 0)
+      return 0;
+  }
+}
+
+ASIO_DECL
+bool non_blocking_write(int d, const buf* bufs, std::size_t count,
+    asio::error_code& ec, std::size_t& bytes_transferred)
+{
+  for (;;)
+  {
+    // Write some data.
+    errno = 0;
+    int bytes = error_wrapper(::writev(d, bufs, static_cast<int>(count)), ec);
+
+    // Retry operation if interrupted by signal.
+    if (ec == asio::error::interrupted)
+      continue;
+
+    // Check if we need to run the operation again.
+    if (ec == asio::error::would_block
+        || ec == asio::error::try_again)
+      return false;
+
+    // Operation is complete.
+    if (bytes >= 0)
+    {
+      ec = asio::error_code();
+      bytes_transferred = bytes;
+    }
+    else
+      bytes_transferred = 0;
+
+    return true;
+  }
+}
+
+ASIO_DECL
+int ioctl(int d, state_type& state, long cmd,
+    ioctl_arg_type* arg, asio::error_code& ec)
+{
+  if (d == -1)
+  {
+    ec = asio::error::bad_descriptor;
+    return -1;
+  }
+
+  errno = 0;
+  int result = error_wrapper(::ioctl(d, cmd, arg), ec);
+
+  if (result >= 0)
+  {
+    ec = asio::error_code();
+
+    // When updating the non-blocking mode we always perform the ioctl syscall,
+    // even if the flags would otherwise indicate that the descriptor is
+    // already in the correct state. This ensures that the underlying
+    // descriptor is put into the state that has been requested by the user. If
+    // the ioctl syscall was successful then we need to update the flags to
+    // match.
+    if (cmd == static_cast<long>(FIONBIO))
+    {
+      if (*arg)
+      {
+        state |= user_set_non_blocking;
+      }
+      else
+      {
+        // Clearing the non-blocking mode always overrides any internally-set
+        // non-blocking flag. Any subsequent asynchronous operations will need
+        // to re-enable non-blocking I/O.
+        state &= ~(user_set_non_blocking | internal_non_blocking);
+      }
+    }
+  }
+
+  return result;
+}
+
+ASIO_DECL
+int fcntl(int d, long cmd, asio::error_code& ec)
+{
+  if (d == -1)
+  {
+    ec = asio::error::bad_descriptor;
+    return -1;
+  }
+
+  errno = 0;
+  int result = error_wrapper(::fcntl(d, cmd), ec);
+  if (result != -1)
+    ec = asio::error_code();
+  return result;
+}
+
+ASIO_DECL
+int fcntl(int d, long cmd, long arg, asio::error_code& ec)
+{
+  if (d == -1)
+  {
+    ec = asio::error::bad_descriptor;
+    return -1;
+  }
+
+  errno = 0;
+  int result = error_wrapper(::fcntl(d, cmd, arg), ec);
+  if (result != -1)
+    ec = asio::error_code();
+  return result;
+}
+
+ASIO_DECL
+int poll_read(int d, asio::error_code& ec)
+{
+  if (d == -1)
+  {
+    ec = asio::error::bad_descriptor;
+    return -1;
+  }
+
+  pollfd fds;
+  fds.fd = d;
+  fds.events = POLLIN;
+  fds.revents = 0;
+  errno = 0;
+  int result = error_wrapper(::poll(&fds, 1, -1), ec);
+  if (result >= 0)
+    ec = asio::error_code();
+  return result;
+}
+
+ASIO_DECL
+int poll_write(int d, asio::error_code& ec)
+{
+  if (d == -1)
+  {
+    ec = asio::error::bad_descriptor;
+    return -1;
+  }
+
+  pollfd fds;
+  fds.fd = d;
+  fds.events = POLLOUT;
+  fds.revents = 0;
+  errno = 0;
+  int result = error_wrapper(::poll(&fds, 1, -1), ec);
+  if (result >= 0)
+    ec = asio::error_code();
+  return result;
+}
+
+} // namespace descriptor_ops
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
+#endif // ASIO_DETAIL_IMPL_DESCRIPTOR_OPS_IPP
diff --git a/ext/asio/asio/detail/impl/dev_poll_reactor.hpp b/ext/asio/asio/detail/impl/dev_poll_reactor.hpp
new file mode 100644
index 0000000..7fbef82
--- /dev/null
+++ b/ext/asio/asio/detail/impl/dev_poll_reactor.hpp
@@ -0,0 +1,77 @@
+//
+// detail/impl/dev_poll_reactor.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_IMPL_DEV_POLL_REACTOR_HPP
+#define ASIO_DETAIL_IMPL_DEV_POLL_REACTOR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(ASIO_HAS_DEV_POLL)
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename Time_Traits>
+void dev_poll_reactor::add_timer_queue(timer_queue<Time_Traits>& queue)
+{
+  do_add_timer_queue(queue);
+}
+
+template <typename Time_Traits>
+void dev_poll_reactor::remove_timer_queue(timer_queue<Time_Traits>& queue)
+{
+  do_remove_timer_queue(queue);
+}
+
+template <typename Time_Traits>
+void dev_poll_reactor::schedule_timer(timer_queue<Time_Traits>& queue,
+    const typename Time_Traits::time_type& time,
+    typename timer_queue<Time_Traits>::per_timer_data& timer, timer_op* op)
+{
+  asio::detail::mutex::scoped_lock lock(mutex_);
+
+  if (shutdown_)
+  {
+    io_service_.post_immediate_completion(op);
+    return;
+  }
+
+  bool earliest = queue.enqueue_timer(time, timer, op);
+  io_service_.work_started();
+  if (earliest)
+    interrupter_.interrupt();
+}
+
+template <typename Time_Traits>
+std::size_t dev_poll_reactor::cancel_timer(timer_queue<Time_Traits>& queue,
+    typename timer_queue<Time_Traits>::per_timer_data& timer)
+{
+  asio::detail::mutex::scoped_lock lock(mutex_);
+  op_queue<operation> ops;
+  std::size_t n = queue.cancel_timer(timer, ops);
+  lock.unlock();
+  io_service_.post_deferred_completions(ops);
+  return n;
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(ASIO_HAS_DEV_POLL)
+
+#endif // ASIO_DETAIL_IMPL_DEV_POLL_REACTOR_HPP
diff --git a/ext/asio/asio/detail/impl/dev_poll_reactor.ipp b/ext/asio/asio/detail/impl/dev_poll_reactor.ipp
new file mode 100644
index 0000000..0d1456f
--- /dev/null
+++ b/ext/asio/asio/detail/impl/dev_poll_reactor.ipp
@@ -0,0 +1,338 @@
+//
+// detail/impl/dev_poll_reactor.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_IMPL_DEV_POLL_REACTOR_IPP
+#define ASIO_DETAIL_IMPL_DEV_POLL_REACTOR_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(ASIO_HAS_DEV_POLL)
+
+#include "asio/detail/dev_poll_reactor.hpp"
+#include "asio/detail/throw_error.hpp"
+#include "asio/error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+dev_poll_reactor::dev_poll_reactor(asio::io_service& io_service)
+  : asio::detail::service_base<dev_poll_reactor>(io_service),
+    io_service_(use_service<io_service_impl>(io_service)),
+    mutex_(),
+    dev_poll_fd_(do_dev_poll_create()),
+    interrupter_(),
+    shutdown_(false)
+{
+  // Add the interrupter's descriptor to /dev/poll.
+  ::pollfd ev = { 0 };
+  ev.fd = interrupter_.read_descriptor();
+  ev.events = POLLIN | POLLERR;
+  ev.revents = 0;
+  ::write(dev_poll_fd_, &ev, sizeof(ev));
+}
+
+dev_poll_reactor::~dev_poll_reactor()
+{
+  shutdown_service();
+  ::close(dev_poll_fd_);
+}
+
+void dev_poll_reactor::shutdown_service()
+{
+  asio::detail::mutex::scoped_lock lock(mutex_);
+  shutdown_ = true;
+  lock.unlock();
+
+  op_queue<operation> ops;
+
+  for (int i = 0; i < max_ops; ++i)
+    op_queue_[i].get_all_operations(ops);
+
+  timer_queues_.get_all_timers(ops);
+} 
+
+void dev_poll_reactor::init_task()
+{
+  io_service_.init_task();
+}
+
+int dev_poll_reactor::register_descriptor(socket_type, per_descriptor_data&)
+{
+  return 0;
+}
+
+void dev_poll_reactor::start_op(int op_type, socket_type descriptor,
+    dev_poll_reactor::per_descriptor_data&,
+    reactor_op* op, bool allow_speculative)
+{
+  asio::detail::mutex::scoped_lock lock(mutex_);
+
+  if (shutdown_)
+  {
+    post_immediate_completion(op);
+    return;
+  }
+
+  if (allow_speculative)
+  {
+    if (op_type != read_op || !op_queue_[except_op].has_operation(descriptor))
+    {
+      if (!op_queue_[op_type].has_operation(descriptor))
+      {
+        if (op->perform())
+        {
+          lock.unlock();
+          io_service_.post_immediate_completion(op);
+          return;
+        }
+      }
+    }
+  }
+
+  bool first = op_queue_[op_type].enqueue_operation(descriptor, op);
+  io_service_.work_started();
+  if (first)
+  {
+    ::pollfd& ev = add_pending_event_change(descriptor);
+    ev.events = POLLERR | POLLHUP;
+    if (op_type == read_op
+        || op_queue_[read_op].has_operation(descriptor))
+      ev.events |= POLLIN;
+    if (op_type == write_op
+        || op_queue_[write_op].has_operation(descriptor))
+      ev.events |= POLLOUT;
+    if (op_type == except_op
+        || op_queue_[except_op].has_operation(descriptor))
+      ev.events |= POLLPRI;
+    interrupter_.interrupt();
+  }
+}
+
+void dev_poll_reactor::cancel_ops(socket_type descriptor,
+    dev_poll_reactor::per_descriptor_data&)
+{
+  asio::detail::mutex::scoped_lock lock(mutex_);
+  cancel_ops_unlocked(descriptor, asio::error::operation_aborted);
+}
+
+void dev_poll_reactor::close_descriptor(socket_type descriptor,
+    dev_poll_reactor::per_descriptor_data&)
+{
+  asio::detail::mutex::scoped_lock lock(mutex_);
+
+  // Remove the descriptor from /dev/poll.
+  ::pollfd& ev = add_pending_event_change(descriptor);
+  ev.events = POLLREMOVE;
+  interrupter_.interrupt();
+
+  // Cancel any outstanding operations associated with the descriptor.
+  cancel_ops_unlocked(descriptor, asio::error::operation_aborted);
+}
+
+void dev_poll_reactor::run(bool block, op_queue<operation>& ops)
+{
+  asio::detail::mutex::scoped_lock lock(mutex_);
+
+  // We can return immediately if there's no work to do and the reactor is
+  // not supposed to block.
+  if (!block && op_queue_[read_op].empty() && op_queue_[write_op].empty()
+      && op_queue_[except_op].empty() && timer_queues_.all_empty())
+    return;
+
+  // Write the pending event registration changes to the /dev/poll descriptor.
+  std::size_t events_size = sizeof(::pollfd) * pending_event_changes_.size();
+  if (events_size > 0)
+  {
+    errno = 0;
+    int result = ::write(dev_poll_fd_,
+        &pending_event_changes_[0], events_size);
+    if (result != static_cast<int>(events_size))
+    {
+      asio::error_code ec = asio::error_code(
+          errno, asio::error::get_system_category());
+      for (std::size_t i = 0; i < pending_event_changes_.size(); ++i)
+      {
+        int descriptor = pending_event_changes_[i].fd;
+        for (int j = 0; j < max_ops; ++j)
+          op_queue_[j].cancel_operations(descriptor, ops, ec);
+      }
+    }
+    pending_event_changes_.clear();
+    pending_event_change_index_.clear();
+  }
+
+  int timeout = block ? get_timeout() : 0;
+  lock.unlock();
+
+  // Block on the /dev/poll descriptor.
+  ::pollfd events[128] = { { 0 } };
+  ::dvpoll dp = { 0 };
+  dp.dp_fds = events;
+  dp.dp_nfds = 128;
+  dp.dp_timeout = timeout;
+  int num_events = ::ioctl(dev_poll_fd_, DP_POLL, &dp);
+
+  lock.lock();
+
+  // Dispatch the waiting events.
+  for (int i = 0; i < num_events; ++i)
+  {
+    int descriptor = events[i].fd;
+    if (descriptor == interrupter_.read_descriptor())
+    {
+      interrupter_.reset();
+    }
+    else
+    {
+      bool more_reads = false;
+      bool more_writes = false;
+      bool more_except = false;
+
+      // Exception operations must be processed first to ensure that any
+      // out-of-band data is read before normal data.
+      if (events[i].events & (POLLPRI | POLLERR | POLLHUP))
+        more_except =
+          op_queue_[except_op].perform_operations(descriptor, ops);
+      else
+        more_except = op_queue_[except_op].has_operation(descriptor);
+
+      if (events[i].events & (POLLIN | POLLERR | POLLHUP))
+        more_reads = op_queue_[read_op].perform_operations(descriptor, ops);
+      else
+        more_reads = op_queue_[read_op].has_operation(descriptor);
+
+      if (events[i].events & (POLLOUT | POLLERR | POLLHUP))
+        more_writes = op_queue_[write_op].perform_operations(descriptor, ops);
+      else
+        more_writes = op_queue_[write_op].has_operation(descriptor);
+
+      if ((events[i].events & (POLLERR | POLLHUP)) != 0
+            && !more_except && !more_reads && !more_writes)
+      {
+        // If we have an event and no operations associated with the
+        // descriptor then we need to delete the descriptor from /dev/poll.
+        // The poll operation can produce POLLHUP or POLLERR events when there
+        // is no operation pending, so if we do not remove the descriptor we
+        // can end up in a tight polling loop.
+        ::pollfd ev = { 0 };
+        ev.fd = descriptor;
+        ev.events = POLLREMOVE;
+        ev.revents = 0;
+        ::write(dev_poll_fd_, &ev, sizeof(ev));
+      }
+      else
+      {
+        ::pollfd ev = { 0 };
+        ev.fd = descriptor;
+        ev.events = POLLERR | POLLHUP;
+        if (more_reads)
+          ev.events |= POLLIN;
+        if (more_writes)
+          ev.events |= POLLOUT;
+        if (more_except)
+          ev.events |= POLLPRI;
+        ev.revents = 0;
+        int result = ::write(dev_poll_fd_, &ev, sizeof(ev));
+        if (result != sizeof(ev))
+        {
+          asio::error_code ec(errno,
+              asio::error::get_system_category());
+          for (int j = 0; j < max_ops; ++j)
+            op_queue_[j].cancel_operations(descriptor, ops, ec);
+        }
+      }
+    }
+  }
+  timer_queues_.get_ready_timers(ops);
+}
+
+void dev_poll_reactor::interrupt()
+{
+  interrupter_.interrupt();
+}
+
+int dev_poll_reactor::do_dev_poll_create()
+{
+  int fd = ::open("/dev/poll", O_RDWR);
+  if (fd == -1)
+  {
+    asio::error_code ec(errno,
+        asio::error::get_system_category());
+    asio::detail::throw_error(ec, "/dev/poll");
+  }
+  return fd;
+}
+
+void dev_poll_reactor::do_add_timer_queue(timer_queue_base& queue)
+{
+  mutex::scoped_lock lock(mutex_);
+  timer_queues_.insert(&queue);
+}
+
+void dev_poll_reactor::do_remove_timer_queue(timer_queue_base& queue)
+{
+  mutex::scoped_lock lock(mutex_);
+  timer_queues_.erase(&queue);
+}
+
+int dev_poll_reactor::get_timeout()
+{
+  // By default we will wait no longer than 5 minutes. This will ensure that
+  // any changes to the system clock are detected after no longer than this.
+  return timer_queues_.wait_duration_msec(5 * 60 * 1000);
+}
+
+void dev_poll_reactor::cancel_ops_unlocked(socket_type descriptor,
+    const asio::error_code& ec)
+{
+  bool need_interrupt = false;
+  op_queue<operation> ops;
+  for (int i = 0; i < max_ops; ++i)
+    need_interrupt = op_queue_[i].cancel_operations(
+        descriptor, ops, ec) || need_interrupt;
+  io_service_.post_deferred_completions(ops);
+  if (need_interrupt)
+    interrupter_.interrupt();
+}
+
+::pollfd& dev_poll_reactor::add_pending_event_change(int descriptor)
+{
+  hash_map<int, std::size_t>::iterator iter
+    = pending_event_change_index_.find(descriptor);
+  if (iter == pending_event_change_index_.end())
+  {
+    std::size_t index = pending_event_changes_.size();
+    pending_event_changes_.reserve(pending_event_changes_.size() + 1);
+    pending_event_change_index_.insert(std::make_pair(descriptor, index));
+    pending_event_changes_.push_back(::pollfd());
+    pending_event_changes_[index].fd = descriptor;
+    pending_event_changes_[index].revents = 0;
+    return pending_event_changes_[index];
+  }
+  else
+  {
+    return pending_event_changes_[iter->second];
+  }
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(ASIO_HAS_DEV_POLL)
+
+#endif // ASIO_DETAIL_IMPL_DEV_POLL_REACTOR_IPP
diff --git a/ext/asio/asio/detail/impl/epoll_reactor.hpp b/ext/asio/asio/detail/impl/epoll_reactor.hpp
new file mode 100644
index 0000000..9f50a23
--- /dev/null
+++ b/ext/asio/asio/detail/impl/epoll_reactor.hpp
@@ -0,0 +1,75 @@
+//
+// detail/impl/epoll_reactor.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_IMPL_EPOLL_REACTOR_HPP
+#define ASIO_DETAIL_IMPL_EPOLL_REACTOR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#if defined(ASIO_HAS_EPOLL)
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename Time_Traits>
+void epoll_reactor::add_timer_queue(timer_queue<Time_Traits>& queue)
+{
+  do_add_timer_queue(queue);
+}
+
+template <typename Time_Traits>
+void epoll_reactor::remove_timer_queue(timer_queue<Time_Traits>& queue)
+{
+  do_remove_timer_queue(queue);
+}
+
+template <typename Time_Traits>
+void epoll_reactor::schedule_timer(timer_queue<Time_Traits>& queue,
+    const typename Time_Traits::time_type& time,
+    typename timer_queue<Time_Traits>::per_timer_data& timer, timer_op* op)
+{
+  mutex::scoped_lock lock(mutex_);
+
+  if (shutdown_)
+  {
+    io_service_.post_immediate_completion(op);
+    return;
+  }
+
+  bool earliest = queue.enqueue_timer(time, timer, op);
+  io_service_.work_started();
+  if (earliest)
+    update_timeout();
+}
+
+template <typename Time_Traits>
+std::size_t epoll_reactor::cancel_timer(timer_queue<Time_Traits>& queue,
+    typename timer_queue<Time_Traits>::per_timer_data& timer)
+{
+  mutex::scoped_lock lock(mutex_);
+  op_queue<operation> ops;
+  std::size_t n = queue.cancel_timer(timer, ops);
+  lock.unlock();
+  io_service_.post_deferred_completions(ops);
+  return n;
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(ASIO_HAS_EPOLL)
+
+#endif // ASIO_DETAIL_IMPL_EPOLL_REACTOR_HPP
diff --git a/ext/asio/asio/detail/impl/epoll_reactor.ipp b/ext/asio/asio/detail/impl/epoll_reactor.ipp
new file mode 100644
index 0000000..a95b8f2
--- /dev/null
+++ b/ext/asio/asio/detail/impl/epoll_reactor.ipp
@@ -0,0 +1,390 @@
+//
+// detail/impl/epoll_reactor.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_IMPL_EPOLL_REACTOR_IPP
+#define ASIO_DETAIL_IMPL_EPOLL_REACTOR_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(ASIO_HAS_EPOLL)
+
+#include <cstddef>
+#include <sys/epoll.h>
+#include "asio/detail/epoll_reactor.hpp"
+#include "asio/detail/throw_error.hpp"
+#include "asio/error.hpp"
+
+#if defined(ASIO_HAS_TIMERFD)
+# include <sys/timerfd.h>
+#endif // defined(ASIO_HAS_TIMERFD)
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+epoll_reactor::epoll_reactor(asio::io_service& io_service)
+  : asio::detail::service_base<epoll_reactor>(io_service),
+    io_service_(use_service<io_service_impl>(io_service)),
+    mutex_(),
+    epoll_fd_(do_epoll_create()),
+#if defined(ASIO_HAS_TIMERFD)
+    timer_fd_(timerfd_create(CLOCK_MONOTONIC, 0)),
+#else // defined(ASIO_HAS_TIMERFD)
+    timer_fd_(-1),
+#endif // defined(ASIO_HAS_TIMERFD)
+    interrupter_(),
+    shutdown_(false)
+{
+  // Add the interrupter's descriptor to epoll.
+  epoll_event ev = { 0, { 0 } };
+  ev.events = EPOLLIN | EPOLLERR | EPOLLET;
+  ev.data.ptr = &interrupter_;
+  epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, interrupter_.read_descriptor(), &ev);
+  interrupter_.interrupt();
+
+  // Add the timer descriptor to epoll.
+  if (timer_fd_ != -1)
+  {
+    ev.events = EPOLLIN | EPOLLERR;
+    ev.data.ptr = &timer_fd_;
+    epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, timer_fd_, &ev);
+  }
+}
+
+epoll_reactor::~epoll_reactor()
+{
+  close(epoll_fd_);
+  if (timer_fd_ != -1)
+    close(timer_fd_);
+}
+
+void epoll_reactor::shutdown_service()
+{
+  mutex::scoped_lock lock(mutex_);
+  shutdown_ = true;
+  lock.unlock();
+
+  op_queue<operation> ops;
+
+  while (descriptor_state* state = registered_descriptors_.first())
+  {
+    for (int i = 0; i < max_ops; ++i)
+      ops.push(state->op_queue_[i]);
+    state->shutdown_ = true;
+    registered_descriptors_.free(state);
+  }
+
+  timer_queues_.get_all_timers(ops);
+}
+
+void epoll_reactor::init_task()
+{
+  io_service_.init_task();
+}
+
+int epoll_reactor::register_descriptor(socket_type descriptor,
+    epoll_reactor::per_descriptor_data& descriptor_data)
+{
+  mutex::scoped_lock lock(registered_descriptors_mutex_);
+
+  descriptor_data = registered_descriptors_.alloc();
+  descriptor_data->shutdown_ = false;
+
+  lock.unlock();
+
+  epoll_event ev = { 0, { 0 } };
+  ev.events = EPOLLIN | EPOLLERR | EPOLLHUP | EPOLLOUT | EPOLLPRI | EPOLLET;
+  ev.data.ptr = descriptor_data;
+  int result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, descriptor, &ev);
+  if (result != 0)
+    return errno;
+
+  return 0;
+}
+
+void epoll_reactor::start_op(int op_type, socket_type descriptor,
+    epoll_reactor::per_descriptor_data& descriptor_data,
+    reactor_op* op, bool allow_speculative)
+{
+  if (!descriptor_data)
+  {
+    op->ec_ = asio::error::bad_descriptor;
+    post_immediate_completion(op);
+    return;
+  }
+
+  mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
+
+  if (descriptor_data->shutdown_)
+  {
+    post_immediate_completion(op);
+    return;
+  }
+
+  if (descriptor_data->op_queue_[op_type].empty())
+  {
+    if (allow_speculative
+        && (op_type != read_op
+          || descriptor_data->op_queue_[except_op].empty()))
+    {
+      if (op->perform())
+      {
+        descriptor_lock.unlock();
+        io_service_.post_immediate_completion(op);
+        return;
+      }
+    }
+    else
+    {
+      epoll_event ev = { 0, { 0 } };
+      ev.events = EPOLLIN | EPOLLERR | EPOLLHUP
+        | EPOLLOUT | EPOLLPRI | EPOLLET;
+      ev.data.ptr = descriptor_data;
+      epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev);
+    }
+  }
+
+  descriptor_data->op_queue_[op_type].push(op);
+  io_service_.work_started();
+}
+
+void epoll_reactor::cancel_ops(socket_type,
+    epoll_reactor::per_descriptor_data& descriptor_data)
+{
+  if (!descriptor_data)
+    return;
+
+  mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
+
+  op_queue<operation> ops;
+  for (int i = 0; i < max_ops; ++i)
+  {
+    while (reactor_op* op = descriptor_data->op_queue_[i].front())
+    {
+      op->ec_ = asio::error::operation_aborted;
+      descriptor_data->op_queue_[i].pop();
+      ops.push(op);
+    }
+  }
+
+  descriptor_lock.unlock();
+
+  io_service_.post_deferred_completions(ops);
+}
+
+void epoll_reactor::close_descriptor(socket_type,
+    epoll_reactor::per_descriptor_data& descriptor_data)
+{
+  if (!descriptor_data)
+    return;
+
+  mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
+  mutex::scoped_lock descriptors_lock(registered_descriptors_mutex_);
+
+  if (!descriptor_data->shutdown_)
+  {
+    // Remove the descriptor from the set of known descriptors. The descriptor
+    // will be automatically removed from the epoll set when it is closed.
+
+    op_queue<operation> ops;
+    for (int i = 0; i < max_ops; ++i)
+    {
+      while (reactor_op* op = descriptor_data->op_queue_[i].front())
+      {
+        op->ec_ = asio::error::operation_aborted;
+        descriptor_data->op_queue_[i].pop();
+        ops.push(op);
+      }
+    }
+
+    descriptor_data->shutdown_ = true;
+
+    descriptor_lock.unlock();
+
+    registered_descriptors_.free(descriptor_data);
+    descriptor_data = 0;
+
+    descriptors_lock.unlock();
+
+    io_service_.post_deferred_completions(ops);
+  }
+}
+
+void epoll_reactor::run(bool block, op_queue<operation>& ops)
+{
+  // Calculate a timeout only if timerfd is not used.
+  int timeout;
+  if (timer_fd_ != -1)
+    timeout = block ? -1 : 0;
+  else
+  {
+    mutex::scoped_lock lock(mutex_);
+    timeout = block ? get_timeout() : 0;
+  }
+
+  // Block on the epoll descriptor.
+  epoll_event events[128];
+  int num_events = epoll_wait(epoll_fd_, events, 128, timeout);
+
+#if defined(ASIO_HAS_TIMERFD)
+  bool check_timers = (timer_fd_ == -1);
+#else // defined(ASIO_HAS_TIMERFD)
+  bool check_timers = true;
+#endif // defined(ASIO_HAS_TIMERFD)
+
+  // Dispatch the waiting events.
+  for (int i = 0; i < num_events; ++i)
+  {
+    void* ptr = events[i].data.ptr;
+    if (ptr == &interrupter_)
+    {
+      // No need to reset the interrupter since we're leaving the descriptor
+      // in a ready-to-read state and relying on edge-triggered notifications
+      // to make it so that we only get woken up when the descriptor's epoll
+      // registration is updated.
+
+#if defined(ASIO_HAS_TIMERFD)
+      if (timer_fd_ == -1)
+        check_timers = true;
+#else // defined(ASIO_HAS_TIMERFD)
+      check_timers = true;
+#endif // defined(ASIO_HAS_TIMERFD)
+    }
+#if defined(ASIO_HAS_TIMERFD)
+    else if (ptr == &timer_fd_)
+    {
+      check_timers = true;
+    }
+#endif // defined(ASIO_HAS_TIMERFD)
+    else
+    {
+      descriptor_state* descriptor_data = static_cast<descriptor_state*>(ptr);
+      mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
+
+      // Exception operations must be processed first to ensure that any
+      // out-of-band data is read before normal data.
+      static const int flag[max_ops] = { EPOLLIN, EPOLLOUT, EPOLLPRI };
+      for (int j = max_ops - 1; j >= 0; --j)
+      {
+        if (events[i].events & (flag[j] | EPOLLERR | EPOLLHUP))
+        {
+          while (reactor_op* op = descriptor_data->op_queue_[j].front())
+          {
+            if (op->perform())
+            {
+              descriptor_data->op_queue_[j].pop();
+              ops.push(op);
+            }
+            else
+              break;
+          }
+        }
+      }
+    }
+  }
+
+  if (check_timers)
+  {
+    mutex::scoped_lock common_lock(mutex_);
+    timer_queues_.get_ready_timers(ops);
+
+#if defined(ASIO_HAS_TIMERFD)
+    if (timer_fd_ != -1)
+    {
+      itimerspec new_timeout;
+      itimerspec old_timeout;
+      int flags = get_timeout(new_timeout);
+      timerfd_settime(timer_fd_, flags, &new_timeout, &old_timeout);
+    }
+#endif // defined(ASIO_HAS_TIMERFD)
+  }
+}
+
+void epoll_reactor::interrupt()
+{
+  epoll_event ev = { 0, { 0 } };
+  ev.events = EPOLLIN | EPOLLERR | EPOLLET;
+  ev.data.ptr = &interrupter_;
+  epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, interrupter_.read_descriptor(), &ev);
+}
+
+int epoll_reactor::do_epoll_create()
+{
+  int fd = epoll_create(epoll_size);
+  if (fd == -1)
+  {
+    asio::error_code ec(errno,
+        asio::error::get_system_category());
+    asio::detail::throw_error(ec, "epoll");
+  }
+  return fd;
+}
+
+void epoll_reactor::do_add_timer_queue(timer_queue_base& queue)
+{
+  mutex::scoped_lock lock(mutex_);
+  timer_queues_.insert(&queue);
+}
+
+void epoll_reactor::do_remove_timer_queue(timer_queue_base& queue)
+{
+  mutex::scoped_lock lock(mutex_);
+  timer_queues_.erase(&queue);
+}
+
+void epoll_reactor::update_timeout()
+{
+#if defined(ASIO_HAS_TIMERFD)
+  if (timer_fd_ != -1)
+  {
+    itimerspec new_timeout;
+    itimerspec old_timeout;
+    int flags = get_timeout(new_timeout);
+    timerfd_settime(timer_fd_, flags, &new_timeout, &old_timeout);
+    return;
+  }
+#endif // defined(ASIO_HAS_TIMERFD)
+  interrupt();
+}
+
+int epoll_reactor::get_timeout()
+{
+  // By default we will wait no longer than 5 minutes. This will ensure that
+  // any changes to the system clock are detected after no longer than this.
+  return timer_queues_.wait_duration_msec(5 * 60 * 1000);
+}
+
+#if defined(ASIO_HAS_TIMERFD)
+int epoll_reactor::get_timeout(itimerspec& ts)
+{
+  ts.it_interval.tv_sec = 0;
+  ts.it_interval.tv_nsec = 0;
+
+  long usec = timer_queues_.wait_duration_usec(5 * 60 * 1000 * 1000);
+  ts.it_value.tv_sec = usec / 1000000;
+  ts.it_value.tv_nsec = usec ? (usec % 1000000) * 1000 : 1;
+
+  return usec ? 0 : TFD_TIMER_ABSTIME;
+}
+#endif // defined(ASIO_HAS_TIMERFD)
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(ASIO_HAS_EPOLL)
+
+#endif // ASIO_DETAIL_IMPL_EPOLL_REACTOR_IPP
diff --git a/ext/asio/asio/detail/impl/eventfd_select_interrupter.ipp b/ext/asio/asio/detail/impl/eventfd_select_interrupter.ipp
new file mode 100644
index 0000000..959d356
--- /dev/null
+++ b/ext/asio/asio/detail/impl/eventfd_select_interrupter.ipp
@@ -0,0 +1,125 @@
+//
+// detail/impl/eventfd_select_interrupter.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2008 Roelof Naude (roelof.naude at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_IMPL_EVENTFD_SELECT_INTERRUPTER_IPP
+#define ASIO_DETAIL_IMPL_EVENTFD_SELECT_INTERRUPTER_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(ASIO_HAS_EVENTFD)
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#if __GLIBC__ == 2 && __GLIBC_MINOR__ < 8
+# include <asm/unistd.h>
+#else // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8
+# include <sys/eventfd.h>
+#endif // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8
+#include "asio/detail/eventfd_select_interrupter.hpp"
+#include "asio/detail/throw_error.hpp"
+#include "asio/error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+eventfd_select_interrupter::eventfd_select_interrupter()
+{
+#if __GLIBC__ == 2 && __GLIBC_MINOR__ < 8
+  write_descriptor_ = read_descriptor_ = syscall(__NR_eventfd, 0);
+#else // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8
+  write_descriptor_ = read_descriptor_ = ::eventfd(0, 0);
+#endif // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8
+  if (read_descriptor_ != -1)
+  {
+    ::fcntl(read_descriptor_, F_SETFL, O_NONBLOCK);
+  }
+  else
+  {
+    int pipe_fds[2];
+    if (pipe(pipe_fds) == 0)
+    {
+      read_descriptor_ = pipe_fds[0];
+      ::fcntl(read_descriptor_, F_SETFL, O_NONBLOCK);
+      write_descriptor_ = pipe_fds[1];
+      ::fcntl(write_descriptor_, F_SETFL, O_NONBLOCK);
+    }
+    else
+    {
+      asio::error_code ec(errno,
+          asio::error::get_system_category());
+      asio::detail::throw_error(ec, "eventfd_select_interrupter");
+    }
+  }
+}
+
+eventfd_select_interrupter::~eventfd_select_interrupter()
+{
+  if (write_descriptor_ != -1 && write_descriptor_ != read_descriptor_)
+    ::close(write_descriptor_);
+  if (read_descriptor_ != -1)
+    ::close(read_descriptor_);
+}
+
+void eventfd_select_interrupter::interrupt()
+{
+  uint64_t counter(1UL);
+  int result = ::write(write_descriptor_, &counter, sizeof(uint64_t));
+  (void)result;
+}
+
+bool eventfd_select_interrupter::reset()
+{
+  if (write_descriptor_ == read_descriptor_)
+  {
+    for (;;)
+    {
+      // Only perform one read. The kernel maintains an atomic counter.
+      uint64_t counter(0);
+      errno = 0;
+      int bytes_read = ::read(read_descriptor_, &counter, sizeof(uint64_t));
+      if (bytes_read < 0 && errno == EINTR)
+        continue;
+      bool was_interrupted = (bytes_read > 0);
+      return was_interrupted;
+    }
+  }
+  else
+  {
+    for (;;)
+    {
+      // Clear all data from the pipe.
+      char data[1024];
+      int bytes_read = ::read(read_descriptor_, data, sizeof(data));
+      if (bytes_read < 0 && errno == EINTR)
+        continue;
+      bool was_interrupted = (bytes_read > 0);
+      while (bytes_read == sizeof(data))
+        bytes_read = ::read(read_descriptor_, data, sizeof(data));
+      return was_interrupted;
+    }
+  }
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(ASIO_HAS_EVENTFD)
+
+#endif // ASIO_DETAIL_IMPL_EVENTFD_SELECT_INTERRUPTER_IPP
diff --git a/ext/asio/asio/detail/impl/kqueue_reactor.hpp b/ext/asio/asio/detail/impl/kqueue_reactor.hpp
new file mode 100644
index 0000000..7950c3b
--- /dev/null
+++ b/ext/asio/asio/detail/impl/kqueue_reactor.hpp
@@ -0,0 +1,79 @@
+//
+// detail/impl/kqueue_reactor.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2005 Stefan Arentz (stefan at soze dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_IMPL_KQUEUE_REACTOR_HPP
+#define ASIO_DETAIL_IMPL_KQUEUE_REACTOR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(ASIO_HAS_KQUEUE)
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename Time_Traits>
+void kqueue_reactor::add_timer_queue(timer_queue<Time_Traits>& queue)
+{
+  do_add_timer_queue(queue);
+}
+
+// Remove a timer queue from the reactor.
+template <typename Time_Traits>
+void kqueue_reactor::remove_timer_queue(timer_queue<Time_Traits>& queue)
+{
+  do_remove_timer_queue(queue);
+}
+
+template <typename Time_Traits>
+void kqueue_reactor::schedule_timer(timer_queue<Time_Traits>& queue,
+    const typename Time_Traits::time_type& time,
+    typename timer_queue<Time_Traits>::per_timer_data& timer, timer_op* op)
+{
+  asio::detail::mutex::scoped_lock lock(mutex_);
+
+  if (shutdown_)
+  {
+    io_service_.post_immediate_completion(op);
+    return;
+  }
+
+  bool earliest = queue.enqueue_timer(time, timer, op);
+  io_service_.work_started();
+  if (earliest)
+    interrupt();
+}
+
+template <typename Time_Traits>
+std::size_t kqueue_reactor::cancel_timer(timer_queue<Time_Traits>& queue,
+    typename timer_queue<Time_Traits>::per_timer_data& timer)
+{
+  asio::detail::mutex::scoped_lock lock(mutex_);
+  op_queue<operation> ops;
+  std::size_t n = queue.cancel_timer(timer, ops);
+  lock.unlock();
+  io_service_.post_deferred_completions(ops);
+  return n;
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(ASIO_HAS_KQUEUE)
+
+#endif // ASIO_DETAIL_IMPL_KQUEUE_REACTOR_HPP
diff --git a/ext/asio/asio/detail/impl/kqueue_reactor.ipp b/ext/asio/asio/detail/impl/kqueue_reactor.ipp
new file mode 100644
index 0000000..8db77cb
--- /dev/null
+++ b/ext/asio/asio/detail/impl/kqueue_reactor.ipp
@@ -0,0 +1,385 @@
+//
+// detail/impl/kqueue_reactor.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2005 Stefan Arentz (stefan at soze dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_IMPL_KQUEUE_REACTOR_IPP
+#define ASIO_DETAIL_IMPL_KQUEUE_REACTOR_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(ASIO_HAS_KQUEUE)
+
+#include "asio/detail/kqueue_reactor.hpp"
+#include "asio/detail/throw_error.hpp"
+#include "asio/error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+#if defined(__NetBSD__)
+# define ASIO_KQUEUE_EV_SET(ev, ident, filt, flags, fflags, data, udata) \
+    EV_SET(ev, ident, filt, flags, fflags, \
+      data, reinterpret_cast<intptr_t>(udata))
+#else
+# define ASIO_KQUEUE_EV_SET(ev, ident, filt, flags, fflags, data, udata) \
+    EV_SET(ev, ident, filt, flags, fflags, data, udata)
+#endif
+
+namespace asio {
+namespace detail {
+
+kqueue_reactor::kqueue_reactor(asio::io_service& io_service)
+  : asio::detail::service_base<kqueue_reactor>(io_service),
+    io_service_(use_service<io_service_impl>(io_service)),
+    mutex_(),
+    kqueue_fd_(do_kqueue_create()),
+    interrupter_(),
+    shutdown_(false)
+{
+  // The interrupter is put into a permanently readable state. Whenever we
+  // want to interrupt the blocked kevent call we register a one-shot read
+  // operation against the descriptor.
+  interrupter_.interrupt();
+}
+
+kqueue_reactor::~kqueue_reactor()
+{
+  close(kqueue_fd_);
+}
+
+void kqueue_reactor::shutdown_service()
+{
+  mutex::scoped_lock lock(mutex_);
+  shutdown_ = true;
+  lock.unlock();
+
+  op_queue<operation> ops;
+
+  while (descriptor_state* state = registered_descriptors_.first())
+  {
+    for (int i = 0; i < max_ops; ++i)
+      ops.push(state->op_queue_[i]);
+    state->shutdown_ = true;
+    registered_descriptors_.free(state);
+  }
+
+  timer_queues_.get_all_timers(ops);
+}
+
+void kqueue_reactor::init_task()
+{
+  io_service_.init_task();
+}
+
+int kqueue_reactor::register_descriptor(socket_type,
+    kqueue_reactor::per_descriptor_data& descriptor_data)
+{
+  mutex::scoped_lock lock(registered_descriptors_mutex_);
+
+  descriptor_data = registered_descriptors_.alloc();
+  descriptor_data->shutdown_ = false;
+
+  return 0;
+}
+
+void kqueue_reactor::start_op(int op_type, socket_type descriptor,
+    kqueue_reactor::per_descriptor_data& descriptor_data,
+    reactor_op* op, bool allow_speculative)
+{
+  if (!descriptor_data)
+  {
+    op->ec_ = asio::error::bad_descriptor;
+    post_immediate_completion(op);
+    return;
+  }
+
+  mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
+
+  if (descriptor_data->shutdown_)
+  {
+    post_immediate_completion(op);
+    return;
+  }
+
+  bool first = descriptor_data->op_queue_[op_type].empty();
+  if (first)
+  {
+    if (allow_speculative)
+    {
+      if (op_type != read_op || descriptor_data->op_queue_[except_op].empty())
+      {
+        if (op->perform())
+        {
+          descriptor_lock.unlock();
+          io_service_.post_immediate_completion(op);
+          return;
+        }
+      }
+    }
+  }
+
+  descriptor_data->op_queue_[op_type].push(op);
+  io_service_.work_started();
+
+  if (first)
+  {
+    struct kevent event;
+    switch (op_type)
+    {
+    case read_op:
+      ASIO_KQUEUE_EV_SET(&event, descriptor, EVFILT_READ,
+          EV_ADD | EV_ONESHOT, 0, 0, descriptor_data);
+      break;
+    case write_op:
+      ASIO_KQUEUE_EV_SET(&event, descriptor, EVFILT_WRITE,
+          EV_ADD | EV_ONESHOT, 0, 0, descriptor_data);
+      break;
+    case except_op:
+      if (!descriptor_data->op_queue_[read_op].empty())
+        return; // Already registered for read events.
+      ASIO_KQUEUE_EV_SET(&event, descriptor, EVFILT_READ,
+          EV_ADD | EV_ONESHOT, EV_OOBAND, 0, descriptor_data);
+      break;
+    }
+
+    if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1)
+    {
+      op->ec_ = asio::error_code(errno,
+          asio::error::get_system_category());
+      descriptor_data->op_queue_[op_type].pop();
+      io_service_.post_deferred_completion(op);
+    }
+  }
+}
+
+void kqueue_reactor::cancel_ops(socket_type,
+    kqueue_reactor::per_descriptor_data& descriptor_data)
+{
+  if (!descriptor_data)
+    return;
+
+  mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
+
+  op_queue<operation> ops;
+  for (int i = 0; i < max_ops; ++i)
+  {
+    while (reactor_op* op = descriptor_data->op_queue_[i].front())
+    {
+      op->ec_ = asio::error::operation_aborted;
+      descriptor_data->op_queue_[i].pop();
+      ops.push(op);
+    }
+  }
+
+  descriptor_lock.unlock();
+
+  io_service_.post_deferred_completions(ops);
+}
+
+void kqueue_reactor::close_descriptor(socket_type,
+    kqueue_reactor::per_descriptor_data& descriptor_data)
+{
+  if (!descriptor_data)
+    return;
+
+  mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
+  mutex::scoped_lock descriptors_lock(registered_descriptors_mutex_);
+
+  if (!descriptor_data->shutdown_)
+  {
+    // Remove the descriptor from the set of known descriptors. The descriptor
+    // will be automatically removed from the kqueue set when it is closed.
+
+    op_queue<operation> ops;
+    for (int i = 0; i < max_ops; ++i)
+    {
+      while (reactor_op* op = descriptor_data->op_queue_[i].front())
+      {
+        op->ec_ = asio::error::operation_aborted;
+        descriptor_data->op_queue_[i].pop();
+        ops.push(op);
+      }
+    }
+
+    descriptor_data->shutdown_ = true;
+
+    descriptor_lock.unlock();
+
+    registered_descriptors_.free(descriptor_data);
+    descriptor_data = 0;
+
+    descriptors_lock.unlock();
+
+    io_service_.post_deferred_completions(ops);
+  }
+}
+
+void kqueue_reactor::run(bool block, op_queue<operation>& ops)
+{
+  mutex::scoped_lock lock(mutex_);
+
+  // Determine how long to block while waiting for events.
+  timespec timeout_buf = { 0, 0 };
+  timespec* timeout = block ? get_timeout(timeout_buf) : &timeout_buf;
+
+  lock.unlock();
+
+  // Block on the kqueue descriptor.
+  struct kevent events[128];
+  int num_events = kevent(kqueue_fd_, 0, 0, events, 128, timeout);
+
+  // Dispatch the waiting events.
+  for (int i = 0; i < num_events; ++i)
+  {
+    int descriptor = events[i].ident;
+    void* ptr = reinterpret_cast<void*>(events[i].udata);
+    if (ptr == &interrupter_)
+    {
+      // No need to reset the interrupter since we're leaving the descriptor
+      // in a ready-to-read state and relying on one-shot notifications.
+    }
+    else
+    {
+      descriptor_state* descriptor_data = static_cast<descriptor_state*>(ptr);
+      mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
+
+      // Exception operations must be processed first to ensure that any
+      // out-of-band data is read before normal data.
+#if defined(__NetBSD__)
+      static const unsigned int filter[max_ops] =
+#else
+      static const int filter[max_ops] =
+#endif
+        { EVFILT_READ, EVFILT_WRITE, EVFILT_READ };
+      for (int j = max_ops - 1; j >= 0; --j)
+      {
+        if (events[i].filter == filter[j])
+        {
+          if (j != except_op || events[i].flags & EV_OOBAND)
+          {
+            while (reactor_op* op = descriptor_data->op_queue_[j].front())
+            {
+              if (events[i].flags & EV_ERROR)
+              {
+                op->ec_ = asio::error_code(events[i].data,
+                    asio::error::get_system_category());
+                descriptor_data->op_queue_[j].pop();
+                ops.push(op);
+              }
+              if (op->perform())
+              {
+                descriptor_data->op_queue_[j].pop();
+                ops.push(op);
+              }
+              else
+                break;
+            }
+          }
+        }
+      }
+
+      // Renew registration for event notifications.
+      struct kevent event;
+      switch (events[i].filter)
+      {
+      case EVFILT_READ:
+        if (!descriptor_data->op_queue_[read_op].empty())
+          ASIO_KQUEUE_EV_SET(&event, descriptor, EVFILT_READ,
+              EV_ADD | EV_ONESHOT, 0, 0, descriptor_data);
+        else if (!descriptor_data->op_queue_[except_op].empty())
+          ASIO_KQUEUE_EV_SET(&event, descriptor, EVFILT_READ,
+              EV_ADD | EV_ONESHOT, EV_OOBAND, 0, descriptor_data);
+        else
+          continue;
+      case EVFILT_WRITE:
+        if (!descriptor_data->op_queue_[write_op].empty())
+          ASIO_KQUEUE_EV_SET(&event, descriptor, EVFILT_WRITE,
+              EV_ADD | EV_ONESHOT, 0, 0, descriptor_data);
+        else
+          continue;
+      default:
+        break;
+      }
+      if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1)
+      {
+        asio::error_code error(errno,
+            asio::error::get_system_category());
+        for (int j = 0; j < max_ops; ++j)
+        {
+          while (reactor_op* op = descriptor_data->op_queue_[j].front())
+          {
+            op->ec_ = error;
+            descriptor_data->op_queue_[j].pop();
+            ops.push(op);
+          }
+        }
+      }
+    }
+  }
+
+  lock.lock();
+  timer_queues_.get_ready_timers(ops);
+}
+
+void kqueue_reactor::interrupt()
+{
+  struct kevent event;
+  ASIO_KQUEUE_EV_SET(&event, interrupter_.read_descriptor(),
+      EVFILT_READ, EV_ADD | EV_ONESHOT, 0, 0, &interrupter_);
+  ::kevent(kqueue_fd_, &event, 1, 0, 0, 0);
+}
+
+int kqueue_reactor::do_kqueue_create()
+{
+  int fd = ::kqueue();
+  if (fd == -1)
+  {
+    asio::error_code ec(errno,
+        asio::error::get_system_category());
+    asio::detail::throw_error(ec, "kqueue");
+  }
+  return fd;
+}
+
+void kqueue_reactor::do_add_timer_queue(timer_queue_base& queue)
+{
+  mutex::scoped_lock lock(mutex_);
+  timer_queues_.insert(&queue);
+}
+
+void kqueue_reactor::do_remove_timer_queue(timer_queue_base& queue)
+{
+  mutex::scoped_lock lock(mutex_);
+  timer_queues_.erase(&queue);
+}
+
+timespec* kqueue_reactor::get_timeout(timespec& ts)
+{
+  // By default we will wait no longer than 5 minutes. This will ensure that
+  // any changes to the system clock are detected after no longer than this.
+  long usec = timer_queues_.wait_duration_usec(5 * 60 * 1000 * 1000);
+  ts.tv_sec = usec / 1000000;
+  ts.tv_nsec = (usec % 1000000) * 1000;
+  return &ts;
+}
+
+} // namespace detail
+} // namespace asio
+
+#undef ASIO_KQUEUE_EV_SET
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(ASIO_HAS_KQUEUE)
+
+#endif // ASIO_DETAIL_IMPL_KQUEUE_REACTOR_IPP
diff --git a/ext/asio/asio/detail/impl/pipe_select_interrupter.ipp b/ext/asio/asio/detail/impl/pipe_select_interrupter.ipp
new file mode 100644
index 0000000..aac20d4
--- /dev/null
+++ b/ext/asio/asio/detail/impl/pipe_select_interrupter.ipp
@@ -0,0 +1,96 @@
+//
+// detail/impl/pipe_select_interrupter.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_IMPL_PIPE_SELECT_INTERRUPTER_IPP
+#define ASIO_DETAIL_IMPL_PIPE_SELECT_INTERRUPTER_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if !defined(BOOST_WINDOWS)
+#if !defined(__CYGWIN__)
+#if !defined(__SYMBIAN32__)
+#if !defined(ASIO_HAS_EVENTFD)
+
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include "asio/detail/pipe_select_interrupter.hpp"
+#include "asio/detail/throw_error.hpp"
+#include "asio/error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+pipe_select_interrupter::pipe_select_interrupter()
+{
+  int pipe_fds[2];
+  if (pipe(pipe_fds) == 0)
+  {
+    read_descriptor_ = pipe_fds[0];
+    ::fcntl(read_descriptor_, F_SETFL, O_NONBLOCK);
+    write_descriptor_ = pipe_fds[1];
+    ::fcntl(write_descriptor_, F_SETFL, O_NONBLOCK);
+  }
+  else
+  {
+    asio::error_code ec(errno,
+        asio::error::get_system_category());
+    asio::detail::throw_error(ec, "pipe_select_interrupter");
+  }
+}
+
+pipe_select_interrupter::~pipe_select_interrupter()
+{
+  if (read_descriptor_ != -1)
+    ::close(read_descriptor_);
+  if (write_descriptor_ != -1)
+    ::close(write_descriptor_);
+}
+
+void pipe_select_interrupter::interrupt()
+{
+  char byte = 0;
+  int result = ::write(write_descriptor_, &byte, 1);
+  (void)result;
+}
+
+bool pipe_select_interrupter::reset()
+{
+  for (;;)
+  {
+    char data[1024];
+    int bytes_read = ::read(read_descriptor_, data, sizeof(data));
+    if (bytes_read < 0 && errno == EINTR)
+      continue;
+    bool was_interrupted = (bytes_read > 0);
+    while (bytes_read == sizeof(data))
+      bytes_read = ::read(read_descriptor_, data, sizeof(data));
+    return was_interrupted;
+  }
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // !defined(ASIO_HAS_EVENTFD)
+#endif // !defined(__SYMBIAN32__)
+#endif // !defined(__CYGWIN__)
+#endif // !defined(BOOST_WINDOWS)
+
+#endif // ASIO_DETAIL_IMPL_PIPE_SELECT_INTERRUPTER_IPP
diff --git a/ext/asio/asio/detail/impl/posix_event.ipp b/ext/asio/asio/detail/impl/posix_event.ipp
new file mode 100644
index 0000000..3206418
--- /dev/null
+++ b/ext/asio/asio/detail/impl/posix_event.ipp
@@ -0,0 +1,46 @@
+//
+// detail/impl/posix_event.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_IMPL_POSIX_EVENT_IPP
+#define ASIO_DETAIL_IMPL_POSIX_EVENT_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(BOOST_HAS_PTHREADS) && !defined(ASIO_DISABLE_THREADS)
+
+#include "asio/detail/posix_event.hpp"
+#include "asio/detail/throw_error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+posix_event::posix_event()
+  : signalled_(false)
+{
+  int error = ::pthread_cond_init(&cond_, 0);
+  asio::error_code ec(error,
+      asio::error::get_system_category());
+  asio::detail::throw_error(ec, "event");
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(BOOST_HAS_PTHREADS) && !defined(ASIO_DISABLE_THREADS)
+
+#endif // ASIO_DETAIL_IMPL_POSIX_EVENT_IPP
diff --git a/ext/asio/asio/detail/impl/posix_mutex.ipp b/ext/asio/asio/detail/impl/posix_mutex.ipp
new file mode 100644
index 0000000..12b6659
--- /dev/null
+++ b/ext/asio/asio/detail/impl/posix_mutex.ipp
@@ -0,0 +1,46 @@
+//
+// detail/impl/posix_mutex.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_IMPL_POSIX_MUTEX_IPP
+#define ASIO_DETAIL_IMPL_POSIX_MUTEX_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(BOOST_HAS_PTHREADS) && !defined(ASIO_DISABLE_THREADS)
+
+#include "asio/detail/posix_mutex.hpp"
+#include "asio/detail/throw_error.hpp"
+#include "asio/error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+posix_mutex::posix_mutex()
+{
+  int error = ::pthread_mutex_init(&mutex_, 0);
+  asio::error_code ec(error,
+      asio::error::get_system_category());
+  asio::detail::throw_error(ec, "mutex");
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(BOOST_HAS_PTHREADS) && !defined(ASIO_DISABLE_THREADS)
+
+#endif // ASIO_DETAIL_IMPL_POSIX_MUTEX_IPP
diff --git a/ext/asio/asio/detail/impl/posix_thread.ipp b/ext/asio/asio/detail/impl/posix_thread.ipp
new file mode 100644
index 0000000..ce91c57
--- /dev/null
+++ b/ext/asio/asio/detail/impl/posix_thread.ipp
@@ -0,0 +1,74 @@
+//
+// detail/impl/posix_thread.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_IMPL_POSIX_THREAD_IPP
+#define ASIO_DETAIL_IMPL_POSIX_THREAD_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(BOOST_HAS_PTHREADS) && !defined(ASIO_DISABLE_THREADS)
+
+#include "asio/detail/posix_thread.hpp"
+#include "asio/detail/throw_error.hpp"
+#include "asio/error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+posix_thread::~posix_thread()
+{
+  if (!joined_)
+    ::pthread_detach(thread_);
+}
+
+void posix_thread::join()
+{
+  if (!joined_)
+  {
+    ::pthread_join(thread_, 0);
+    joined_ = true;
+  }
+}
+
+void posix_thread::start_thread(func_base* arg)
+{
+  int error = ::pthread_create(&thread_, 0,
+        asio_detail_posix_thread_function, arg);
+  if (error != 0)
+  {
+    delete arg;
+    asio::error_code ec(error,
+        asio::error::get_system_category());
+    asio::detail::throw_error(ec, "thread");
+  }
+}
+
+void* asio_detail_posix_thread_function(void* arg)
+{
+  posix_thread::auto_func_base_ptr func = {
+      static_cast<posix_thread::func_base*>(arg) };
+  func.ptr->run();
+  return 0;
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(BOOST_HAS_PTHREADS) && !defined(ASIO_DISABLE_THREADS)
+
+#endif // ASIO_DETAIL_IMPL_POSIX_THREAD_IPP
diff --git a/ext/asio/asio/detail/impl/posix_tss_ptr.ipp b/ext/asio/asio/detail/impl/posix_tss_ptr.ipp
new file mode 100644
index 0000000..89b40f7
--- /dev/null
+++ b/ext/asio/asio/detail/impl/posix_tss_ptr.ipp
@@ -0,0 +1,46 @@
+//
+// detail/impl/posix_tss_ptr.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_IMPL_POSIX_TSS_PTR_IPP
+#define ASIO_DETAIL_IMPL_POSIX_TSS_PTR_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(BOOST_HAS_PTHREADS) && !defined(ASIO_DISABLE_THREADS)
+
+#include "asio/detail/posix_tss_ptr.hpp"
+#include "asio/detail/throw_error.hpp"
+#include "asio/error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+void posix_tss_ptr_create(pthread_key_t& key)
+{
+  int error = ::pthread_key_create(&key, 0);
+  asio::error_code ec(error,
+      asio::error::get_system_category());
+  asio::detail::throw_error(ec, "tss");
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(BOOST_HAS_PTHREADS) && !defined(ASIO_DISABLE_THREADS)
+
+#endif // ASIO_DETAIL_IMPL_POSIX_TSS_PTR_IPP
diff --git a/ext/asio/asio/detail/impl/reactive_descriptor_service.ipp b/ext/asio/asio/detail/impl/reactive_descriptor_service.ipp
new file mode 100644
index 0000000..706d60f
--- /dev/null
+++ b/ext/asio/asio/detail/impl/reactive_descriptor_service.ipp
@@ -0,0 +1,136 @@
+//
+// detail/impl/reactive_descriptor_service.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_IMPL_REACTIVE_DESCRIPTOR_SERVICE_IPP
+#define ASIO_DETAIL_IMPL_REACTIVE_DESCRIPTOR_SERVICE_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
+#include "asio/error.hpp"
+#include "asio/detail/reactive_descriptor_service.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+reactive_descriptor_service::reactive_descriptor_service(
+    asio::io_service& io_service)
+  : reactor_(asio::use_service<reactor>(io_service))
+{
+  reactor_.init_task();
+}
+
+void reactive_descriptor_service::shutdown_service()
+{
+}
+
+void reactive_descriptor_service::construct(
+    reactive_descriptor_service::implementation_type& impl)
+{
+  impl.descriptor_ = -1;
+  impl.state_ = 0;
+}
+
+void reactive_descriptor_service::destroy(
+    reactive_descriptor_service::implementation_type& impl)
+{
+  if (is_open(impl))
+    reactor_.close_descriptor(impl.descriptor_, impl.reactor_data_);
+
+  asio::error_code ignored_ec;
+  descriptor_ops::close(impl.descriptor_, impl.state_, ignored_ec);
+}
+
+asio::error_code reactive_descriptor_service::assign(
+    reactive_descriptor_service::implementation_type& impl,
+    const native_type& native_descriptor, asio::error_code& ec)
+{
+  if (is_open(impl))
+  {
+    ec = asio::error::already_open;
+    return ec;
+  }
+
+  if (int err = reactor_.register_descriptor(
+        native_descriptor, impl.reactor_data_))
+  {
+    ec = asio::error_code(err,
+        asio::error::get_system_category());
+    return ec;
+  }
+
+  impl.descriptor_ = native_descriptor;
+  impl.state_ = 0;
+  ec = asio::error_code();
+  return ec;
+}
+
+asio::error_code reactive_descriptor_service::close(
+    reactive_descriptor_service::implementation_type& impl,
+    asio::error_code& ec)
+{
+  if (is_open(impl))
+    reactor_.close_descriptor(impl.descriptor_, impl.reactor_data_);
+
+  if (descriptor_ops::close(impl.descriptor_, impl.state_, ec) == 0)
+    construct(impl);
+
+  return ec;
+}
+
+asio::error_code reactive_descriptor_service::cancel(
+    reactive_descriptor_service::implementation_type& impl,
+    asio::error_code& ec)
+{
+  if (!is_open(impl))
+  {
+    ec = asio::error::bad_descriptor;
+    return ec;
+  }
+
+  reactor_.cancel_ops(impl.descriptor_, impl.reactor_data_);
+  ec = asio::error_code();
+  return ec;
+}
+
+void reactive_descriptor_service::start_op(
+    reactive_descriptor_service::implementation_type& impl,
+    int op_type, reactor_op* op, bool non_blocking, bool noop)
+{
+  if (!noop)
+  {
+    if ((impl.state_ & descriptor_ops::non_blocking) ||
+        descriptor_ops::set_internal_non_blocking(
+          impl.descriptor_, impl.state_, op->ec_))
+    {
+      reactor_.start_op(op_type, impl.descriptor_,
+          impl.reactor_data_, op, non_blocking);
+      return;
+    }
+  }
+
+  reactor_.post_immediate_completion(op);
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
+#endif // ASIO_DETAIL_IMPL_REACTIVE_DESCRIPTOR_SERVICE_IPP
diff --git a/ext/asio/asio/detail/impl/reactive_serial_port_service.ipp b/ext/asio/asio/detail/impl/reactive_serial_port_service.ipp
new file mode 100644
index 0000000..c4df793
--- /dev/null
+++ b/ext/asio/asio/detail/impl/reactive_serial_port_service.ipp
@@ -0,0 +1,151 @@
+//
+// detail/impl/reactive_serial_port_service.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2008 Rep Invariant Systems, Inc. (info at repinvariant.com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_IMPL_REACTIVE_SERIAL_PORT_SERVICE_IPP
+#define ASIO_DETAIL_IMPL_REACTIVE_SERIAL_PORT_SERVICE_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(ASIO_HAS_SERIAL_PORT)
+#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
+#include <cstring>
+#include "asio/detail/reactive_serial_port_service.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+reactive_serial_port_service::reactive_serial_port_service(
+    asio::io_service& io_service)
+  : descriptor_service_(io_service)
+{
+}
+
+void reactive_serial_port_service::shutdown_service()
+{
+  descriptor_service_.shutdown_service();
+}
+
+asio::error_code reactive_serial_port_service::open(
+    reactive_serial_port_service::implementation_type& impl,
+    const std::string& device, asio::error_code& ec)
+{
+  if (is_open(impl))
+  {
+    ec = asio::error::already_open;
+    return ec;
+  }
+
+  descriptor_ops::state_type state = 0;
+  int fd = descriptor_ops::open(device.c_str(),
+      O_RDWR | O_NONBLOCK | O_NOCTTY, ec);
+  if (fd < 0)
+    return ec;
+
+  int s = descriptor_ops::fcntl(fd, F_GETFL, ec);
+  if (s >= 0)
+    s = descriptor_ops::fcntl(fd, F_SETFL, s | O_NONBLOCK, ec);
+  if (s < 0)
+  {
+    asio::error_code ignored_ec;
+    descriptor_ops::close(fd, state, ignored_ec);
+    return ec;
+  }
+
+  // Set up default serial port options.
+  termios ios;
+  errno = 0;
+  s = descriptor_ops::error_wrapper(::tcgetattr(fd, &ios), ec);
+  if (s >= 0)
+  {
+#if defined(_BSD_SOURCE)
+    ::cfmakeraw(&ios);
+#else
+    ios.c_iflag &= ~(IGNBRK | BRKINT | PARMRK
+        | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
+    ios.c_oflag &= ~OPOST;
+    ios.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
+    ios.c_cflag &= ~(CSIZE | PARENB);
+    ios.c_cflag |= CS8;
+#endif
+    ios.c_iflag |= IGNPAR;
+    ios.c_cflag |= CREAD | CLOCAL;
+    errno = 0;
+    s = descriptor_ops::error_wrapper(::tcsetattr(fd, TCSANOW, &ios), ec);
+  }
+  if (s < 0)
+  {
+    asio::error_code ignored_ec;
+    descriptor_ops::close(fd, state, ignored_ec);
+    return ec;
+  }
+
+  // We're done. Take ownership of the serial port descriptor.
+  if (descriptor_service_.assign(impl, fd, ec))
+  {
+    asio::error_code ignored_ec;
+    descriptor_ops::close(fd, state, ignored_ec);
+  }
+
+  return ec;
+}
+
+asio::error_code reactive_serial_port_service::do_set_option(
+    reactive_serial_port_service::implementation_type& impl,
+    reactive_serial_port_service::store_function_type store,
+    const void* option, asio::error_code& ec)
+{
+  termios ios;
+  errno = 0;
+  descriptor_ops::error_wrapper(::tcgetattr(
+        descriptor_service_.native(impl), &ios), ec);
+  if (ec)
+    return ec;
+
+  if (store(option, ios, ec))
+    return ec;
+
+  errno = 0;
+  descriptor_ops::error_wrapper(::tcsetattr(
+        descriptor_service_.native(impl), TCSANOW, &ios), ec);
+  return ec;
+}
+
+asio::error_code reactive_serial_port_service::do_get_option(
+    const reactive_serial_port_service::implementation_type& impl,
+    reactive_serial_port_service::load_function_type load,
+    void* option, asio::error_code& ec) const
+{
+  termios ios;
+  errno = 0;
+  descriptor_ops::error_wrapper(::tcgetattr(
+        descriptor_service_.native(impl), &ios), ec);
+  if (ec)
+    return ec;
+
+  return load(option, ios, ec);
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+#endif // defined(ASIO_HAS_SERIAL_PORT)
+
+#endif // ASIO_DETAIL_IMPL_REACTIVE_SERIAL_PORT_SERVICE_IPP
diff --git a/ext/asio/asio/detail/impl/reactive_socket_service_base.ipp b/ext/asio/asio/detail/impl/reactive_socket_service_base.ipp
new file mode 100644
index 0000000..54e7944
--- /dev/null
+++ b/ext/asio/asio/detail/impl/reactive_socket_service_base.ipp
@@ -0,0 +1,212 @@
+//
+// detail/reactive_socket_service_base.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_IMPL_REACTIVE_SOCKET_SERVICE_BASE_IPP
+#define ASIO_DETAIL_IMPL_REACTIVE_SOCKET_SERVICE_BASE_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if !defined(ASIO_HAS_IOCP)
+
+#include "asio/detail/reactive_socket_service_base.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+reactive_socket_service_base::reactive_socket_service_base(
+    asio::io_service& io_service)
+  : reactor_(use_service<reactor>(io_service))
+{
+  reactor_.init_task();
+}
+
+void reactive_socket_service_base::shutdown_service()
+{
+}
+
+void reactive_socket_service_base::construct(
+    reactive_socket_service_base::base_implementation_type& impl)
+{
+  impl.socket_ = invalid_socket;
+  impl.state_ = 0;
+}
+
+void reactive_socket_service_base::destroy(
+    reactive_socket_service_base::base_implementation_type& impl)
+{
+  if (impl.socket_ != invalid_socket)
+  {
+    reactor_.close_descriptor(impl.socket_, impl.reactor_data_);
+
+    asio::error_code ignored_ec;
+    socket_ops::close(impl.socket_, impl.state_, true, ignored_ec);
+  }
+}
+
+asio::error_code reactive_socket_service_base::close(
+    reactive_socket_service_base::base_implementation_type& impl,
+    asio::error_code& ec)
+{
+  if (is_open(impl))
+    reactor_.close_descriptor(impl.socket_, impl.reactor_data_);
+
+  if (socket_ops::close(impl.socket_, impl.state_, true, ec) == 0)
+    construct(impl);
+
+  return ec;
+}
+
+asio::error_code reactive_socket_service_base::cancel(
+    reactive_socket_service_base::base_implementation_type& impl,
+    asio::error_code& ec)
+{
+  if (!is_open(impl))
+  {
+    ec = asio::error::bad_descriptor;
+    return ec;
+  }
+
+  reactor_.cancel_ops(impl.socket_, impl.reactor_data_);
+  ec = asio::error_code();
+  return ec;
+}
+
+asio::error_code reactive_socket_service_base::do_open(
+    reactive_socket_service_base::base_implementation_type& impl,
+    int af, int type, int protocol, asio::error_code& ec)
+{
+  if (is_open(impl))
+  {
+    ec = asio::error::already_open;
+    return ec;
+  }
+
+  socket_holder sock(socket_ops::socket(af, type, protocol, ec));
+  if (sock.get() == invalid_socket)
+    return ec;
+
+  if (int err = reactor_.register_descriptor(sock.get(), impl.reactor_data_))
+  {
+    ec = asio::error_code(err,
+        asio::error::get_system_category());
+    return ec;
+  }
+
+  impl.socket_ = sock.release();
+  switch (type)
+  {
+  case SOCK_STREAM: impl.state_ = socket_ops::stream_oriented; break;
+  case SOCK_DGRAM: impl.state_ = socket_ops::datagram_oriented; break;
+  default: impl.state_ = 0; break;
+  }
+  ec = asio::error_code();
+  return ec;
+}
+
+asio::error_code reactive_socket_service_base::do_assign(
+    reactive_socket_service_base::base_implementation_type& impl, int type,
+    const reactive_socket_service_base::native_type& native_socket,
+    asio::error_code& ec)
+{
+  if (is_open(impl))
+  {
+    ec = asio::error::already_open;
+    return ec;
+  }
+
+  if (int err = reactor_.register_descriptor(
+        native_socket, impl.reactor_data_))
+  {
+    ec = asio::error_code(err,
+        asio::error::get_system_category());
+    return ec;
+  }
+
+  impl.socket_ = native_socket;
+  switch (type)
+  {
+  case SOCK_STREAM: impl.state_ = socket_ops::stream_oriented; break;
+  case SOCK_DGRAM: impl.state_ = socket_ops::datagram_oriented; break;
+  default: impl.state_ = 0; break;
+  }
+  ec = asio::error_code();
+  return ec;
+}
+
+void reactive_socket_service_base::start_op(
+    reactive_socket_service_base::base_implementation_type& impl,
+    int op_type, reactor_op* op, bool non_blocking, bool noop)
+{
+  if (!noop)
+  {
+    if ((impl.state_ & socket_ops::non_blocking)
+        || socket_ops::set_internal_non_blocking(
+          impl.socket_, impl.state_, op->ec_))
+    {
+      reactor_.start_op(op_type, impl.socket_,
+          impl.reactor_data_, op, non_blocking);
+      return;
+    }
+  }
+
+  reactor_.post_immediate_completion(op);
+}
+
+void reactive_socket_service_base::start_accept_op(
+    reactive_socket_service_base::base_implementation_type& impl,
+    reactor_op* op, bool peer_is_open)
+{
+  if (!peer_is_open)
+    start_op(impl, reactor::read_op, op, true, false);
+  else
+  {
+    op->ec_ = asio::error::already_open;
+    reactor_.post_immediate_completion(op);
+  }
+}
+
+void reactive_socket_service_base::start_connect_op(
+    reactive_socket_service_base::base_implementation_type& impl,
+    reactor_op* op, const socket_addr_type* addr, size_t addrlen)
+{
+  if ((impl.state_ & socket_ops::non_blocking)
+      || socket_ops::set_internal_non_blocking(
+        impl.socket_, impl.state_, op->ec_))
+  {
+    if (socket_ops::connect(impl.socket_, addr, addrlen, op->ec_) != 0)
+    {
+      if (op->ec_ == asio::error::in_progress
+          || op->ec_ == asio::error::would_block)
+      {
+        op->ec_ = asio::error_code();
+        reactor_.start_op(reactor::connect_op,
+            impl.socket_, impl.reactor_data_, op, false);
+        return;
+      }
+    }
+  }
+
+  reactor_.post_immediate_completion(op);
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // !defined(ASIO_HAS_IOCP)
+
+#endif // ASIO_DETAIL_IMPL_REACTIVE_SOCKET_SERVICE_BASE_IPP
diff --git a/ext/asio/asio/detail/impl/resolver_service_base.ipp b/ext/asio/asio/detail/impl/resolver_service_base.ipp
new file mode 100644
index 0000000..a844a23
--- /dev/null
+++ b/ext/asio/asio/detail/impl/resolver_service_base.ipp
@@ -0,0 +1,106 @@
+//
+// detail/impl/resolver_service_base.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_IMPL_RESOLVER_SERVICE_BASE_IPP
+#define ASIO_DETAIL_IMPL_RESOLVER_SERVICE_BASE_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+#include "asio/detail/resolver_service_base.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+class resolver_service_base::work_io_service_runner
+{
+public:
+  work_io_service_runner(asio::io_service& io_service)
+    : io_service_(io_service) {}
+  void operator()() { io_service_.run(); }
+private:
+  asio::io_service& io_service_;
+};
+
+resolver_service_base::resolver_service_base(
+    asio::io_service& io_service)
+  : io_service_impl_(asio::use_service<io_service_impl>(io_service)),
+    work_io_service_(new asio::io_service),
+    work_io_service_impl_(asio::use_service<
+        io_service_impl>(*work_io_service_)),
+    work_(new asio::io_service::work(*work_io_service_)),
+    work_thread_(0)
+{
+}
+
+resolver_service_base::~resolver_service_base()
+{
+  shutdown_service();
+}
+
+void resolver_service_base::shutdown_service()
+{
+  work_.reset();
+  if (work_io_service_)
+  {
+    work_io_service_->stop();
+    if (work_thread_)
+    {
+      work_thread_->join();
+      work_thread_.reset();
+    }
+    work_io_service_.reset();
+  }
+}
+
+void resolver_service_base::construct(
+    resolver_service_base::implementation_type& impl)
+{
+  impl.reset(static_cast<void*>(0), socket_ops::noop_deleter());
+}
+
+void resolver_service_base::destroy(
+    resolver_service_base::implementation_type&)
+{
+}
+
+void resolver_service_base::cancel(
+    resolver_service_base::implementation_type& impl)
+{
+  impl.reset(static_cast<void*>(0), socket_ops::noop_deleter());
+}
+
+void resolver_service_base::start_resolve_op(operation* op)
+{
+  start_work_thread();
+  io_service_impl_.work_started();
+  work_io_service_impl_.post_immediate_completion(op);
+}
+
+void resolver_service_base::start_work_thread()
+{
+  asio::detail::mutex::scoped_lock lock(mutex_);
+  if (!work_thread_)
+  {
+    work_thread_.reset(new asio::detail::thread(
+          work_io_service_runner(*work_io_service_)));
+  }
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_IMPL_RESOLVER_SERVICE_BASE_IPP
diff --git a/ext/asio/asio/detail/impl/select_reactor.hpp b/ext/asio/asio/detail/impl/select_reactor.hpp
new file mode 100644
index 0000000..50d3ad4
--- /dev/null
+++ b/ext/asio/asio/detail/impl/select_reactor.hpp
@@ -0,0 +1,84 @@
+//
+// detail/impl/select_reactor.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_IMPL_SELECT_REACTOR_HPP
+#define ASIO_DETAIL_IMPL_SELECT_REACTOR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(ASIO_HAS_IOCP) \
+  || (!defined(ASIO_HAS_DEV_POLL) \
+      && !defined(ASIO_HAS_EPOLL) \
+      && !defined(ASIO_HAS_KQUEUE))
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename Time_Traits>
+void select_reactor::add_timer_queue(timer_queue<Time_Traits>& queue)
+{
+  do_add_timer_queue(queue);
+}
+
+// Remove a timer queue from the reactor.
+template <typename Time_Traits>
+void select_reactor::remove_timer_queue(timer_queue<Time_Traits>& queue)
+{
+  do_remove_timer_queue(queue);
+}
+
+template <typename Time_Traits>
+void select_reactor::schedule_timer(timer_queue<Time_Traits>& queue,
+    const typename Time_Traits::time_type& time,
+    typename timer_queue<Time_Traits>::per_timer_data& timer, timer_op* op)
+{
+  asio::detail::mutex::scoped_lock lock(mutex_);
+
+  if (shutdown_)
+  {
+    io_service_.post_immediate_completion(op);
+    return;
+  }
+
+  bool earliest = queue.enqueue_timer(time, timer, op);
+  io_service_.work_started();
+  if (earliest)
+    interrupter_.interrupt();
+}
+
+template <typename Time_Traits>
+std::size_t select_reactor::cancel_timer(timer_queue<Time_Traits>& queue,
+    typename timer_queue<Time_Traits>::per_timer_data& timer)
+{
+  asio::detail::mutex::scoped_lock lock(mutex_);
+  op_queue<operation> ops;
+  std::size_t n = queue.cancel_timer(timer, ops);
+  lock.unlock();
+  io_service_.post_deferred_completions(ops);
+  return n;
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(ASIO_HAS_IOCP)
+       //   || (!defined(ASIO_HAS_DEV_POLL)
+       //       && !defined(ASIO_HAS_EPOLL)
+       //       && !defined(ASIO_HAS_KQUEUE))
+
+#endif // ASIO_DETAIL_IMPL_SELECT_REACTOR_HPP
diff --git a/ext/asio/asio/detail/impl/select_reactor.ipp b/ext/asio/asio/detail/impl/select_reactor.ipp
new file mode 100644
index 0000000..1a59be3
--- /dev/null
+++ b/ext/asio/asio/detail/impl/select_reactor.ipp
@@ -0,0 +1,273 @@
+//
+// detail/impl/select_reactor.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_IMPL_SELECT_REACTOR_IPP
+#define ASIO_DETAIL_IMPL_SELECT_REACTOR_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(ASIO_HAS_IOCP) \
+  || (!defined(ASIO_HAS_DEV_POLL) \
+      && !defined(ASIO_HAS_EPOLL) \
+      && !defined(ASIO_HAS_KQUEUE))
+
+#include "asio/detail/bind_handler.hpp"
+#include "asio/detail/fd_set_adapter.hpp"
+#include "asio/detail/select_reactor.hpp"
+#include "asio/detail/signal_blocker.hpp"
+#include "asio/detail/socket_ops.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+select_reactor::select_reactor(asio::io_service& io_service)
+  : asio::detail::service_base<select_reactor>(io_service),
+    io_service_(use_service<io_service_impl>(io_service)),
+    mutex_(),
+    interrupter_(),
+#if defined(ASIO_HAS_IOCP)
+    stop_thread_(false),
+    thread_(0),
+#endif // defined(ASIO_HAS_IOCP)
+    shutdown_(false)
+{
+#if defined(ASIO_HAS_IOCP)
+  asio::detail::signal_blocker sb;
+  thread_ = new asio::detail::thread(
+      bind_handler(&select_reactor::call_run_thread, this));
+#endif // defined(ASIO_HAS_IOCP)
+}
+
+select_reactor::~select_reactor()
+{
+  shutdown_service();
+}
+
+void select_reactor::shutdown_service()
+{
+  asio::detail::mutex::scoped_lock lock(mutex_);
+  shutdown_ = true;
+#if defined(ASIO_HAS_IOCP)
+  stop_thread_ = true;
+#endif // defined(ASIO_HAS_IOCP)
+  lock.unlock();
+
+#if defined(ASIO_HAS_IOCP)
+  if (thread_)
+  {
+    interrupter_.interrupt();
+    thread_->join();
+    delete thread_;
+    thread_ = 0;
+  }
+#endif // defined(ASIO_HAS_IOCP)
+
+  op_queue<operation> ops;
+
+  for (int i = 0; i < max_ops; ++i)
+    op_queue_[i].get_all_operations(ops);
+
+  timer_queues_.get_all_timers(ops);
+}
+
+void select_reactor::init_task()
+{
+  io_service_.init_task();
+}
+
+int select_reactor::register_descriptor(socket_type,
+    select_reactor::per_descriptor_data&)
+{
+  return 0;
+}
+
+void select_reactor::start_op(int op_type, socket_type descriptor,
+    select_reactor::per_descriptor_data&, reactor_op* op, bool)
+{
+  asio::detail::mutex::scoped_lock lock(mutex_);
+
+  if (shutdown_)
+  {
+    post_immediate_completion(op);
+    return;
+  }
+
+  bool first = op_queue_[op_type].enqueue_operation(descriptor, op);
+  io_service_.work_started();
+  if (first)
+    interrupter_.interrupt();
+}
+
+void select_reactor::cancel_ops(socket_type descriptor,
+    select_reactor::per_descriptor_data&)
+{
+  asio::detail::mutex::scoped_lock lock(mutex_);
+  cancel_ops_unlocked(descriptor, asio::error::operation_aborted);
+}
+
+void select_reactor::close_descriptor(socket_type descriptor,
+    select_reactor::per_descriptor_data&)
+{
+  asio::detail::mutex::scoped_lock lock(mutex_);
+  cancel_ops_unlocked(descriptor, asio::error::operation_aborted);
+}
+
+void select_reactor::run(bool block, op_queue<operation>& ops)
+{
+  asio::detail::mutex::scoped_lock lock(mutex_);
+
+#if defined(ASIO_HAS_IOCP)
+  // Check if the thread is supposed to stop.
+  if (stop_thread_)
+    return;
+#endif // defined(ASIO_HAS_IOCP)
+
+  // Set up the descriptor sets.
+  fd_set_adapter fds[max_select_ops];
+  fds[read_op].set(interrupter_.read_descriptor());
+  socket_type max_fd = 0;
+  bool have_work_to_do = !timer_queues_.all_empty();
+  for (int i = 0; i < max_select_ops; ++i)
+  {
+    have_work_to_do = have_work_to_do || !op_queue_[i].empty();
+    op_queue_[i].get_descriptors(fds[i], ops);
+    if (fds[i].max_descriptor() > max_fd)
+      max_fd = fds[i].max_descriptor();
+  }
+
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+  // Connection operations on Windows use both except and write fd_sets.
+  have_work_to_do = have_work_to_do || !op_queue_[connect_op].empty();
+  op_queue_[connect_op].get_descriptors(fds[write_op], ops);
+  if (fds[write_op].max_descriptor() > max_fd)
+    max_fd = fds[write_op].max_descriptor();
+  op_queue_[connect_op].get_descriptors(fds[except_op], ops);
+  if (fds[except_op].max_descriptor() > max_fd)
+    max_fd = fds[except_op].max_descriptor();
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+
+  // We can return immediately if there's no work to do and the reactor is
+  // not supposed to block.
+  if (!block && !have_work_to_do)
+    return;
+
+  // Determine how long to block while waiting for events.
+  timeval tv_buf = { 0, 0 };
+  timeval* tv = block ? get_timeout(tv_buf) : &tv_buf;
+
+  lock.unlock();
+
+  // Block on the select call until descriptors become ready.
+  asio::error_code ec;
+  int retval = socket_ops::select(static_cast<int>(max_fd + 1),
+      fds[read_op], fds[write_op], fds[except_op], tv, ec);
+
+  // Reset the interrupter.
+  if (retval > 0 && fds[read_op].is_set(interrupter_.read_descriptor()))
+    interrupter_.reset();
+
+  lock.lock();
+
+  // Dispatch all ready operations.
+  if (retval > 0)
+  {
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+    // Connection operations on Windows use both except and write fd_sets.
+    op_queue_[connect_op].perform_operations_for_descriptors(
+        fds[except_op], ops);
+    op_queue_[connect_op].perform_operations_for_descriptors(
+        fds[write_op], ops);
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+
+    // Exception operations must be processed first to ensure that any
+    // out-of-band data is read before normal data.
+    for (int i = max_select_ops - 1; i >= 0; --i)
+      op_queue_[i].perform_operations_for_descriptors(fds[i], ops);
+  }
+  timer_queues_.get_ready_timers(ops);
+}
+
+void select_reactor::interrupt()
+{
+  interrupter_.interrupt();
+}
+
+#if defined(ASIO_HAS_IOCP)
+void select_reactor::run_thread()
+{
+  asio::detail::mutex::scoped_lock lock(mutex_);
+  while (!stop_thread_)
+  {
+    lock.unlock();
+    op_queue<operation> ops;
+    run(true, ops);
+    io_service_.post_deferred_completions(ops);
+    lock.lock();
+  }
+}
+
+void select_reactor::call_run_thread(select_reactor* reactor)
+{
+  reactor->run_thread();
+}
+#endif // defined(ASIO_HAS_IOCP)
+
+void select_reactor::do_add_timer_queue(timer_queue_base& queue)
+{
+  mutex::scoped_lock lock(mutex_);
+  timer_queues_.insert(&queue);
+}
+
+void select_reactor::do_remove_timer_queue(timer_queue_base& queue)
+{
+  mutex::scoped_lock lock(mutex_);
+  timer_queues_.erase(&queue);
+}
+
+timeval* select_reactor::get_timeout(timeval& tv)
+{
+  // By default we will wait no longer than 5 minutes. This will ensure that
+  // any changes to the system clock are detected after no longer than this.
+  long usec = timer_queues_.wait_duration_usec(5 * 60 * 1000 * 1000);
+  tv.tv_sec = usec / 1000000;
+  tv.tv_usec = usec % 1000000;
+  return &tv;
+}
+
+void select_reactor::cancel_ops_unlocked(socket_type descriptor,
+    const asio::error_code& ec)
+{
+  bool need_interrupt = false;
+  op_queue<operation> ops;
+  for (int i = 0; i < max_ops; ++i)
+    need_interrupt = op_queue_[i].cancel_operations(
+        descriptor, ops, ec) || need_interrupt;
+  io_service_.post_deferred_completions(ops);
+  if (need_interrupt)
+    interrupter_.interrupt();
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(ASIO_HAS_IOCP)
+       //   || (!defined(ASIO_HAS_DEV_POLL)
+       //       && !defined(ASIO_HAS_EPOLL)
+       //       && !defined(ASIO_HAS_KQUEUE))
+
+#endif // ASIO_DETAIL_IMPL_SELECT_REACTOR_IPP
diff --git a/ext/asio/asio/detail/impl/service_registry.hpp b/ext/asio/asio/detail/impl/service_registry.hpp
new file mode 100644
index 0000000..c2aa9ec
--- /dev/null
+++ b/ext/asio/asio/detail/impl/service_registry.hpp
@@ -0,0 +1,70 @@
+//
+// detail/impl/service_registry.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_IMPL_SERVICE_REGISTRY_HPP
+#define ASIO_DETAIL_IMPL_SERVICE_REGISTRY_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename Service>
+Service& service_registry::use_service()
+{
+  asio::io_service::service::key key;
+  init_key(key, Service::id);
+  factory_type factory = &service_registry::create<Service>;
+  return *static_cast<Service*>(do_use_service(key, factory));
+}
+
+template <typename Service>
+void service_registry::add_service(Service* new_service)
+{
+  asio::io_service::service::key key;
+  init_key(key, Service::id);
+  return do_add_service(key, new_service);
+}
+
+template <typename Service>
+bool service_registry::has_service() const
+{
+  asio::io_service::service::key key;
+  init_key(key, Service::id);
+  return do_has_service(key);
+}
+
+#if !defined(ASIO_NO_TYPEID)
+template <typename Service>
+void service_registry::init_key(asio::io_service::service::key& key,
+    const asio::detail::service_id<Service>& /*id*/)
+{
+  key.type_info_ = &typeid(typeid_wrapper<Service>);
+  key.id_ = 0;
+}
+#endif // !defined(ASIO_NO_TYPEID)
+
+template <typename Service>
+asio::io_service::service* service_registry::create(
+    asio::io_service& owner)
+{
+  return new Service(owner);
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_IMPL_SERVICE_REGISTRY_HPP
diff --git a/ext/asio/asio/detail/impl/service_registry.ipp b/ext/asio/asio/detail/impl/service_registry.ipp
new file mode 100644
index 0000000..57c57b8
--- /dev/null
+++ b/ext/asio/asio/detail/impl/service_registry.ipp
@@ -0,0 +1,164 @@
+//
+// detail/impl/service_registry.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_IMPL_SERVICE_REGISTRY_IPP
+#define ASIO_DETAIL_IMPL_SERVICE_REGISTRY_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+#include <boost/throw_exception.hpp>
+#include "asio/detail/service_registry.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+service_registry::service_registry(asio::io_service& o)
+  : owner_(o),
+    first_service_(0)
+{
+}
+
+service_registry::~service_registry()
+{
+  // Shutdown all services. This must be done in a separate loop before the
+  // services are destroyed since the destructors of user-defined handler
+  // objects may try to access other service objects.
+  asio::io_service::service* service = first_service_;
+  while (service)
+  {
+    service->shutdown_service();
+    service = service->next_;
+  }
+
+  // Destroy all services.
+  while (first_service_)
+  {
+    asio::io_service::service* next_service = first_service_->next_;
+    destroy(first_service_);
+    first_service_ = next_service;
+  }
+}
+
+void service_registry::init_key(asio::io_service::service::key& key,
+    const asio::io_service::id& id)
+{
+  key.type_info_ = 0;
+  key.id_ = &id;
+}
+
+bool service_registry::keys_match(
+    const asio::io_service::service::key& key1,
+    const asio::io_service::service::key& key2)
+{
+  if (key1.id_ && key2.id_)
+    if (key1.id_ == key2.id_)
+      return true;
+  if (key1.type_info_ && key2.type_info_)
+    if (*key1.type_info_ == *key2.type_info_)
+      return true;
+  return false;
+}
+
+void service_registry::destroy(asio::io_service::service* service)
+{
+  delete service;
+}
+
+asio::io_service::service* service_registry::do_use_service(
+    const asio::io_service::service::key& key,
+    factory_type factory)
+{
+  asio::detail::mutex::scoped_lock lock(mutex_);
+
+  // First see if there is an existing service object with the given key.
+  asio::io_service::service* service = first_service_;
+  while (service)
+  {
+    if (keys_match(service->key_, key))
+      return service;
+    service = service->next_;
+  }
+
+  // Create a new service object. The service registry's mutex is not locked
+  // at this time to allow for nested calls into this function from the new
+  // service's constructor.
+  lock.unlock();
+  auto_service_ptr new_service = { factory(owner_) };
+  new_service.ptr_->key_ = key;
+  lock.lock();
+
+  // Check that nobody else created another service object of the same type
+  // while the lock was released.
+  service = first_service_;
+  while (service)
+  {
+    if (keys_match(service->key_, key))
+      return service;
+    service = service->next_;
+  }
+
+  // Service was successfully initialised, pass ownership to registry.
+  new_service.ptr_->next_ = first_service_;
+  first_service_ = new_service.ptr_;
+  new_service.ptr_ = 0;
+  return first_service_;
+}
+
+void service_registry::do_add_service(
+    const asio::io_service::service::key& key,
+    asio::io_service::service* new_service)
+{
+  if (&owner_ != &new_service->io_service())
+    boost::throw_exception(invalid_service_owner());
+
+  asio::detail::mutex::scoped_lock lock(mutex_);
+
+  // Check if there is an existing service object with the given key.
+  asio::io_service::service* service = first_service_;
+  while (service)
+  {
+    if (keys_match(service->key_, key))
+      boost::throw_exception(service_already_exists());
+    service = service->next_;
+  }
+
+  // Take ownership of the service object.
+  new_service->key_ = key;
+  new_service->next_ = first_service_;
+  first_service_ = new_service;
+}
+
+bool service_registry::do_has_service(
+    const asio::io_service::service::key& key) const
+{
+  asio::detail::mutex::scoped_lock lock(mutex_);
+
+  asio::io_service::service* service = first_service_;
+  while (service)
+  {
+    if (keys_match(service->key_, key))
+      return true;
+    service = service->next_;
+  }
+
+  return false;
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_IMPL_SERVICE_REGISTRY_IPP
diff --git a/ext/asio/asio/detail/impl/socket_ops.ipp b/ext/asio/asio/detail/impl/socket_ops.ipp
new file mode 100644
index 0000000..66006ea
--- /dev/null
+++ b/ext/asio/asio/detail/impl/socket_ops.ipp
@@ -0,0 +1,2917 @@
+//
+// detail/impl/socket_ops.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_SOCKET_OPS_IPP
+#define ASIO_DETAIL_SOCKET_OPS_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+#include <boost/assert.hpp>
+#include <boost/detail/workaround.hpp>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <cerrno>
+#include <new>
+#include "asio/detail/socket_ops.hpp"
+#include "asio/error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+namespace socket_ops {
+
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+struct msghdr { int msg_namelen; };
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+
+#if defined(__hpux)
+// HP-UX doesn't declare these functions extern "C", so they are declared again
+// here to avoid linker errors about undefined symbols.
+extern "C" char* if_indextoname(unsigned int, char*);
+extern "C" unsigned int if_nametoindex(const char*);
+#endif // defined(__hpux)
+
+inline void clear_last_error()
+{
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+  WSASetLastError(0);
+#else
+  errno = 0;
+#endif
+}
+
+template <typename ReturnType>
+inline ReturnType error_wrapper(ReturnType return_value,
+    asio::error_code& ec)
+{
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+  ec = asio::error_code(WSAGetLastError(),
+      asio::error::get_system_category());
+#else
+  ec = asio::error_code(errno,
+      asio::error::get_system_category());
+#endif
+  return return_value;
+}
+
+template <typename SockLenType>
+inline socket_type call_accept(SockLenType msghdr::*,
+    socket_type s, socket_addr_type* addr, std::size_t* addrlen)
+{
+  SockLenType tmp_addrlen = addrlen ? (SockLenType)*addrlen : 0;
+  socket_type result = ::accept(s, addr, addrlen ? &tmp_addrlen : 0);
+  if (addrlen)
+    *addrlen = (std::size_t)tmp_addrlen;
+  return result;
+}
+
+ASIO_DECL
+socket_type accept(socket_type s, socket_addr_type* addr,
+    std::size_t* addrlen, asio::error_code& ec)
+{
+  if (s == invalid_socket)
+  {
+    ec = asio::error::bad_descriptor;
+    return invalid_socket;
+  }
+
+  clear_last_error();
+
+  socket_type new_s = error_wrapper(call_accept(
+        &msghdr::msg_namelen, s, addr, addrlen), ec);
+  if (new_s == invalid_socket)
+    return new_s;
+
+#if defined(__MACH__) && defined(__APPLE__) || defined(__FreeBSD__)
+  int optval = 1;
+  int result = error_wrapper(::setsockopt(new_s,
+        SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval)), ec);
+  if (result != 0)
+  {
+    ::close(new_s);
+    return invalid_socket;
+  }
+#endif
+
+  ec = asio::error_code();
+  return new_s;
+}
+
+ASIO_DECL
+socket_type sync_accept(socket_type s, state_type state,
+    socket_addr_type* addr, std::size_t* addrlen, asio::error_code& ec)
+{
+  // Accept a socket.
+  for (;;)
+  {
+    // Try to complete the operation without blocking.
+    socket_type new_socket = socket_ops::accept(s, addr, addrlen, ec);
+
+    // Check if operation succeeded.
+    if (new_socket != invalid_socket)
+      return new_socket;
+
+    // Operation failed.
+    if (ec == asio::error::would_block
+        || ec == asio::error::try_again)
+    {
+      if (state & user_set_non_blocking)
+        return invalid_socket;
+      // Fall through to retry operation.
+    }
+    else if (ec == asio::error::connection_aborted)
+    {
+      if (state & enable_connection_aborted)
+        return invalid_socket;
+      // Fall through to retry operation.
+    }
+#if defined(EPROTO)
+    else if (ec.value() == EPROTO)
+    {
+      if (state & enable_connection_aborted)
+        return invalid_socket;
+      // Fall through to retry operation.
+    }
+#endif // defined(EPROTO)
+    else
+      return invalid_socket;
+
+    // Wait for socket to become ready.
+    if (socket_ops::poll_read(s, ec) < 0)
+      return invalid_socket;
+  }
+}
+
+#if defined(ASIO_HAS_IOCP)
+
+void complete_iocp_accept(socket_type s,
+    void* output_buffer, DWORD address_length,
+    socket_addr_type* addr, std::size_t* addrlen,
+    socket_type new_socket, asio::error_code& ec)
+{
+  // Map non-portable errors to their portable counterparts.
+  if (ec.value() == ERROR_NETNAME_DELETED)
+    ec = asio::error::connection_aborted;
+
+  if (!ec)
+  {
+    // Get the address of the peer.
+    if (addr && addrlen)
+    {
+      LPSOCKADDR local_addr = 0;
+      int local_addr_length = 0;
+      LPSOCKADDR remote_addr = 0;
+      int remote_addr_length = 0;
+      GetAcceptExSockaddrs(output_buffer, 0, address_length,
+          address_length, &local_addr, &local_addr_length,
+          &remote_addr, &remote_addr_length);
+      if (static_cast<std::size_t>(remote_addr_length) > *addrlen)
+      {
+        ec = asio::error::invalid_argument;
+      }
+      else
+      {
+        using namespace std; // For memcpy.
+        memcpy(addr, remote_addr, remote_addr_length);
+        *addrlen = static_cast<std::size_t>(remote_addr_length);
+      }
+    }
+
+    // Need to set the SO_UPDATE_ACCEPT_CONTEXT option so that getsockname
+    // and getpeername will work on the accepted socket.
+    SOCKET update_ctx_param = s;
+    socket_ops::state_type state = 0;
+    socket_ops::setsockopt(new_socket, state,
+          SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT,
+          &update_ctx_param, sizeof(SOCKET), ec);
+  }
+}
+
+#else // defined(ASIO_HAS_IOCP)
+
+ASIO_DECL
+bool non_blocking_accept(socket_type s,
+    state_type state, socket_addr_type* addr, std::size_t* addrlen,
+    asio::error_code& ec, socket_type& new_socket)
+{
+  for (;;)
+  {
+    // Accept the waiting connection.
+    new_socket = socket_ops::accept(s, addr, addrlen, ec);
+
+    // Check if operation succeeded.
+    if (new_socket != invalid_socket)
+      return true;
+
+    // Retry operation if interrupted by signal.
+    if (ec == asio::error::interrupted)
+      continue;
+
+    // Operation failed.
+    if (ec == asio::error::would_block
+        || ec == asio::error::try_again)
+    {
+      if (state & user_set_non_blocking)
+        return true;
+      // Fall through to retry operation.
+    }
+    else if (ec == asio::error::connection_aborted)
+    {
+      if (state & enable_connection_aborted)
+        return true;
+      // Fall through to retry operation.
+    }
+#if defined(EPROTO)
+    else if (ec.value() == EPROTO)
+    {
+      if (state & enable_connection_aborted)
+        return true;
+      // Fall through to retry operation.
+    }
+#endif // defined(EPROTO)
+    else
+      return true;
+
+    return false;
+  }
+}
+
+#endif // defined(ASIO_HAS_IOCP)
+
+template <typename SockLenType>
+inline int call_bind(SockLenType msghdr::*,
+    socket_type s, const socket_addr_type* addr, std::size_t addrlen)
+{
+  return ::bind(s, addr, (SockLenType)addrlen);
+}
+
+ASIO_DECL
+int bind(socket_type s, const socket_addr_type* addr,
+    std::size_t addrlen, asio::error_code& ec)
+{
+  if (s == invalid_socket)
+  {
+    ec = asio::error::bad_descriptor;
+    return socket_error_retval;
+  }
+
+  clear_last_error();
+  int result = error_wrapper(call_bind(
+        &msghdr::msg_namelen, s, addr, addrlen), ec);
+  if (result == 0)
+    ec = asio::error_code();
+  return result;
+}
+
+ASIO_DECL
+int close(socket_type s, state_type& state,
+    bool destruction, asio::error_code& ec)
+{
+  int result = 0;
+  if (s != invalid_socket)
+  {
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+    if ((state & non_blocking) && (state & user_set_linger))
+    {
+      ioctl_arg_type arg = 0;
+      ::ioctlsocket(s, FIONBIO, &arg);
+      state &= ~non_blocking;
+    }
+#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+    if (state & non_blocking)
+    {
+#if defined(__SYMBIAN32__)
+      int flags = ::fcntl(s, F_GETFL, 0);
+      if (flags >= 0)
+        ::fcntl(s, F_SETFL, flags & ~O_NONBLOCK);
+#else // defined(__SYMBIAN32__)
+      ioctl_arg_type arg = 0;
+      ::ioctl(s, FIONBIO, &arg);
+#endif // defined(__SYMBIAN32__)
+      state &= ~non_blocking;
+    }
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+
+    if (destruction && (state & user_set_linger))
+    {
+      ::linger opt;
+      opt.l_onoff = 0;
+      opt.l_linger = 0;
+      asio::error_code ignored_ec;
+      socket_ops::setsockopt(s, state, SOL_SOCKET,
+          SO_LINGER, &opt, sizeof(opt), ignored_ec);
+    }
+
+    clear_last_error();
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+    result = error_wrapper(::closesocket(s), ec);
+#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+    result = error_wrapper(::close(s), ec);
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+  }
+
+  if (result == 0)
+    ec = asio::error_code();
+  return result;
+}
+
+ASIO_DECL
+bool set_internal_non_blocking(socket_type s,
+    state_type& state, asio::error_code& ec)
+{
+  if (s == invalid_socket)
+  {
+    ec = asio::error::bad_descriptor;
+    return false;
+  }
+
+  clear_last_error();
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+  ioctl_arg_type arg = 1;
+  int result = error_wrapper(::ioctlsocket(s, FIONBIO, &arg), ec);
+#elif defined(__SYMBIAN32__)
+  int result = error_wrapper(::fcntl(s, F_GETFL, 0), ec);
+  if (result >= 0)
+  {
+    clear_last_error();
+    result = error_wrapper(::fcntl(s, F_SETFL, result | O_NONBLOCK), ec);
+  }
+#else
+  ioctl_arg_type arg = 1;
+  int result = error_wrapper(::ioctl(s, FIONBIO, &arg), ec);
+#endif
+
+  if (result >= 0)
+  {
+    ec = asio::error_code();
+    state |= internal_non_blocking;
+    return true;
+  }
+
+  return false;
+}
+
+ASIO_DECL
+int shutdown(socket_type s, int what, asio::error_code& ec)
+{
+  if (s == invalid_socket)
+  {
+    ec = asio::error::bad_descriptor;
+    return socket_error_retval;
+  }
+
+  clear_last_error();
+  int result = error_wrapper(::shutdown(s, what), ec);
+  if (result == 0)
+    ec = asio::error_code();
+  return result;
+}
+
+template <typename SockLenType>
+inline int call_connect(SockLenType msghdr::*,
+    socket_type s, const socket_addr_type* addr, std::size_t addrlen)
+{
+  return ::connect(s, addr, (SockLenType)addrlen);
+}
+
+ASIO_DECL
+int connect(socket_type s, const socket_addr_type* addr,
+    std::size_t addrlen, asio::error_code& ec)
+{
+  if (s == invalid_socket)
+  {
+    ec = asio::error::bad_descriptor;
+    return socket_error_retval;
+  }
+
+  clear_last_error();
+  int result = error_wrapper(call_connect(
+        &msghdr::msg_namelen, s, addr, addrlen), ec);
+  if (result == 0)
+    ec = asio::error_code();
+  return result;
+}
+
+ASIO_DECL
+void sync_connect(socket_type s, const socket_addr_type* addr,
+    std::size_t addrlen, asio::error_code& ec)
+{
+  // Perform the connect operation.
+  socket_ops::connect(s, addr, addrlen, ec);
+  if (ec != asio::error::in_progress
+      && ec != asio::error::would_block)
+  {
+    // The connect operation finished immediately.
+    return;
+  }
+
+  // Wait for socket to become ready.
+  if (socket_ops::poll_connect(s, ec) < 0)
+    return;
+
+  // Get the error code from the connect operation.
+  int connect_error = 0;
+  size_t connect_error_len = sizeof(connect_error);
+  if (socket_ops::getsockopt(s, 0, SOL_SOCKET, SO_ERROR,
+        &connect_error, &connect_error_len, ec) == socket_error_retval)
+    return;
+
+  // Return the result of the connect operation.
+  ec = asio::error_code(connect_error,
+      asio::error::get_system_category());
+}
+
+ASIO_DECL
+bool non_blocking_connect(socket_type s, asio::error_code& ec)
+{
+  // Get the error code from the connect operation.
+  int connect_error = 0;
+  size_t connect_error_len = sizeof(connect_error);
+  if (socket_ops::getsockopt(s, 0, SOL_SOCKET, SO_ERROR,
+        &connect_error, &connect_error_len, ec) == 0)
+  {
+    if (connect_error)
+    {
+      ec = asio::error_code(connect_error,
+          asio::error::get_system_category());
+    }
+    else
+      ec = asio::error_code();
+  }
+
+  return true;
+}
+
+ASIO_DECL
+int socketpair(int af, int type, int protocol,
+    socket_type sv[2], asio::error_code& ec)
+{
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+  (void)(af);
+  (void)(type);
+  (void)(protocol);
+  (void)(sv);
+  ec = asio::error::operation_not_supported;
+  return socket_error_retval;
+#else
+  clear_last_error();
+  int result = error_wrapper(::socketpair(af, type, protocol, sv), ec);
+  if (result == 0)
+    ec = asio::error_code();
+  return result;
+#endif
+}
+
+ASIO_DECL
+bool sockatmark(socket_type s, asio::error_code& ec)
+{
+  if (s == invalid_socket)
+  {
+    ec = asio::error::bad_descriptor;
+    return false;
+  }
+
+#if defined(SIOCATMARK)
+  ioctl_arg_type value = 0;
+# if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+  int result = error_wrapper(::ioctlsocket(s, SIOCATMARK, &value), ec);
+# else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+  int result = error_wrapper(::ioctl(s, SIOCATMARK, &value), ec);
+# endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+  if (result == 0)
+    ec = asio::error_code();
+# if defined(ENOTTY)
+  if (ec.value() == ENOTTY)
+    ec = asio::error::not_socket;
+# endif // defined(ENOTTY)
+#else // defined(SIOCATMARK)
+  int value = error_wrapper(::sockatmark(s), ec);
+  if (value != -1)
+    ec = asio::error_code();
+#endif // defined(SIOCATMARK)
+
+  return ec ? false : value != 0;
+}
+
+ASIO_DECL
+size_t available(socket_type s, asio::error_code& ec)
+{
+  if (s == invalid_socket)
+  {
+    ec = asio::error::bad_descriptor;
+    return 0;
+  }
+
+  ioctl_arg_type value = 0;
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+  int result = error_wrapper(::ioctlsocket(s, FIONREAD, &value), ec);
+#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+  int result = error_wrapper(::ioctl(s, FIONREAD, &value), ec);
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+  if (result == 0)
+    ec = asio::error_code();
+#if defined(ENOTTY)
+  if (ec.value() == ENOTTY)
+    ec = asio::error::not_socket;
+#endif // defined(ENOTTY)
+
+  return ec ? static_cast<size_t>(0) : static_cast<size_t>(value);
+}
+
+ASIO_DECL
+int listen(socket_type s, int backlog, asio::error_code& ec)
+{
+  if (s == invalid_socket)
+  {
+    ec = asio::error::bad_descriptor;
+    return socket_error_retval;
+  }
+
+  clear_last_error();
+  int result = error_wrapper(::listen(s, backlog), ec);
+  if (result == 0)
+    ec = asio::error_code();
+  return result;
+}
+
+inline void init_buf_iov_base(void*& base, void* addr)
+{
+  base = addr;
+}
+
+template <typename T>
+inline void init_buf_iov_base(T& base, void* addr)
+{
+  base = static_cast<T>(addr);
+}
+
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+typedef WSABUF buf;
+#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+typedef iovec buf;
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+
+ASIO_DECL
+void init_buf(buf& b, void* data, size_t size)
+{
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+  b.buf = static_cast<char*>(data);
+  b.len = static_cast<u_long>(size);
+#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+  init_buf_iov_base(b.iov_base, data);
+  b.iov_len = size;
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+}
+
+ASIO_DECL
+void init_buf(buf& b, const void* data, size_t size)
+{
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+  b.buf = static_cast<char*>(const_cast<void*>(data));
+  b.len = static_cast<u_long>(size);
+#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+  init_buf_iov_base(b.iov_base, const_cast<void*>(data));
+  b.iov_len = size;
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+}
+
+inline void init_msghdr_msg_name(void*& name, socket_addr_type* addr)
+{
+  name = addr;
+}
+
+inline void init_msghdr_msg_name(void*& name, const socket_addr_type* addr)
+{
+  name = const_cast<socket_addr_type*>(addr);
+}
+
+template <typename T>
+inline void init_msghdr_msg_name(T& name, socket_addr_type* addr)
+{
+  name = reinterpret_cast<T>(addr);
+}
+
+template <typename T>
+inline void init_msghdr_msg_name(T& name, const socket_addr_type* addr)
+{
+  name = reinterpret_cast<T>(const_cast<socket_addr_type*>(addr));
+}
+
+ASIO_DECL
+int recv(socket_type s, buf* bufs, size_t count, int flags,
+    asio::error_code& ec)
+{
+  clear_last_error();
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+  // Receive some data.
+  DWORD recv_buf_count = static_cast<DWORD>(count);
+  DWORD bytes_transferred = 0;
+  DWORD recv_flags = flags;
+  int result = error_wrapper(::WSARecv(s, bufs,
+        recv_buf_count, &bytes_transferred, &recv_flags, 0, 0), ec);
+  if (ec.value() == ERROR_NETNAME_DELETED)
+    ec = asio::error::connection_reset;
+  else if (ec.value() == ERROR_PORT_UNREACHABLE)
+    ec = asio::error::connection_refused;
+  if (result != 0)
+    return socket_error_retval;
+  ec = asio::error_code();
+  return bytes_transferred;
+#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+  msghdr msg = msghdr();
+  msg.msg_iov = bufs;
+  msg.msg_iovlen = count;
+  int result = error_wrapper(::recvmsg(s, &msg, flags), ec);
+  if (result >= 0)
+    ec = asio::error_code();
+  return result;
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+}
+
+ASIO_DECL
+size_t sync_recv(socket_type s, state_type state, buf* bufs,
+    size_t count, int flags, bool all_empty, asio::error_code& ec)
+{
+  if (s == invalid_socket)
+  {
+    ec = asio::error::bad_descriptor;
+    return 0;
+  }
+
+  // A request to read 0 bytes on a stream is a no-op.
+  if (all_empty && (state & stream_oriented))
+  {
+    ec = asio::error_code();
+    return 0;
+  }
+
+  // Read some data.
+  for (;;)
+  {
+    // Try to complete the operation without blocking.
+    int bytes = socket_ops::recv(s, bufs, count, flags, ec);
+
+    // Check if operation succeeded.
+    if (bytes > 0)
+      return bytes;
+
+    // Check for EOF.
+    if ((state & stream_oriented) && bytes == 0)
+    {
+      ec = asio::error::eof;
+      return 0;
+    }
+
+    // Operation failed.
+    if ((state & user_set_non_blocking)
+        || (ec != asio::error::would_block
+          && ec != asio::error::try_again))
+      return 0;
+
+    // Wait for socket to become ready.
+    if (socket_ops::poll_read(s, ec) < 0)
+      return 0;
+  }
+}
+
+#if defined(ASIO_HAS_IOCP)
+
+ASIO_DECL
+void complete_iocp_recv(state_type state,
+    const weak_cancel_token_type& cancel_token, bool all_empty,
+    asio::error_code& ec, size_t bytes_transferred)
+{
+  // Map non-portable errors to their portable counterparts.
+  if (ec.value() == ERROR_NETNAME_DELETED)
+  {
+    if (cancel_token.expired())
+      ec = asio::error::operation_aborted;
+    else
+      ec = asio::error::connection_reset;
+  }
+  else if (ec.value() == ERROR_PORT_UNREACHABLE)
+  {
+    ec = asio::error::connection_refused;
+  }
+
+  // Check for connection closed.
+  else if (!ec && bytes_transferred == 0
+      && (state & stream_oriented) != 0
+      && !all_empty)
+  {
+    ec = asio::error::eof;
+  }
+}
+
+#else // defined(ASIO_HAS_IOCP)
+
+ASIO_DECL
+bool non_blocking_recv(socket_type s,
+    buf* bufs, size_t count, int flags, bool is_stream,
+    asio::error_code& ec, size_t& bytes_transferred)
+{
+  for (;;)
+  {
+    // Read some data.
+    int bytes = socket_ops::recv(s, bufs, count, flags, ec);
+
+    // Check for end of stream.
+    if (is_stream && bytes == 0)
+    {
+      ec = asio::error::eof;
+      return true;
+    }
+
+    // Retry operation if interrupted by signal.
+    if (ec == asio::error::interrupted)
+      continue;
+
+    // Check if we need to run the operation again.
+    if (ec == asio::error::would_block
+        || ec == asio::error::try_again)
+      return false;
+
+    // Operation is complete.
+    if (bytes >= 0)
+    {
+      ec = asio::error_code();
+      bytes_transferred = bytes;
+    }
+    else
+      bytes_transferred = 0;
+
+    return true;
+  }
+}
+
+#endif // defined(ASIO_HAS_IOCP)
+
+ASIO_DECL
+int recvfrom(socket_type s, buf* bufs, size_t count, int flags,
+    socket_addr_type* addr, std::size_t* addrlen,
+    asio::error_code& ec)
+{
+  clear_last_error();
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+  // Receive some data.
+  DWORD recv_buf_count = static_cast<DWORD>(count);
+  DWORD bytes_transferred = 0;
+  DWORD recv_flags = flags;
+  int tmp_addrlen = (int)*addrlen;
+  int result = error_wrapper(::WSARecvFrom(s, bufs, recv_buf_count,
+        &bytes_transferred, &recv_flags, addr, &tmp_addrlen, 0, 0), ec);
+  *addrlen = (std::size_t)tmp_addrlen;
+  if (ec.value() == ERROR_NETNAME_DELETED)
+    ec = asio::error::connection_reset;
+  else if (ec.value() == ERROR_PORT_UNREACHABLE)
+    ec = asio::error::connection_refused;
+  if (result != 0)
+    return socket_error_retval;
+  ec = asio::error_code();
+  return bytes_transferred;
+#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+  msghdr msg = msghdr();
+  init_msghdr_msg_name(msg.msg_name, addr);
+  msg.msg_namelen = *addrlen;
+  msg.msg_iov = bufs;
+  msg.msg_iovlen = count;
+  int result = error_wrapper(::recvmsg(s, &msg, flags), ec);
+  *addrlen = msg.msg_namelen;
+  if (result >= 0)
+    ec = asio::error_code();
+  return result;
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+}
+
+ASIO_DECL
+size_t sync_recvfrom(socket_type s, state_type state, buf* bufs,
+    size_t count, int flags, socket_addr_type* addr,
+    std::size_t* addrlen, asio::error_code& ec)
+{
+  if (s == invalid_socket)
+  {
+    ec = asio::error::bad_descriptor;
+    return 0;
+  }
+
+  // Read some data.
+  for (;;)
+  {
+    // Try to complete the operation without blocking.
+    int bytes = socket_ops::recvfrom(s, bufs, count, flags, addr, addrlen, ec);
+
+    // Check if operation succeeded.
+    if (bytes >= 0)
+      return bytes;
+
+    // Operation failed.
+    if ((state & user_set_non_blocking)
+        || (ec != asio::error::would_block
+          && ec != asio::error::try_again))
+      return 0;
+
+    // Wait for socket to become ready.
+    if (socket_ops::poll_read(s, ec) < 0)
+      return 0;
+  }
+}
+
+#if defined(ASIO_HAS_IOCP)
+
+ASIO_DECL
+void complete_iocp_recvfrom(
+    const weak_cancel_token_type& cancel_token,
+    asio::error_code& ec)
+{
+  // Map non-portable errors to their portable counterparts.
+  if (ec.value() == ERROR_NETNAME_DELETED)
+  {
+    if (cancel_token.expired())
+      ec = asio::error::operation_aborted;
+    else
+      ec = asio::error::connection_reset;
+  }
+  else if (ec.value() == ERROR_PORT_UNREACHABLE)
+  {
+    ec = asio::error::connection_refused;
+  }
+}
+
+#else // defined(ASIO_HAS_IOCP)
+
+ASIO_DECL
+bool non_blocking_recvfrom(socket_type s,
+    buf* bufs, size_t count, int flags,
+    socket_addr_type* addr, std::size_t* addrlen,
+    asio::error_code& ec, size_t& bytes_transferred)
+{
+  for (;;)
+  {
+    // Read some data.
+    int bytes = socket_ops::recvfrom(s, bufs, count, flags, addr, addrlen, ec);
+
+    // Retry operation if interrupted by signal.
+    if (ec == asio::error::interrupted)
+      continue;
+
+    // Check if we need to run the operation again.
+    if (ec == asio::error::would_block
+        || ec == asio::error::try_again)
+      return false;
+
+    // Operation is complete.
+    if (bytes >= 0)
+    {
+      ec = asio::error_code();
+      bytes_transferred = bytes;
+    }
+    else
+      bytes_transferred = 0;
+
+    return true;
+  }
+}
+
+#endif // defined(ASIO_HAS_IOCP)
+
+ASIO_DECL
+int send(socket_type s, const buf* bufs, size_t count, int flags,
+    asio::error_code& ec)
+{
+  clear_last_error();
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+  // Send the data.
+  DWORD send_buf_count = static_cast<DWORD>(count);
+  DWORD bytes_transferred = 0;
+  DWORD send_flags = flags;
+  int result = error_wrapper(::WSASend(s, const_cast<buf*>(bufs),
+        send_buf_count, &bytes_transferred, send_flags, 0, 0), ec);
+  if (ec.value() == ERROR_NETNAME_DELETED)
+    ec = asio::error::connection_reset;
+  else if (ec.value() == ERROR_PORT_UNREACHABLE)
+    ec = asio::error::connection_refused;
+  if (result != 0)
+    return socket_error_retval;
+  ec = asio::error_code();
+  return bytes_transferred;
+#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+  msghdr msg = msghdr();
+  msg.msg_iov = const_cast<buf*>(bufs);
+  msg.msg_iovlen = count;
+#if defined(__linux__)
+  flags |= MSG_NOSIGNAL;
+#endif // defined(__linux__)
+  int result = error_wrapper(::sendmsg(s, &msg, flags), ec);
+  if (result >= 0)
+    ec = asio::error_code();
+  return result;
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+}
+
+ASIO_DECL
+size_t sync_send(socket_type s, state_type state, const buf* bufs,
+    size_t count, int flags, bool all_empty, asio::error_code& ec)
+{
+  if (s == invalid_socket)
+  {
+    ec = asio::error::bad_descriptor;
+    return 0;
+  }
+
+  // A request to write 0 bytes to a stream is a no-op.
+  if (all_empty && (state & stream_oriented))
+  {
+    ec = asio::error_code();
+    return 0;
+  }
+
+  // Read some data.
+  for (;;)
+  {
+    // Try to complete the operation without blocking.
+    int bytes = socket_ops::send(s, bufs, count, flags, ec);
+
+    // Check if operation succeeded.
+    if (bytes >= 0)
+      return bytes;
+
+    // Operation failed.
+    if ((state & user_set_non_blocking)
+        || (ec != asio::error::would_block
+          && ec != asio::error::try_again))
+      return 0;
+
+    // Wait for socket to become ready.
+    if (socket_ops::poll_write(s, ec) < 0)
+      return 0;
+  }
+}
+
+#if defined(ASIO_HAS_IOCP)
+
+ASIO_DECL
+void complete_iocp_send(
+    const weak_cancel_token_type& cancel_token,
+    asio::error_code& ec)
+{
+  // Map non-portable errors to their portable counterparts.
+  if (ec.value() == ERROR_NETNAME_DELETED)
+  {
+    if (cancel_token.expired())
+      ec = asio::error::operation_aborted;
+    else
+      ec = asio::error::connection_reset;
+  }
+  else if (ec.value() == ERROR_PORT_UNREACHABLE)
+  {
+    ec = asio::error::connection_refused;
+  }
+}
+
+#else // defined(ASIO_HAS_IOCP)
+
+ASIO_DECL
+bool non_blocking_send(socket_type s,
+    const buf* bufs, size_t count, int flags,
+    asio::error_code& ec, size_t& bytes_transferred)
+{
+  for (;;)
+  {
+    // Write some data.
+    int bytes = socket_ops::send(s, bufs, count, flags, ec);
+
+    // Retry operation if interrupted by signal.
+    if (ec == asio::error::interrupted)
+      continue;
+
+    // Check if we need to run the operation again.
+    if (ec == asio::error::would_block
+        || ec == asio::error::try_again)
+      return false;
+
+    // Operation is complete.
+    if (bytes >= 0)
+    {
+      ec = asio::error_code();
+      bytes_transferred = bytes;
+    }
+    else
+      bytes_transferred = 0;
+
+    return true;
+  }
+}
+
+#endif // defined(ASIO_HAS_IOCP)
+
+ASIO_DECL
+int sendto(socket_type s, const buf* bufs, size_t count, int flags,
+    const socket_addr_type* addr, std::size_t addrlen,
+    asio::error_code& ec)
+{
+  clear_last_error();
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+  // Send the data.
+  DWORD send_buf_count = static_cast<DWORD>(count);
+  DWORD bytes_transferred = 0;
+  int result = error_wrapper(::WSASendTo(s, const_cast<buf*>(bufs),
+        send_buf_count, &bytes_transferred, flags, addr,
+        static_cast<int>(addrlen), 0, 0), ec);
+  if (ec.value() == ERROR_NETNAME_DELETED)
+    ec = asio::error::connection_reset;
+  else if (ec.value() == ERROR_PORT_UNREACHABLE)
+    ec = asio::error::connection_refused;
+  if (result != 0)
+    return socket_error_retval;
+  ec = asio::error_code();
+  return bytes_transferred;
+#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+  msghdr msg = msghdr();
+  init_msghdr_msg_name(msg.msg_name, addr);
+  msg.msg_namelen = addrlen;
+  msg.msg_iov = const_cast<buf*>(bufs);
+  msg.msg_iovlen = count;
+#if defined(__linux__)
+  flags |= MSG_NOSIGNAL;
+#endif // defined(__linux__)
+  int result = error_wrapper(::sendmsg(s, &msg, flags), ec);
+  if (result >= 0)
+    ec = asio::error_code();
+  return result;
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+}
+
+ASIO_DECL
+size_t sync_sendto(socket_type s, state_type state, const buf* bufs,
+    size_t count, int flags, const socket_addr_type* addr,
+    std::size_t addrlen, asio::error_code& ec)
+{
+  if (s == invalid_socket)
+  {
+    ec = asio::error::bad_descriptor;
+    return 0;
+  }
+
+  // Write some data.
+  for (;;)
+  {
+    // Try to complete the operation without blocking.
+    int bytes = socket_ops::sendto(s, bufs, count, flags, addr, addrlen, ec);
+
+    // Check if operation succeeded.
+    if (bytes >= 0)
+      return bytes;
+
+    // Operation failed.
+    if ((state & user_set_non_blocking)
+        || (ec != asio::error::would_block
+          && ec != asio::error::try_again))
+      return 0;
+
+    // Wait for socket to become ready.
+    if (socket_ops::poll_write(s, ec) < 0)
+      return 0;
+  }
+}
+
+#if !defined(ASIO_HAS_IOCP)
+
+ASIO_DECL
+bool non_blocking_sendto(socket_type s,
+    const buf* bufs, size_t count, int flags,
+    const socket_addr_type* addr, std::size_t addrlen,
+    asio::error_code& ec, size_t& bytes_transferred)
+{
+  for (;;)
+  {
+    // Write some data.
+    int bytes = socket_ops::sendto(s, bufs, count, flags, addr, addrlen, ec);
+
+    // Retry operation if interrupted by signal.
+    if (ec == asio::error::interrupted)
+      continue;
+
+    // Check if we need to run the operation again.
+    if (ec == asio::error::would_block
+        || ec == asio::error::try_again)
+      return false;
+
+    // Operation is complete.
+    if (bytes >= 0)
+    {
+      ec = asio::error_code();
+      bytes_transferred = bytes;
+    }
+    else
+      bytes_transferred = 0;
+
+    return true;
+  }
+}
+
+#endif // !defined(ASIO_HAS_IOCP)
+
+ASIO_DECL
+socket_type socket(int af, int type, int protocol,
+    asio::error_code& ec)
+{
+  clear_last_error();
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+  socket_type s = error_wrapper(::WSASocket(af, type, protocol, 0, 0,
+        WSA_FLAG_OVERLAPPED), ec);
+  if (s == invalid_socket)
+    return s;
+
+  if (af == AF_INET6)
+  {
+    // Try to enable the POSIX default behaviour of having IPV6_V6ONLY set to
+    // false. This will only succeed on Windows Vista and later versions of
+    // Windows, where a dual-stack IPv4/v6 implementation is available.
+    DWORD optval = 0;
+    ::setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
+        reinterpret_cast<const char*>(&optval), sizeof(optval));
+  }
+
+  ec = asio::error_code();
+
+  return s;
+#elif defined(__MACH__) && defined(__APPLE__) || defined(__FreeBSD__)
+  socket_type s = error_wrapper(::socket(af, type, protocol), ec);
+  if (s == invalid_socket)
+    return s;
+
+  int optval = 1;
+  int result = error_wrapper(::setsockopt(s,
+        SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval)), ec);
+  if (result != 0)
+  {
+    ::close(s);
+    return invalid_socket;
+  }
+
+  return s;
+#else
+  int s = error_wrapper(::socket(af, type, protocol), ec);
+  if (s >= 0)
+    ec = asio::error_code();
+  return s;
+#endif
+}
+
+template <typename SockLenType>
+inline int call_setsockopt(SockLenType msghdr::*,
+    socket_type s, int level, int optname,
+    const void* optval, std::size_t optlen)
+{
+  return ::setsockopt(s, level, optname,
+      (const char*)optval, (SockLenType)optlen);
+}
+
+ASIO_DECL
+int setsockopt(socket_type s, state_type& state, int level, int optname,
+    const void* optval, std::size_t optlen, asio::error_code& ec)
+{
+  if (s == invalid_socket)
+  {
+    ec = asio::error::bad_descriptor;
+    return socket_error_retval;
+  }
+
+  if (level == custom_socket_option_level && optname == always_fail_option)
+  {
+    ec = asio::error::invalid_argument;
+    return socket_error_retval;
+  }
+
+  if (level == custom_socket_option_level
+      && optname == enable_connection_aborted_option)
+  {
+    if (optlen != sizeof(int))
+    {
+      ec = asio::error::invalid_argument;
+      return socket_error_retval;
+    }
+
+    if (*static_cast<const int*>(optval))
+      state |= enable_connection_aborted;
+    else
+      state &= ~enable_connection_aborted;
+    ec = asio::error_code();
+    return 0;
+  }
+
+  if (level == SOL_SOCKET && optname == SO_LINGER)
+    state |= user_set_linger;
+
+#if defined(__BORLANDC__)
+  // Mysteriously, using the getsockopt and setsockopt functions directly with
+  // Borland C++ results in incorrect values being set and read. The bug can be
+  // worked around by using function addresses resolved with GetProcAddress.
+  if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32"))
+  {
+    typedef int (WSAAPI *sso_t)(SOCKET, int, int, const char*, int);
+    if (sso_t sso = (sso_t)::GetProcAddress(winsock_module, "setsockopt"))
+    {
+      clear_last_error();
+      return error_wrapper(sso(s, level, optname,
+            reinterpret_cast<const char*>(optval),
+            static_cast<int>(optlen)), ec);
+    }
+  }
+  ec = asio::error::fault;
+  return socket_error_retval;
+#else // defined(__BORLANDC__)
+  clear_last_error();
+  int result = error_wrapper(call_setsockopt(&msghdr::msg_namelen,
+        s, level, optname, optval, optlen), ec);
+  if (result == 0)
+  {
+    ec = asio::error_code();
+
+#if defined(__MACH__) && defined(__APPLE__) \
+  || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
+    // To implement portable behaviour for SO_REUSEADDR with UDP sockets we
+    // need to also set SO_REUSEPORT on BSD-based platforms.
+    if ((state & datagram_oriented)
+        && level == SOL_SOCKET && optname == SO_REUSEADDR)
+    {
+      call_setsockopt(&msghdr::msg_namelen, s,
+          SOL_SOCKET, SO_REUSEPORT, optval, optlen);
+    }
+#endif
+  }
+
+  return result;
+#endif // defined(__BORLANDC__)
+}
+
+template <typename SockLenType>
+inline int call_getsockopt(SockLenType msghdr::*,
+    socket_type s, int level, int optname,
+    void* optval, std::size_t* optlen)
+{
+  SockLenType tmp_optlen = (SockLenType)*optlen;
+  int result = ::getsockopt(s, level, optname, (char*)optval, &tmp_optlen);
+  *optlen = (std::size_t)tmp_optlen;
+  return result;
+}
+
+ASIO_DECL
+int getsockopt(socket_type s, state_type state, int level, int optname,
+    void* optval, size_t* optlen, asio::error_code& ec)
+{
+  if (s == invalid_socket)
+  {
+    ec = asio::error::bad_descriptor;
+    return socket_error_retval;
+  }
+
+  if (level == custom_socket_option_level && optname == always_fail_option)
+  {
+    ec = asio::error::invalid_argument;
+    return socket_error_retval;
+  }
+
+  if (level == custom_socket_option_level
+      && optname == enable_connection_aborted_option)
+  {
+    if (*optlen != sizeof(int))
+    {
+      ec = asio::error::invalid_argument;
+      return socket_error_retval;
+    }
+
+    *static_cast<int*>(optval) = (state & enable_connection_aborted) ? 1 : 0;
+    ec = asio::error_code();
+    return 0;
+  }
+
+#if defined(__BORLANDC__)
+  // Mysteriously, using the getsockopt and setsockopt functions directly with
+  // Borland C++ results in incorrect values being set and read. The bug can be
+  // worked around by using function addresses resolved with GetProcAddress.
+  if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32"))
+  {
+    typedef int (WSAAPI *gso_t)(SOCKET, int, int, char*, int*);
+    if (gso_t gso = (gso_t)::GetProcAddress(winsock_module, "getsockopt"))
+    {
+      clear_last_error();
+      int tmp_optlen = static_cast<int>(*optlen);
+      int result = error_wrapper(gso(s, level, optname,
+            reinterpret_cast<char*>(optval), &tmp_optlen), ec);
+      *optlen = static_cast<size_t>(tmp_optlen);
+      if (result != 0 && level == IPPROTO_IPV6 && optname == IPV6_V6ONLY
+          && ec.value() == WSAENOPROTOOPT && *optlen == sizeof(DWORD))
+      {
+        // Dual-stack IPv4/v6 sockets, and the IPV6_V6ONLY socket option, are
+        // only supported on Windows Vista and later. To simplify program logic
+        // we will fake success of getting this option and specify that the
+        // value is non-zero (i.e. true). This corresponds to the behavior of
+        // IPv6 sockets on Windows platforms pre-Vista.
+        *static_cast<DWORD*>(optval) = 1;
+        ec = asio::error_code();
+      }
+      return result;
+    }
+  }
+  ec = asio::error::fault;
+  return socket_error_retval;
+#elif defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+  clear_last_error();
+  int result = error_wrapper(call_getsockopt(&msghdr::msg_namelen,
+        s, level, optname, optval, optlen), ec);
+  if (result != 0 && level == IPPROTO_IPV6 && optname == IPV6_V6ONLY
+      && ec.value() == WSAENOPROTOOPT && *optlen == sizeof(DWORD))
+  {
+    // Dual-stack IPv4/v6 sockets, and the IPV6_V6ONLY socket option, are only
+    // supported on Windows Vista and later. To simplify program logic we will
+    // fake success of getting this option and specify that the value is
+    // non-zero (i.e. true). This corresponds to the behavior of IPv6 sockets
+    // on Windows platforms pre-Vista.
+    *static_cast<DWORD*>(optval) = 1;
+    ec = asio::error_code();
+  }
+  if (result == 0)
+    ec = asio::error_code();
+  return result;
+#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+  clear_last_error();
+  int result = error_wrapper(call_getsockopt(&msghdr::msg_namelen,
+        s, level, optname, optval, optlen), ec);
+#if defined(__linux__)
+  if (result == 0 && level == SOL_SOCKET && *optlen == sizeof(int)
+      && (optname == SO_SNDBUF || optname == SO_RCVBUF))
+  {
+    // On Linux, setting SO_SNDBUF or SO_RCVBUF to N actually causes the kernel
+    // to set the buffer size to N*2. Linux puts additional stuff into the
+    // buffers so that only about half is actually available to the application.
+    // The retrieved value is divided by 2 here to make it appear as though the
+    // correct value has been set.
+    *static_cast<int*>(optval) /= 2;
+  }
+#endif // defined(__linux__)
+  if (result == 0)
+    ec = asio::error_code();
+  return result;
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+}
+
+template <typename SockLenType>
+inline int call_getpeername(SockLenType msghdr::*,
+    socket_type s, socket_addr_type* addr, std::size_t* addrlen)
+{
+  SockLenType tmp_addrlen = (SockLenType)*addrlen;
+  int result = ::getpeername(s, addr, &tmp_addrlen);
+  *addrlen = (std::size_t)tmp_addrlen;
+  return result;
+}
+
+ASIO_DECL
+int getpeername(socket_type s, socket_addr_type* addr,
+    std::size_t* addrlen, bool cached, asio::error_code& ec)
+{
+  if (s == invalid_socket)
+  {
+    ec = asio::error::bad_descriptor;
+    return socket_error_retval;
+  }
+
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+  if (cached)
+  {
+    // Check if socket is still connected.
+    DWORD connect_time = 0;
+    size_t connect_time_len = sizeof(connect_time);
+    if (socket_ops::getsockopt(s, 0, SOL_SOCKET, SO_CONNECT_TIME,
+          &connect_time, &connect_time_len, ec) == socket_error_retval)
+    {
+      return socket_error_retval;
+    }
+    if (connect_time == 0xFFFFFFFF)
+    {
+      ec = asio::error::not_connected;
+      return socket_error_retval;
+    }
+
+    // The cached value is still valid.
+    ec = asio::error_code();
+    return 0;
+  }
+#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+  (void)cached;
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+
+  clear_last_error();
+  int result = error_wrapper(call_getpeername(
+        &msghdr::msg_namelen, s, addr, addrlen), ec);
+  if (result == 0)
+    ec = asio::error_code();
+  return result;
+}
+
+template <typename SockLenType>
+inline int call_getsockname(SockLenType msghdr::*,
+    socket_type s, socket_addr_type* addr, std::size_t* addrlen)
+{
+  SockLenType tmp_addrlen = (SockLenType)*addrlen;
+  int result = ::getsockname(s, addr, &tmp_addrlen);
+  *addrlen = (std::size_t)tmp_addrlen;
+  return result;
+}
+
+ASIO_DECL
+int getsockname(socket_type s, socket_addr_type* addr,
+    std::size_t* addrlen, asio::error_code& ec)
+{
+  if (s == invalid_socket)
+  {
+    ec = asio::error::bad_descriptor;
+    return socket_error_retval;
+  }
+
+  clear_last_error();
+  int result = error_wrapper(call_getsockname(
+        &msghdr::msg_namelen, s, addr, addrlen), ec);
+  if (result == 0)
+    ec = asio::error_code();
+  return result;
+}
+
+ASIO_DECL
+int ioctl(socket_type s, state_type& state, int cmd,
+    ioctl_arg_type* arg, asio::error_code& ec)
+{
+  if (s == invalid_socket)
+  {
+    ec = asio::error::bad_descriptor;
+    return socket_error_retval;
+  }
+
+  clear_last_error();
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+  int result = error_wrapper(::ioctlsocket(s, cmd, arg), ec);
+#elif defined(__MACH__) && defined(__APPLE__) \
+  || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
+  int result = error_wrapper(::ioctl(s,
+        static_cast<unsigned int>(cmd), arg), ec);
+#else
+  int result = error_wrapper(::ioctl(s, cmd, arg), ec);
+#endif
+  if (result >= 0)
+  {
+    ec = asio::error_code();
+
+    // When updating the non-blocking mode we always perform the ioctl syscall,
+    // even if the flags would otherwise indicate that the socket is already in
+    // the correct state. This ensures that the underlying socket is put into
+    // the state that has been requested by the user. If the ioctl syscall was
+    // successful then we need to update the flags to match.
+    if (cmd == static_cast<int>(FIONBIO))
+    {
+      if (*arg)
+      {
+        state |= user_set_non_blocking;
+      }
+      else
+      {
+        // Clearing the non-blocking mode always overrides any internally-set
+        // non-blocking flag. Any subsequent asynchronous operations will need
+        // to re-enable non-blocking I/O.
+        state &= ~(user_set_non_blocking | internal_non_blocking);
+      }
+    }
+  }
+
+  return result;
+}
+
+ASIO_DECL
+int select(int nfds, fd_set* readfds, fd_set* writefds,
+    fd_set* exceptfds, timeval* timeout, asio::error_code& ec)
+{
+  clear_last_error();
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+  if (!readfds && !writefds && !exceptfds && timeout)
+  {
+    DWORD milliseconds = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
+    if (milliseconds == 0)
+      milliseconds = 1; // Force context switch.
+    ::Sleep(milliseconds);
+    ec = asio::error_code();
+    return 0;
+  }
+
+  // The select() call allows timeout values measured in microseconds, but the
+  // system clock (as wrapped by boost::posix_time::microsec_clock) typically
+  // has a resolution of 10 milliseconds. This can lead to a spinning select
+  // reactor, meaning increased CPU usage, when waiting for the earliest
+  // scheduled timeout if it's less than 10 milliseconds away. To avoid a tight
+  // spin we'll use a minimum timeout of 1 millisecond.
+  if (timeout && timeout->tv_sec == 0
+      && timeout->tv_usec > 0 && timeout->tv_usec < 1000)
+    timeout->tv_usec = 1000;
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+
+#if defined(__hpux) && defined(__SELECT)
+  timespec ts;
+  ts.tv_sec = timeout ? timeout->tv_sec : 0;
+  ts.tv_nsec = timeout ? timeout->tv_usec * 1000 : 0;
+  return error_wrapper(::pselect(nfds, readfds,
+        writefds, exceptfds, timeout ? &ts : 0, 0), ec);
+#else
+  int result = error_wrapper(::select(nfds, readfds,
+        writefds, exceptfds, timeout), ec);
+  if (result >= 0)
+    ec = asio::error_code();
+  return result;
+#endif
+}
+
+ASIO_DECL
+int poll_read(socket_type s, asio::error_code& ec)
+{
+  if (s == invalid_socket)
+  {
+    ec = asio::error::bad_descriptor;
+    return socket_error_retval;
+  }
+
+#if defined(BOOST_WINDOWS) \
+  || defined(__CYGWIN__) \
+  || defined(__SYMBIAN32__)
+  fd_set fds;
+  FD_ZERO(&fds);
+  FD_SET(s, &fds);
+  clear_last_error();
+  int result = error_wrapper(::select(s, &fds, 0, 0, 0), ec);
+  if (result >= 0)
+    ec = asio::error_code();
+  return result;
+#else // defined(BOOST_WINDOWS)
+      // || defined(__CYGWIN__)
+      // || defined(__SYMBIAN32__)
+  pollfd fds;
+  fds.fd = s;
+  fds.events = POLLIN;
+  fds.revents = 0;
+  clear_last_error();
+  int result = error_wrapper(::poll(&fds, 1, -1), ec);
+  if (result >= 0)
+    ec = asio::error_code();
+  return result;
+#endif // defined(BOOST_WINDOWS)
+       // || defined(__CYGWIN__)
+       // || defined(__SYMBIAN32__)
+}
+
+ASIO_DECL
+int poll_write(socket_type s, asio::error_code& ec)
+{
+  if (s == invalid_socket)
+  {
+    ec = asio::error::bad_descriptor;
+    return socket_error_retval;
+  }
+
+#if defined(BOOST_WINDOWS) \
+  || defined(__CYGWIN__) \
+  || defined(__SYMBIAN32__)
+  fd_set fds;
+  FD_ZERO(&fds);
+  FD_SET(s, &fds);
+  clear_last_error();
+  int result = error_wrapper(::select(s, 0, &fds, 0, 0), ec);
+  if (result >= 0)
+    ec = asio::error_code();
+  return result;
+#else // defined(BOOST_WINDOWS)
+      // || defined(__CYGWIN__)
+      // || defined(__SYMBIAN32__)
+  pollfd fds;
+  fds.fd = s;
+  fds.events = POLLOUT;
+  fds.revents = 0;
+  clear_last_error();
+  int result = error_wrapper(::poll(&fds, 1, -1), ec);
+  if (result >= 0)
+    ec = asio::error_code();
+  return result;
+#endif // defined(BOOST_WINDOWS)
+       // || defined(__CYGWIN__)
+       // || defined(__SYMBIAN32__)
+}
+
+ASIO_DECL
+int poll_connect(socket_type s, asio::error_code& ec)
+{
+  if (s == invalid_socket)
+  {
+    ec = asio::error::bad_descriptor;
+    return socket_error_retval;
+  }
+
+#if defined(BOOST_WINDOWS) \
+  || defined(__CYGWIN__) \
+  || defined(__SYMBIAN32__)
+  fd_set write_fds;
+  FD_ZERO(&write_fds);
+  FD_SET(s, &write_fds);
+  fd_set except_fds;
+  FD_ZERO(&except_fds);
+  FD_SET(s, &except_fds);
+  clear_last_error();
+  int result = error_wrapper(::select(s, 0, &write_fds, &except_fds, 0), ec);
+  if (result >= 0)
+    ec = asio::error_code();
+  return result;
+#else // defined(BOOST_WINDOWS)
+      // || defined(__CYGWIN__)
+      // || defined(__SYMBIAN32__)
+  pollfd fds;
+  fds.fd = s;
+  fds.events = POLLOUT;
+  fds.revents = 0;
+  clear_last_error();
+  int result = error_wrapper(::poll(&fds, 1, -1), ec);
+  if (result >= 0)
+    ec = asio::error_code();
+  return result;
+#endif // defined(BOOST_WINDOWS)
+       // || defined(__CYGWIN__)
+       // || defined(__SYMBIAN32__)
+}
+
+ASIO_DECL
+const char* inet_ntop(int af, const void* src, char* dest, size_t length,
+    unsigned long scope_id, asio::error_code& ec)
+{
+  clear_last_error();
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+  using namespace std; // For memcpy.
+
+  if (af != AF_INET && af != AF_INET6)
+  {
+    ec = asio::error::address_family_not_supported;
+    return 0;
+  }
+
+  union
+  {
+    socket_addr_type base;
+    sockaddr_storage_type storage;
+    sockaddr_in4_type v4;
+    sockaddr_in6_type v6;
+  } address;
+  DWORD address_length;
+  if (af == AF_INET)
+  {
+    address_length = sizeof(sockaddr_in4_type);
+    address.v4.sin_family = AF_INET;
+    address.v4.sin_port = 0;
+    memcpy(&address.v4.sin_addr, src, sizeof(in4_addr_type));
+  }
+  else // AF_INET6
+  {
+    address_length = sizeof(sockaddr_in6_type);
+    address.v6.sin6_family = AF_INET6;
+    address.v6.sin6_port = 0;
+    address.v6.sin6_flowinfo = 0;
+    address.v6.sin6_scope_id = scope_id;
+    memcpy(&address.v6.sin6_addr, src, sizeof(in6_addr_type));
+  }
+
+  DWORD string_length = static_cast<DWORD>(length);
+#if defined(BOOST_NO_ANSI_APIS)
+  LPWSTR string_buffer = (LPWSTR)_alloca(length * sizeof(WCHAR));
+  int result = error_wrapper(::WSAAddressToStringW(&address.base,
+        address_length, 0, string_buffer, &string_length), ec);
+  ::WideCharToMultiByte(CP_ACP, 0, string_buffer, -1, dest, length, 0, 0);
+#else
+  int result = error_wrapper(::WSAAddressToStringA(
+        &address.base, address_length, 0, dest, &string_length), ec);
+#endif
+
+  // Windows may set error code on success.
+  if (result != socket_error_retval)
+    ec = asio::error_code();
+
+  // Windows may not set an error code on failure.
+  else if (result == socket_error_retval && !ec)
+    ec = asio::error::invalid_argument;
+
+  return result == socket_error_retval ? 0 : dest;
+#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+  const char* result = error_wrapper(::inet_ntop(af, src, dest, length), ec);
+  if (result == 0 && !ec)
+    ec = asio::error::invalid_argument;
+  if (result != 0 && af == AF_INET6 && scope_id != 0)
+  {
+    using namespace std; // For strcat and sprintf.
+    char if_name[IF_NAMESIZE + 1] = "%";
+    const in6_addr_type* ipv6_address = static_cast<const in6_addr_type*>(src);
+    bool is_link_local = IN6_IS_ADDR_LINKLOCAL(ipv6_address);
+    if (!is_link_local || if_indextoname(scope_id, if_name + 1) == 0)
+      sprintf(if_name + 1, "%lu", scope_id);
+    strcat(dest, if_name);
+  }
+  return result;
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+}
+
+ASIO_DECL
+int inet_pton(int af, const char* src, void* dest,
+    unsigned long* scope_id, asio::error_code& ec)
+{
+  clear_last_error();
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+  using namespace std; // For memcpy and strcmp.
+
+  if (af != AF_INET && af != AF_INET6)
+  {
+    ec = asio::error::address_family_not_supported;
+    return -1;
+  }
+
+  union
+  {
+    socket_addr_type base;
+    sockaddr_storage_type storage;
+    sockaddr_in4_type v4;
+    sockaddr_in6_type v6;
+  } address;
+  int address_length = sizeof(sockaddr_storage_type);
+#if defined(BOOST_NO_ANSI_APIS)
+  int num_wide_chars = strlen(src) + 1;
+  LPWSTR wide_buffer = (LPWSTR)_alloca(num_wide_chars * sizeof(WCHAR));
+  ::MultiByteToWideChar(CP_ACP, 0, src, -1, wide_buffer, num_wide_chars);
+  int result = error_wrapper(::WSAStringToAddressW(
+        wide_buffer, af, 0, &address.base, &address_length), ec);
+#else
+  int result = error_wrapper(::WSAStringToAddressA(
+        const_cast<char*>(src), af, 0, &address.base, &address_length), ec);
+#endif
+
+  if (af == AF_INET)
+  {
+    if (result != socket_error_retval)
+    {
+      memcpy(dest, &address.v4.sin_addr, sizeof(in4_addr_type));
+      ec = asio::error_code();
+    }
+    else if (strcmp(src, "255.255.255.255") == 0)
+    {
+      static_cast<in4_addr_type*>(dest)->s_addr = INADDR_NONE;
+      ec = asio::error_code();
+    }
+  }
+  else // AF_INET6
+  {
+    if (result != socket_error_retval)
+    {
+      memcpy(dest, &address.v6.sin6_addr, sizeof(in6_addr_type));
+      if (scope_id)
+        *scope_id = address.v6.sin6_scope_id;
+      ec = asio::error_code();
+    }
+  }
+
+  // Windows may not set an error code on failure.
+  if (result == socket_error_retval && !ec)
+    ec = asio::error::invalid_argument;
+
+  if (result != socket_error_retval)
+    ec = asio::error_code();
+
+  return result == socket_error_retval ? -1 : 1;
+#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+  int result = error_wrapper(::inet_pton(af, src, dest), ec);
+  if (result <= 0 && !ec)
+    ec = asio::error::invalid_argument;
+  if (result > 0 && af == AF_INET6 && scope_id)
+  {
+    using namespace std; // For strchr and atoi.
+    *scope_id = 0;
+    if (const char* if_name = strchr(src, '%'))
+    {
+      in6_addr_type* ipv6_address = static_cast<in6_addr_type*>(dest);
+      bool is_link_local = IN6_IS_ADDR_LINKLOCAL(ipv6_address);
+      if (is_link_local)
+        *scope_id = if_nametoindex(if_name + 1);
+      if (*scope_id == 0)
+        *scope_id = atoi(if_name + 1);
+    }
+  }
+  return result;
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+}
+
+ASIO_DECL
+int gethostname(char* name, int namelen, asio::error_code& ec)
+{
+  clear_last_error();
+  int result = error_wrapper(::gethostname(name, namelen), ec);
+#if defined(BOOST_WINDOWS)
+  if (result == 0)
+    ec = asio::error_code();
+#endif
+  return result;
+}
+
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) \
+  || defined(__MACH__) && defined(__APPLE__)
+
+// The following functions are only needed for emulation of getaddrinfo and
+// getnameinfo.
+
+inline asio::error_code translate_netdb_error(int error)
+{
+  switch (error)
+  {
+  case 0:
+    return asio::error_code();
+  case HOST_NOT_FOUND:
+    return asio::error::host_not_found;
+  case TRY_AGAIN:
+    return asio::error::host_not_found_try_again;
+  case NO_RECOVERY:
+    return asio::error::no_recovery;
+  case NO_DATA:
+    return asio::error::no_data;
+  default:
+    BOOST_ASSERT(false);
+    return asio::error::invalid_argument;
+  }
+}
+
+inline hostent* gethostbyaddr(const char* addr, int length, int af,
+    hostent* result, char* buffer, int buflength, asio::error_code& ec)
+{
+  clear_last_error();
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+  (void)(buffer);
+  (void)(buflength);
+  hostent* retval = error_wrapper(::gethostbyaddr(addr, length, af), ec);
+  if (!retval)
+    return 0;
+  ec = asio::error_code();
+  *result = *retval;
+  return retval;
+#elif defined(__sun) || defined(__QNX__)
+  int error = 0;
+  hostent* retval = error_wrapper(::gethostbyaddr_r(addr, length, af, result,
+        buffer, buflength, &error), ec);
+  if (error)
+    ec = translate_netdb_error(error);
+  return retval;
+#elif defined(__MACH__) && defined(__APPLE__)
+  (void)(buffer);
+  (void)(buflength);
+  int error = 0;
+  hostent* retval = error_wrapper(::getipnodebyaddr(
+        addr, length, af, &error), ec);
+  if (error)
+    ec = translate_netdb_error(error);
+  if (!retval)
+    return 0;
+  *result = *retval;
+  return retval;
+#else
+  hostent* retval = 0;
+  int error = 0;
+  error_wrapper(::gethostbyaddr_r(addr, length, af, result, buffer,
+        buflength, &retval, &error), ec);
+  if (error)
+    ec = translate_netdb_error(error);
+  return retval;
+#endif
+}
+
+inline hostent* gethostbyname(const char* name, int af, struct hostent* result,
+    char* buffer, int buflength, int ai_flags, asio::error_code& ec)
+{
+  clear_last_error();
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+  (void)(buffer);
+  (void)(buflength);
+  (void)(ai_flags);
+  if (af != AF_INET)
+  {
+    ec = asio::error::address_family_not_supported;
+    return 0;
+  }
+  hostent* retval = error_wrapper(::gethostbyname(name), ec);
+  if (!retval)
+    return 0;
+  ec = asio::error_code();
+  *result = *retval;
+  return result;
+#elif defined(__sun) || defined(__QNX__)
+  (void)(ai_flags);
+  if (af != AF_INET)
+  {
+    ec = asio::error::address_family_not_supported;
+    return 0;
+  }
+  int error = 0;
+  hostent* retval = error_wrapper(::gethostbyname_r(name, result, buffer,
+        buflength, &error), ec);
+  if (error)
+    ec = translate_netdb_error(error);
+  return retval;
+#elif defined(__MACH__) && defined(__APPLE__)
+  (void)(buffer);
+  (void)(buflength);
+  int error = 0;
+  hostent* retval = error_wrapper(::getipnodebyname(
+        name, af, ai_flags, &error), ec);
+  if (error)
+    ec = translate_netdb_error(error);
+  if (!retval)
+    return 0;
+  *result = *retval;
+  return retval;
+#else
+  (void)(ai_flags);
+  if (af != AF_INET)
+  {
+    ec = asio::error::address_family_not_supported;
+    return 0;
+  }
+  hostent* retval = 0;
+  int error = 0;
+  error_wrapper(::gethostbyname_r(name, result,
+        buffer, buflength, &retval, &error), ec);
+  if (error)
+    ec = translate_netdb_error(error);
+  return retval;
+#endif
+}
+
+inline void freehostent(hostent* h)
+{
+#if defined(__MACH__) && defined(__APPLE__)
+  if (h)
+    ::freehostent(h);
+#else
+  (void)(h);
+#endif
+}
+
+// Emulation of getaddrinfo based on implementation in:
+// Stevens, W. R., UNIX Network Programming Vol. 1, 2nd Ed., Prentice-Hall 1998.
+
+struct gai_search
+{
+  const char* host;
+  int family;
+};
+
+inline int gai_nsearch(const char* host,
+    const addrinfo_type* hints, gai_search (&search)[2])
+{
+  int search_count = 0;
+  if (host == 0 || host[0] == '\0')
+  {
+    if (hints->ai_flags & AI_PASSIVE)
+    {
+      // No host and AI_PASSIVE implies wildcard bind.
+      switch (hints->ai_family)
+      {
+      case AF_INET:
+        search[search_count].host = "0.0.0.0";
+        search[search_count].family = AF_INET;
+        ++search_count;
+        break;
+      case AF_INET6:
+        search[search_count].host = "0::0";
+        search[search_count].family = AF_INET6;
+        ++search_count;
+        break;
+      case AF_UNSPEC:
+        search[search_count].host = "0::0";
+        search[search_count].family = AF_INET6;
+        ++search_count;
+        search[search_count].host = "0.0.0.0";
+        search[search_count].family = AF_INET;
+        ++search_count;
+        break;
+      default:
+        break;
+      }
+    }
+    else
+    {
+      // No host and not AI_PASSIVE means connect to local host.
+      switch (hints->ai_family)
+      {
+      case AF_INET:
+        search[search_count].host = "localhost";
+        search[search_count].family = AF_INET;
+        ++search_count;
+        break;
+      case AF_INET6:
+        search[search_count].host = "localhost";
+        search[search_count].family = AF_INET6;
+        ++search_count;
+        break;
+      case AF_UNSPEC:
+        search[search_count].host = "localhost";
+        search[search_count].family = AF_INET6;
+        ++search_count;
+        search[search_count].host = "localhost";
+        search[search_count].family = AF_INET;
+        ++search_count;
+        break;
+      default:
+        break;
+      }
+    }
+  }
+  else
+  {
+    // Host is specified.
+    switch (hints->ai_family)
+    {
+    case AF_INET:
+      search[search_count].host = host;
+      search[search_count].family = AF_INET;
+      ++search_count;
+      break;
+    case AF_INET6:
+      search[search_count].host = host;
+      search[search_count].family = AF_INET6;
+      ++search_count;
+      break;
+    case AF_UNSPEC:
+      search[search_count].host = host;
+      search[search_count].family = AF_INET6;
+      ++search_count;
+      search[search_count].host = host;
+      search[search_count].family = AF_INET;
+      ++search_count;
+      break;
+    default:
+      break;
+    }
+  }
+  return search_count;
+}
+
+template <typename T>
+inline T* gai_alloc(std::size_t size = sizeof(T))
+{
+  using namespace std;
+  T* p = static_cast<T*>(::operator new(size, std::nothrow));
+  if (p)
+    memset(p, 0, size);
+  return p;
+}
+
+inline void gai_free(void* p)
+{
+  ::operator delete(p);
+}
+
+inline void gai_strcpy(char* target, const char* source, std::size_t max_size)
+{
+  using namespace std;
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) && !defined(UNDER_CE)
+  strcpy_s(target, max_size, source);
+#else
+  *target = 0;
+  strncat(target, source, max_size);
+#endif
+}
+
+enum { gai_clone_flag = 1 << 30 };
+
+inline int gai_aistruct(addrinfo_type*** next, const addrinfo_type* hints,
+    const void* addr, int family)
+{
+  using namespace std;
+
+  addrinfo_type* ai = gai_alloc<addrinfo_type>();
+  if (ai == 0)
+    return EAI_MEMORY;
+
+  ai->ai_next = 0;
+  **next = ai;
+  *next = &ai->ai_next;
+
+  ai->ai_canonname = 0;
+  ai->ai_socktype = hints->ai_socktype;
+  if (ai->ai_socktype == 0)
+    ai->ai_flags |= gai_clone_flag;
+  ai->ai_protocol = hints->ai_protocol;
+  ai->ai_family = family;
+
+  switch (ai->ai_family)
+  {
+  case AF_INET:
+    {
+      sockaddr_in4_type* sinptr = gai_alloc<sockaddr_in4_type>();
+      if (sinptr == 0)
+        return EAI_MEMORY;
+      sinptr->sin_family = AF_INET;
+      memcpy(&sinptr->sin_addr, addr, sizeof(in4_addr_type));
+      ai->ai_addr = reinterpret_cast<sockaddr*>(sinptr);
+      ai->ai_addrlen = sizeof(sockaddr_in4_type);
+      break;
+    }
+  case AF_INET6:
+    {
+      sockaddr_in6_type* sin6ptr = gai_alloc<sockaddr_in6_type>();
+      if (sin6ptr == 0)
+        return EAI_MEMORY;
+      sin6ptr->sin6_family = AF_INET6;
+      memcpy(&sin6ptr->sin6_addr, addr, sizeof(in6_addr_type));
+      ai->ai_addr = reinterpret_cast<sockaddr*>(sin6ptr);
+      ai->ai_addrlen = sizeof(sockaddr_in6_type);
+      break;
+    }
+  default:
+    break;
+  }
+
+  return 0;
+}
+
+inline addrinfo_type* gai_clone(addrinfo_type* ai)
+{
+  using namespace std;
+
+  addrinfo_type* new_ai = gai_alloc<addrinfo_type>();
+  if (new_ai == 0)
+    return new_ai;
+
+  new_ai->ai_next = ai->ai_next;
+  ai->ai_next = new_ai;
+
+  new_ai->ai_flags = 0;
+  new_ai->ai_family = ai->ai_family;
+  new_ai->ai_socktype = ai->ai_socktype;
+  new_ai->ai_protocol = ai->ai_protocol;
+  new_ai->ai_canonname = 0;
+  new_ai->ai_addrlen = ai->ai_addrlen;
+  new_ai->ai_addr = gai_alloc<sockaddr>(ai->ai_addrlen);
+  memcpy(new_ai->ai_addr, ai->ai_addr, ai->ai_addrlen);
+
+  return new_ai;
+}
+
+inline int gai_port(addrinfo_type* aihead, int port, int socktype)
+{
+  int num_found = 0;
+
+  for (addrinfo_type* ai = aihead; ai; ai = ai->ai_next)
+  {
+    if (ai->ai_flags & gai_clone_flag)
+    {
+      if (ai->ai_socktype != 0)
+      {
+        ai = gai_clone(ai);
+        if (ai == 0)
+          return -1;
+        // ai now points to newly cloned entry.
+      }
+    }
+    else if (ai->ai_socktype != socktype)
+    {
+      // Ignore if mismatch on socket type.
+      continue;
+    }
+
+    ai->ai_socktype = socktype;
+
+    switch (ai->ai_family)
+    {
+    case AF_INET:
+      {
+        sockaddr_in4_type* sinptr =
+          reinterpret_cast<sockaddr_in4_type*>(ai->ai_addr);
+        sinptr->sin_port = port;
+        ++num_found;
+        break;
+      }
+    case AF_INET6:
+      {
+        sockaddr_in6_type* sin6ptr =
+          reinterpret_cast<sockaddr_in6_type*>(ai->ai_addr);
+        sin6ptr->sin6_port = port;
+        ++num_found;
+        break;
+      }
+    default:
+      break;
+    }
+  }
+
+  return num_found;
+}
+
+inline int gai_serv(addrinfo_type* aihead,
+    const addrinfo_type* hints, const char* serv)
+{
+  using namespace std;
+
+  int num_found = 0;
+
+  if (
+#if defined(AI_NUMERICSERV)
+      (hints->ai_flags & AI_NUMERICSERV) ||
+#endif
+      isdigit(static_cast<unsigned char>(serv[0])))
+  {
+    int port = htons(atoi(serv));
+    if (hints->ai_socktype)
+    {
+      // Caller specifies socket type.
+      int rc = gai_port(aihead, port, hints->ai_socktype);
+      if (rc < 0)
+        return EAI_MEMORY;
+      num_found += rc;
+    }
+    else
+    {
+      // Caller does not specify socket type.
+      int rc = gai_port(aihead, port, SOCK_STREAM);
+      if (rc < 0)
+        return EAI_MEMORY;
+      num_found += rc;
+      rc = gai_port(aihead, port, SOCK_DGRAM);
+      if (rc < 0)
+        return EAI_MEMORY;
+      num_found += rc;
+    }
+  }
+  else
+  {
+    // Try service name with TCP first, then UDP.
+    if (hints->ai_socktype == 0 || hints->ai_socktype == SOCK_STREAM)
+    {
+      servent* sptr = getservbyname(serv, "tcp");
+      if (sptr != 0)
+      {
+        int rc = gai_port(aihead, sptr->s_port, SOCK_STREAM);
+        if (rc < 0)
+          return EAI_MEMORY;
+        num_found += rc;
+      }
+    }
+    if (hints->ai_socktype == 0 || hints->ai_socktype == SOCK_DGRAM)
+    {
+      servent* sptr = getservbyname(serv, "udp");
+      if (sptr != 0)
+      {
+        int rc = gai_port(aihead, sptr->s_port, SOCK_DGRAM);
+        if (rc < 0)
+          return EAI_MEMORY;
+        num_found += rc;
+      }
+    }
+  }
+
+  if (num_found == 0)
+  {
+    if (hints->ai_socktype == 0)
+    {
+      // All calls to getservbyname() failed.
+      return EAI_NONAME;
+    }
+    else
+    {
+      // Service not supported for socket type.
+      return EAI_SERVICE;
+    }
+  }
+
+  return 0;
+}
+
+inline int gai_echeck(const char* host, const char* service,
+    int flags, int family, int socktype, int protocol)
+{
+  (void)(flags);
+  (void)(protocol);
+
+  // Host or service must be specified.
+  if (host == 0 || host[0] == '\0')
+    if (service == 0 || service[0] == '\0')
+      return EAI_NONAME;
+
+  // Check combination of family and socket type.
+  switch (family)
+  {
+  case AF_UNSPEC:
+    break;
+  case AF_INET:
+  case AF_INET6:
+    if (service != 0 && service[0] != '\0')
+      if (socktype != 0 && socktype != SOCK_STREAM && socktype != SOCK_DGRAM)
+        return EAI_SOCKTYPE;
+    break;
+  default:
+    return EAI_FAMILY;
+  }
+
+  return 0;
+}
+
+inline void freeaddrinfo_emulation(addrinfo_type* aihead)
+{
+  addrinfo_type* ai = aihead;
+  while (ai)
+  {
+    gai_free(ai->ai_addr);
+    gai_free(ai->ai_canonname);
+    addrinfo_type* ainext = ai->ai_next;
+    gai_free(ai);
+    ai = ainext;
+  }
+}
+
+inline int getaddrinfo_emulation(const char* host, const char* service,
+    const addrinfo_type* hintsp, addrinfo_type** result)
+{
+  // Set up linked list of addrinfo structures.
+  addrinfo_type* aihead = 0;
+  addrinfo_type** ainext = &aihead;
+  char* canon = 0;
+
+  // Supply default hints if not specified by caller.
+  addrinfo_type hints = addrinfo_type();
+  hints.ai_family = AF_UNSPEC;
+  if (hintsp)
+    hints = *hintsp;
+
+  // If the resolution is not specifically for AF_INET6, remove the AI_V4MAPPED
+  // and AI_ALL flags.
+#if defined(AI_V4MAPPED)
+  if (hints.ai_family != AF_INET6)
+    hints.ai_flags &= ~AI_V4MAPPED;
+#endif
+#if defined(AI_ALL)
+  if (hints.ai_family != AF_INET6)
+    hints.ai_flags &= ~AI_ALL;
+#endif
+
+  // Basic error checking.
+  int rc = gai_echeck(host, service, hints.ai_flags, hints.ai_family,
+      hints.ai_socktype, hints.ai_protocol);
+  if (rc != 0)
+  {
+    freeaddrinfo_emulation(aihead);
+    return rc;
+  }
+
+  gai_search search[2];
+  int search_count = gai_nsearch(host, &hints, search);
+  for (gai_search* sptr = search; sptr < search + search_count; ++sptr)
+  {
+    // Check for IPv4 dotted decimal string.
+    in4_addr_type inaddr;
+    asio::error_code ec;
+    if (socket_ops::inet_pton(AF_INET, sptr->host, &inaddr, 0, ec) == 1)
+    {
+      if (hints.ai_family != AF_UNSPEC && hints.ai_family != AF_INET)
+      {
+        freeaddrinfo_emulation(aihead);
+        gai_free(canon);
+        return EAI_FAMILY;
+      }
+      if (sptr->family == AF_INET)
+      {
+        rc = gai_aistruct(&ainext, &hints, &inaddr, AF_INET);
+        if (rc != 0)
+        {
+          freeaddrinfo_emulation(aihead);
+          gai_free(canon);
+          return rc;
+        }
+      }
+      continue;
+    }
+
+    // Check for IPv6 hex string.
+    in6_addr_type in6addr;
+    if (socket_ops::inet_pton(AF_INET6, sptr->host, &in6addr, 0, ec) == 1)
+    {
+      if (hints.ai_family != AF_UNSPEC && hints.ai_family != AF_INET6)
+      {
+        freeaddrinfo_emulation(aihead);
+        gai_free(canon);
+        return EAI_FAMILY;
+      }
+      if (sptr->family == AF_INET6)
+      {
+        rc = gai_aistruct(&ainext, &hints, &in6addr, AF_INET6);
+        if (rc != 0)
+        {
+          freeaddrinfo_emulation(aihead);
+          gai_free(canon);
+          return rc;
+        }
+      }
+      continue;
+    }
+
+    // Look up hostname.
+    hostent hent;
+    char hbuf[8192] = "";
+    hostent* hptr = socket_ops::gethostbyname(sptr->host,
+        sptr->family, &hent, hbuf, sizeof(hbuf), hints.ai_flags, ec);
+    if (hptr == 0)
+    {
+      if (search_count == 2)
+      {
+        // Failure is OK if there are multiple searches.
+        continue;
+      }
+      freeaddrinfo_emulation(aihead);
+      gai_free(canon);
+      if (ec == asio::error::host_not_found)
+        return EAI_NONAME;
+      if (ec == asio::error::host_not_found_try_again)
+        return EAI_AGAIN;
+      if (ec == asio::error::no_recovery)
+        return EAI_FAIL;
+      if (ec == asio::error::no_data)
+        return EAI_NONAME;
+      return EAI_NONAME;
+    }
+
+    // Check for address family mismatch if one was specified.
+    if (hints.ai_family != AF_UNSPEC && hints.ai_family != hptr->h_addrtype)
+    {
+      freeaddrinfo_emulation(aihead);
+      gai_free(canon);
+      socket_ops::freehostent(hptr);
+      return EAI_FAMILY;
+    }
+
+    // Save canonical name first time.
+    if (host != 0 && host[0] != '\0' && hptr->h_name && hptr->h_name[0]
+        && (hints.ai_flags & AI_CANONNAME) && canon == 0)
+    {
+      std::size_t canon_len = strlen(hptr->h_name) + 1;
+      canon = gai_alloc<char>(canon_len);
+      if (canon == 0)
+      {
+        freeaddrinfo_emulation(aihead);
+        socket_ops::freehostent(hptr);
+        return EAI_MEMORY;
+      }
+      gai_strcpy(canon, hptr->h_name, canon_len);
+    }
+
+    // Create an addrinfo structure for each returned address.
+    for (char** ap = hptr->h_addr_list; *ap; ++ap)
+    {
+      rc = gai_aistruct(&ainext, &hints, *ap, hptr->h_addrtype);
+      if (rc != 0)
+      {
+        freeaddrinfo_emulation(aihead);
+        gai_free(canon);
+        socket_ops::freehostent(hptr);
+        return EAI_FAMILY;
+      }
+    }
+
+    socket_ops::freehostent(hptr);
+  }
+
+  // Check if we found anything.
+  if (aihead == 0)
+  {
+    gai_free(canon);
+    return EAI_NONAME;
+  }
+
+  // Return canonical name in first entry.
+  if (host != 0 && host[0] != '\0' && (hints.ai_flags & AI_CANONNAME))
+  {
+    if (canon)
+    {
+      aihead->ai_canonname = canon;
+      canon = 0;
+    }
+    else
+    {
+      std::size_t canonname_len = strlen(search[0].host) + 1;
+      aihead->ai_canonname = gai_alloc<char>(canonname_len);
+      if (aihead->ai_canonname == 0)
+      {
+        freeaddrinfo_emulation(aihead);
+        return EAI_MEMORY;
+      }
+      gai_strcpy(aihead->ai_canonname, search[0].host, canonname_len);
+    }
+  }
+  gai_free(canon);
+
+  // Process the service name.
+  if (service != 0 && service[0] != '\0')
+  {
+    rc = gai_serv(aihead, &hints, service);
+    if (rc != 0)
+    {
+      freeaddrinfo_emulation(aihead);
+      return rc;
+    }
+  }
+
+  // Return result to caller.
+  *result = aihead;
+  return 0;
+}
+
+inline asio::error_code getnameinfo_emulation(
+    const socket_addr_type* sa, std::size_t salen, char* host,
+    std::size_t hostlen, char* serv, std::size_t servlen, int flags,
+    asio::error_code& ec)
+{
+  using namespace std;
+
+  const char* addr;
+  size_t addr_len;
+  unsigned short port;
+  switch (sa->sa_family)
+  {
+  case AF_INET:
+    if (salen != sizeof(sockaddr_in4_type))
+    {
+      return ec = asio::error::invalid_argument;
+    }
+    addr = reinterpret_cast<const char*>(
+        &reinterpret_cast<const sockaddr_in4_type*>(sa)->sin_addr);
+    addr_len = sizeof(in4_addr_type);
+    port = reinterpret_cast<const sockaddr_in4_type*>(sa)->sin_port;
+    break;
+  case AF_INET6:
+    if (salen != sizeof(sockaddr_in6_type))
+    {
+      return ec = asio::error::invalid_argument;
+    }
+    addr = reinterpret_cast<const char*>(
+        &reinterpret_cast<const sockaddr_in6_type*>(sa)->sin6_addr);
+    addr_len = sizeof(in6_addr_type);
+    port = reinterpret_cast<const sockaddr_in6_type*>(sa)->sin6_port;
+    break;
+  default:
+    return ec = asio::error::address_family_not_supported;
+  }
+
+  if (host && hostlen > 0)
+  {
+    if (flags & NI_NUMERICHOST)
+    {
+      if (socket_ops::inet_ntop(sa->sa_family, addr, host, hostlen, 0, ec) == 0)
+      {
+        return ec;
+      }
+    }
+    else
+    {
+      hostent hent;
+      char hbuf[8192] = "";
+      hostent* hptr = socket_ops::gethostbyaddr(addr,
+          static_cast<int>(addr_len), sa->sa_family,
+          &hent, hbuf, sizeof(hbuf), ec);
+      if (hptr && hptr->h_name && hptr->h_name[0] != '\0')
+      {
+        if (flags & NI_NOFQDN)
+        {
+          char* dot = strchr(hptr->h_name, '.');
+          if (dot)
+          {
+            *dot = 0;
+          }
+        }
+        gai_strcpy(host, hptr->h_name, hostlen);
+        socket_ops::freehostent(hptr);
+      }
+      else
+      {
+        socket_ops::freehostent(hptr);
+        if (flags & NI_NAMEREQD)
+        {
+          return ec = asio::error::host_not_found;
+        }
+        if (socket_ops::inet_ntop(sa->sa_family,
+              addr, host, hostlen, 0, ec) == 0)
+        {
+          return ec;
+        }
+      }
+    }
+  }
+
+  if (serv && servlen > 0)
+  {
+    if (flags & NI_NUMERICSERV)
+    {
+      if (servlen < 6)
+      {
+        return ec = asio::error::no_buffer_space;
+      }
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) && !defined(UNDER_CE)
+      sprintf_s(serv, servlen, "%u", ntohs(port));
+#else
+      sprintf(serv, "%u", ntohs(port));
+#endif
+    }
+    else
+    {
+#if defined(BOOST_HAS_THREADS) && defined(BOOST_HAS_PTHREADS) \
+      && !defined(ASIO_DISABLE_THREADS)
+      static ::pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+      ::pthread_mutex_lock(&mutex);
+#endif // defined(BOOST_HAS_THREADS) && defined(BOOST_HAS_PTHREADS)
+       //   && !defined(ASIO_DISABLE_THREADS)
+      servent* sptr = ::getservbyport(port, (flags & NI_DGRAM) ? "udp" : 0);
+      if (sptr && sptr->s_name && sptr->s_name[0] != '\0')
+      {
+        gai_strcpy(serv, sptr->s_name, servlen);
+      }
+      else
+      {
+        if (servlen < 6)
+        {
+          return ec = asio::error::no_buffer_space;
+        }
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) && !defined(UNDER_CE)
+        sprintf_s(serv, servlen, "%u", ntohs(port));
+#else
+        sprintf(serv, "%u", ntohs(port));
+#endif
+      }
+#if defined(BOOST_HAS_THREADS) && defined(BOOST_HAS_PTHREADS) \
+      && !defined(ASIO_DISABLE_THREADS)
+      ::pthread_mutex_unlock(&mutex);
+#endif // defined(BOOST_HAS_THREADS) && defined(BOOST_HAS_PTHREADS)
+       //   && !defined(ASIO_DISABLE_THREADS)
+    }
+  }
+
+  ec = asio::error_code();
+  return ec;
+}
+
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+       //   || defined(__MACH__) && defined(__APPLE__)
+
+inline asio::error_code translate_addrinfo_error(int error)
+{
+  switch (error)
+  {
+  case 0:
+    return asio::error_code();
+  case EAI_AGAIN:
+    return asio::error::host_not_found_try_again;
+  case EAI_BADFLAGS:
+    return asio::error::invalid_argument;
+  case EAI_FAIL:
+    return asio::error::no_recovery;
+  case EAI_FAMILY:
+    return asio::error::address_family_not_supported;
+  case EAI_MEMORY:
+    return asio::error::no_memory;
+  case EAI_NONAME:
+#if defined(EAI_ADDRFAMILY)
+  case EAI_ADDRFAMILY:
+#endif
+#if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME)
+  case EAI_NODATA:
+#endif
+    return asio::error::host_not_found;
+  case EAI_SERVICE:
+    return asio::error::service_not_found;
+  case EAI_SOCKTYPE:
+    return asio::error::socket_type_not_supported;
+  default: // Possibly the non-portable EAI_SYSTEM.
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+    return asio::error_code(
+        WSAGetLastError(), asio::error::get_system_category());
+#else
+    return asio::error_code(
+        errno, asio::error::get_system_category());
+#endif
+  }
+}
+
+ASIO_DECL
+asio::error_code getaddrinfo(const char* host,
+    const char* service, const addrinfo_type& hints,
+    addrinfo_type** result, asio::error_code& ec)
+{
+  host = (host && *host) ? host : 0;
+  service = (service && *service) ? service : 0;
+  clear_last_error();
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+# if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) || defined(UNDER_CE)
+  // Building for Windows XP, Windows Server 2003, or later.
+  int error = ::getaddrinfo(host, service, &hints, result);
+  return ec = translate_addrinfo_error(error);
+# else
+  // Building for Windows 2000 or earlier.
+  typedef int (WSAAPI *gai_t)(const char*,
+      const char*, const addrinfo_type*, addrinfo_type**);
+  if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32"))
+  {
+    if (gai_t gai = (gai_t)::GetProcAddress(winsock_module, "getaddrinfo"))
+    {
+      int error = gai(host, service, &hints, result);
+      return ec = translate_addrinfo_error(error);
+    }
+  }
+  int error = getaddrinfo_emulation(host, service, &hints, result);
+  return ec = translate_addrinfo_error(error);
+# endif
+#elif defined(__MACH__) && defined(__APPLE__)
+  int error = getaddrinfo_emulation(host, service, &hints, result);
+  return ec = translate_addrinfo_error(error);
+#else
+  int error = ::getaddrinfo(host, service, &hints, result);
+  return ec = translate_addrinfo_error(error);
+#endif
+}
+
+ASIO_DECL
+asio::error_code background_getaddrinfo(
+    const weak_cancel_token_type& cancel_token, const char* host,
+    const char* service, const addrinfo_type& hints,
+    addrinfo_type** result, asio::error_code& ec)
+{
+  if (cancel_token.expired())
+    ec = asio::error::operation_aborted;
+  else
+    socket_ops::getaddrinfo(host, service, hints, result, ec);
+  return ec;
+}
+
+ASIO_DECL
+void freeaddrinfo(addrinfo_type* ai)
+{
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+# if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) || defined(UNDER_CE)
+  // Building for Windows XP, Windows Server 2003, or later.
+  ::freeaddrinfo(ai);
+# else
+  // Building for Windows 2000 or earlier.
+  typedef int (WSAAPI *fai_t)(addrinfo_type*);
+  if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32"))
+  {
+    if (fai_t fai = (fai_t)::GetProcAddress(winsock_module, "freeaddrinfo"))
+    {
+      fai(ai);
+      return;
+    }
+  }
+  freeaddrinfo_emulation(ai);
+# endif
+#elif defined(__MACH__) && defined(__APPLE__)
+  freeaddrinfo_emulation(ai);
+#else
+  ::freeaddrinfo(ai);
+#endif
+}
+
+ASIO_DECL
+asio::error_code getnameinfo(const socket_addr_type* addr,
+    std::size_t addrlen, char* host, std::size_t hostlen,
+    char* serv, std::size_t servlen, int flags, asio::error_code& ec)
+{
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+# if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) || defined(UNDER_CE)
+  // Building for Windows XP, Windows Server 2003, or later.
+  clear_last_error();
+  int error = ::getnameinfo(addr, static_cast<socklen_t>(addrlen),
+      host, static_cast<DWORD>(hostlen),
+      serv, static_cast<DWORD>(servlen), flags);
+  return ec = translate_addrinfo_error(error);
+# else
+  // Building for Windows 2000 or earlier.
+  typedef int (WSAAPI *gni_t)(const socket_addr_type*,
+      int, char*, DWORD, char*, DWORD, int);
+  if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32"))
+  {
+    if (gni_t gni = (gni_t)::GetProcAddress(winsock_module, "getnameinfo"))
+    {
+      clear_last_error();
+      int error = gni(addr, static_cast<int>(addrlen),
+          host, static_cast<DWORD>(hostlen),
+          serv, static_cast<DWORD>(servlen), flags);
+      return ec = translate_addrinfo_error(error);
+    }
+  }
+  clear_last_error();
+  return getnameinfo_emulation(addr, addrlen,
+      host, hostlen, serv, servlen, flags, ec);
+# endif
+#elif defined(__MACH__) && defined(__APPLE__)
+  using namespace std; // For memcpy.
+  sockaddr_storage_type tmp_addr;
+  memcpy(&tmp_addr, addr, addrlen);
+  tmp_addr.ss_len = addrlen;
+  addr = reinterpret_cast<socket_addr_type*>(&tmp_addr);
+  clear_last_error();
+  return getnameinfo_emulation(addr, addrlen,
+      host, hostlen, serv, servlen, flags, ec);
+#else
+  clear_last_error();
+  int error = ::getnameinfo(addr, addrlen, host, hostlen, serv, servlen, flags);
+  return ec = translate_addrinfo_error(error);
+#endif
+}
+
+ASIO_DECL
+asio::error_code sync_getnameinfo(
+    const socket_addr_type* addr, std::size_t addrlen,
+    char* host, std::size_t hostlen, char* serv,
+    std::size_t servlen, int sock_type, asio::error_code& ec)
+{
+  // First try resolving with the service name. If that fails try resolving
+  // but allow the service to be returned as a number.
+  int flags = (sock_type == SOCK_DGRAM) ? NI_DGRAM : 0;
+  socket_ops::getnameinfo(addr, addrlen, host,
+      hostlen, serv, servlen, flags, ec);
+  if (ec)
+  {
+    socket_ops::getnameinfo(addr, addrlen, host, hostlen,
+        serv, servlen, flags | NI_NUMERICSERV, ec);
+  }
+
+  return ec;
+}
+
+ASIO_DECL
+asio::error_code background_getnameinfo(
+    const weak_cancel_token_type& cancel_token,
+    const socket_addr_type* addr, std::size_t addrlen,
+    char* host, std::size_t hostlen, char* serv,
+    std::size_t servlen, int sock_type, asio::error_code& ec)
+{
+  if (cancel_token.expired())
+  {
+    ec = asio::error::operation_aborted;
+  }
+  else
+  {
+    // First try resolving with the service name. If that fails try resolving
+    // but allow the service to be returned as a number.
+    int flags = (sock_type == SOCK_DGRAM) ? NI_DGRAM : 0;
+    socket_ops::getnameinfo(addr, addrlen, host,
+        hostlen, serv, servlen, flags, ec);
+    if (ec)
+    {
+      socket_ops::getnameinfo(addr, addrlen, host, hostlen,
+          serv, servlen, flags | NI_NUMERICSERV, ec);
+    }
+  }
+
+  return ec;
+}
+
+ASIO_DECL
+u_long_type network_to_host_long(u_long_type value)
+{
+  return ntohl(value);
+}
+
+ASIO_DECL
+u_long_type host_to_network_long(u_long_type value)
+{
+  return htonl(value);
+}
+
+ASIO_DECL
+u_short_type network_to_host_short(u_short_type value)
+{
+  return ntohs(value);
+}
+
+ASIO_DECL
+u_short_type host_to_network_short(u_short_type value)
+{
+  return htons(value);
+}
+
+} // namespace socket_ops
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_SOCKET_OPS_IPP
diff --git a/ext/asio/asio/detail/impl/socket_select_interrupter.ipp b/ext/asio/asio/detail/impl/socket_select_interrupter.ipp
new file mode 100644
index 0000000..181c543
--- /dev/null
+++ b/ext/asio/asio/detail/impl/socket_select_interrupter.ipp
@@ -0,0 +1,151 @@
+//
+// detail/impl/socket_select_interrupter.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_IMPL_SOCKET_SELECT_INTERRUPTER_IPP
+#define ASIO_DETAIL_IMPL_SOCKET_SELECT_INTERRUPTER_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(BOOST_WINDOWS) \
+  || defined(__CYGWIN__) \
+  || defined(__SYMBIAN32__)
+
+#include <cstdlib>
+#include "asio/detail/socket_holder.hpp"
+#include "asio/detail/socket_ops.hpp"
+#include "asio/detail/socket_select_interrupter.hpp"
+#include "asio/detail/throw_error.hpp"
+#include "asio/error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+socket_select_interrupter::socket_select_interrupter()
+{
+  asio::error_code ec;
+  socket_holder acceptor(socket_ops::socket(
+        AF_INET, SOCK_STREAM, IPPROTO_TCP, ec));
+  if (acceptor.get() == invalid_socket)
+    asio::detail::throw_error(ec, "socket_select_interrupter");
+
+  int opt = 1;
+  socket_ops::state_type acceptor_state = 0;
+  socket_ops::setsockopt(acceptor.get(), acceptor_state,
+      SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt), ec);
+
+  using namespace std; // For memset.
+  sockaddr_in4_type addr;
+  std::size_t addr_len = sizeof(addr);
+  memset(&addr, 0, sizeof(addr));
+  addr.sin_family = AF_INET;
+  addr.sin_addr.s_addr = inet_addr("127.0.0.1");
+  addr.sin_port = 0;
+  if (socket_ops::bind(acceptor.get(), (const socket_addr_type*)&addr,
+        addr_len, ec) == socket_error_retval)
+    asio::detail::throw_error(ec, "socket_select_interrupter");
+
+  if (socket_ops::getsockname(acceptor.get(), (socket_addr_type*)&addr,
+        &addr_len, ec) == socket_error_retval)
+    asio::detail::throw_error(ec, "socket_select_interrupter");
+
+  // Some broken firewalls on Windows will intermittently cause getsockname to
+  // return 0.0.0.0 when the socket is actually bound to 127.0.0.1. We
+  // explicitly specify the target address here to work around this problem.
+  addr.sin_addr.s_addr = inet_addr("127.0.0.1");
+
+  if (socket_ops::listen(acceptor.get(),
+        SOMAXCONN, ec) == socket_error_retval)
+    asio::detail::throw_error(ec, "socket_select_interrupter");
+
+  socket_holder client(socket_ops::socket(
+        AF_INET, SOCK_STREAM, IPPROTO_TCP, ec));
+  if (client.get() == invalid_socket)
+    asio::detail::throw_error(ec, "socket_select_interrupter");
+
+  if (socket_ops::connect(client.get(), (const socket_addr_type*)&addr,
+        addr_len, ec) == socket_error_retval)
+    asio::detail::throw_error(ec, "socket_select_interrupter");
+
+  socket_holder server(socket_ops::accept(acceptor.get(), 0, 0, ec));
+  if (server.get() == invalid_socket)
+    asio::detail::throw_error(ec, "socket_select_interrupter");
+  
+  ioctl_arg_type non_blocking = 1;
+  socket_ops::state_type client_state = 0;
+  if (socket_ops::ioctl(client.get(), client_state,
+        FIONBIO, &non_blocking, ec))
+    asio::detail::throw_error(ec, "socket_select_interrupter");
+
+  opt = 1;
+  socket_ops::setsockopt(client.get(), client_state,
+      IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt), ec);
+
+  non_blocking = 1;
+  socket_ops::state_type server_state = 0;
+  if (socket_ops::ioctl(server.get(), server_state,
+        FIONBIO, &non_blocking, ec))
+    asio::detail::throw_error(ec, "socket_select_interrupter");
+
+  opt = 1;
+  socket_ops::setsockopt(server.get(), server_state,
+      IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt), ec);
+
+  read_descriptor_ = server.release();
+  write_descriptor_ = client.release();
+}
+
+socket_select_interrupter::~socket_select_interrupter()
+{
+  asio::error_code ec;
+  socket_ops::state_type state = socket_ops::internal_non_blocking;
+  if (read_descriptor_ != invalid_socket)
+    socket_ops::close(read_descriptor_, state, true, ec);
+  if (write_descriptor_ != invalid_socket)
+    socket_ops::close(write_descriptor_, state, true, ec);
+}
+
+void socket_select_interrupter::interrupt()
+{
+  char byte = 0;
+  socket_ops::buf b;
+  socket_ops::init_buf(b, &byte, 1);
+  asio::error_code ec;
+  socket_ops::send(write_descriptor_, &b, 1, 0, ec);
+}
+
+bool socket_select_interrupter::reset()
+{
+  char data[1024];
+  socket_ops::buf b;
+  socket_ops::init_buf(b, data, sizeof(data));
+  asio::error_code ec;
+  int bytes_read = socket_ops::recv(read_descriptor_, &b, 1, 0, ec);
+  bool was_interrupted = (bytes_read > 0);
+  while (bytes_read == sizeof(data))
+    bytes_read = socket_ops::recv(read_descriptor_, &b, 1, 0, ec);
+  return was_interrupted;
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(BOOST_WINDOWS)
+       // || defined(__CYGWIN__)
+       // || defined(__SYMBIAN32__)
+
+#endif // ASIO_DETAIL_IMPL_SOCKET_SELECT_INTERRUPTER_IPP
diff --git a/ext/asio/asio/detail/impl/strand_service.hpp b/ext/asio/asio/detail/impl/strand_service.hpp
new file mode 100644
index 0000000..81f438a
--- /dev/null
+++ b/ext/asio/asio/detail/impl/strand_service.hpp
@@ -0,0 +1,140 @@
+//
+// detail/impl/strand_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_IMPL_STRAND_SERVICE_HPP
+#define ASIO_DETAIL_IMPL_STRAND_SERVICE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/call_stack.hpp"
+#include "asio/detail/completion_handler.hpp"
+#include "asio/detail/fenced_block.hpp"
+#include "asio/detail/handler_alloc_helpers.hpp"
+#include "asio/detail/handler_invoke_helpers.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+inline strand_service::strand_impl::strand_impl()
+  : operation(&strand_service::do_complete),
+    count_(0)
+{
+}
+
+struct strand_service::on_dispatch_exit
+{
+  io_service_impl* io_service_;
+  strand_impl* impl_;
+
+  ~on_dispatch_exit()
+  {
+    impl_->mutex_.lock();
+    bool more_handlers = (--impl_->count_ > 0);
+    impl_->mutex_.unlock();
+
+    if (more_handlers)
+      io_service_->post_immediate_completion(impl_);
+  }
+};
+
+inline void strand_service::destroy(strand_service::implementation_type& impl)
+{
+  impl = 0;
+}
+
+template <typename Handler>
+void strand_service::dispatch(strand_service::implementation_type& impl,
+    Handler handler)
+{
+  // If we are already in the strand then the handler can run immediately.
+  if (call_stack<strand_impl>::contains(impl))
+  {
+    asio::detail::fenced_block b;
+    asio_handler_invoke_helpers::invoke(handler, handler);
+    return;
+  }
+
+  // Allocate and construct an operation to wrap the handler.
+  typedef completion_handler<Handler> op;
+  typename op::ptr p = { boost::addressof(handler),
+    asio_handler_alloc_helpers::allocate(
+      sizeof(op), handler), 0 };
+  p.p = new (p.v) op(handler);
+
+  // If we are running inside the io_service, and no other handler is queued
+  // or running, then the handler can run immediately.
+  bool can_dispatch = call_stack<io_service_impl>::contains(&io_service_);
+  impl->mutex_.lock();
+  bool first = (++impl->count_ == 1);
+  if (can_dispatch && first)
+  {
+    // Immediate invocation is allowed.
+    impl->mutex_.unlock();
+
+    // Memory must be releaesed before any upcall is made.
+    p.reset();
+
+    // Indicate that this strand is executing on the current thread.
+    call_stack<strand_impl>::context ctx(impl);
+
+    // Ensure the next handler, if any, is scheduled on block exit.
+    on_dispatch_exit on_exit = { &io_service_, impl };
+    (void)on_exit;
+
+    asio::detail::fenced_block b;
+    asio_handler_invoke_helpers::invoke(handler, handler);
+    return;
+  }
+
+  // Immediate invocation is not allowed, so enqueue for later.
+  impl->queue_.push(p.p);
+  impl->mutex_.unlock();
+  p.v = p.p = 0;
+
+  // The first handler to be enqueued is responsible for scheduling the
+  // strand.
+  if (first)
+    io_service_.post_immediate_completion(impl);
+}
+
+// Request the io_service to invoke the given handler and return immediately.
+template <typename Handler>
+void strand_service::post(strand_service::implementation_type& impl,
+    Handler handler)
+{
+  // Allocate and construct an operation to wrap the handler.
+  typedef completion_handler<Handler> op;
+  typename op::ptr p = { boost::addressof(handler),
+    asio_handler_alloc_helpers::allocate(
+      sizeof(op), handler), 0 };
+  p.p = new (p.v) op(handler);
+
+  // Add the handler to the queue.
+  impl->mutex_.lock();
+  bool first = (++impl->count_ == 1);
+  impl->queue_.push(p.p);
+  impl->mutex_.unlock();
+  p.v = p.p = 0;
+
+  // The first handler to be enqueue is responsible for scheduling the strand.
+  if (first)
+    io_service_.post_immediate_completion(impl);
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_IMPL_STRAND_SERVICE_HPP
diff --git a/ext/asio/asio/detail/impl/strand_service.ipp b/ext/asio/asio/detail/impl/strand_service.ipp
new file mode 100644
index 0000000..84b806a
--- /dev/null
+++ b/ext/asio/asio/detail/impl/strand_service.ipp
@@ -0,0 +1,106 @@
+//
+// detail/impl/strand_service.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_IMPL_STRAND_SERVICE_IPP
+#define ASIO_DETAIL_IMPL_STRAND_SERVICE_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+#include "asio/detail/call_stack.hpp"
+#include "asio/detail/strand_service.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+struct strand_service::on_do_complete_exit
+{
+  io_service_impl* owner_;
+  strand_impl* impl_;
+
+  ~on_do_complete_exit()
+  {
+    impl_->mutex_.lock();
+    bool more_handlers = (--impl_->count_ > 0);
+    impl_->mutex_.unlock();
+
+    if (more_handlers)
+      owner_->post_immediate_completion(impl_);
+  }
+};
+
+strand_service::strand_service(asio::io_service& io_service)
+  : asio::detail::service_base<strand_service>(io_service),
+    io_service_(asio::use_service<io_service_impl>(io_service)),
+    mutex_(),
+    salt_(0)
+{
+}
+
+void strand_service::shutdown_service()
+{
+  op_queue<operation> ops;
+
+  asio::detail::mutex::scoped_lock lock(mutex_);
+
+  for (std::size_t i = 0; i < num_implementations; ++i)
+    if (strand_impl* impl = implementations_[i].get())
+      ops.push(impl->queue_);
+}
+
+void strand_service::construct(strand_service::implementation_type& impl)
+{
+  std::size_t salt = salt_++;
+  std::size_t index = reinterpret_cast<std::size_t>(&impl);
+  index += (reinterpret_cast<std::size_t>(&impl) >> 3);
+  index ^= salt + 0x9e3779b9 + (index << 6) + (index >> 2);
+  index = index % num_implementations;
+
+  asio::detail::mutex::scoped_lock lock(mutex_);
+
+  if (!implementations_[index])
+    implementations_[index].reset(new strand_impl);
+  impl = implementations_[index].get();
+}
+
+void strand_service::do_complete(io_service_impl* owner, operation* base,
+    asio::error_code /*ec*/, std::size_t /*bytes_transferred*/)
+{
+  if (owner)
+  {
+    strand_impl* impl = static_cast<strand_impl*>(base);
+
+    // Get the next handler to be executed.
+    impl->mutex_.lock();
+    operation* o = impl->queue_.front();
+    impl->queue_.pop();
+    impl->mutex_.unlock();
+
+    // Indicate that this strand is executing on the current thread.
+    call_stack<strand_impl>::context ctx(impl);
+
+    // Ensure the next handler, if any, is scheduled on block exit.
+    on_do_complete_exit on_exit = { owner, impl };
+    (void)on_exit;
+
+    o->complete(*owner);
+  }
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_IMPL_STRAND_SERVICE_IPP
diff --git a/ext/asio/asio/detail/impl/task_io_service.hpp b/ext/asio/asio/detail/impl/task_io_service.hpp
new file mode 100644
index 0000000..20ffd61
--- /dev/null
+++ b/ext/asio/asio/detail/impl/task_io_service.hpp
@@ -0,0 +1,60 @@
+//
+// detail/impl/task_io_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_IMPL_TASK_IO_SERVICE_HPP
+#define ASIO_DETAIL_IMPL_TASK_IO_SERVICE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/call_stack.hpp"
+#include "asio/detail/completion_handler.hpp"
+#include "asio/detail/fenced_block.hpp"
+#include "asio/detail/handler_alloc_helpers.hpp"
+#include "asio/detail/handler_invoke_helpers.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename Handler>
+void task_io_service::dispatch(Handler handler)
+{
+  if (call_stack<task_io_service>::contains(this))
+  {
+    asio::detail::fenced_block b;
+    asio_handler_invoke_helpers::invoke(handler, handler);
+  }
+  else
+    post(handler);
+}
+
+template <typename Handler>
+void task_io_service::post(Handler handler)
+{
+  // Allocate and construct an operation to wrap the handler.
+  typedef completion_handler<Handler> op;
+  typename op::ptr p = { boost::addressof(handler),
+    asio_handler_alloc_helpers::allocate(
+      sizeof(op), handler), 0 };
+  p.p = new (p.v) op(handler);
+
+  post_immediate_completion(p.p);
+  p.v = p.p = 0;
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_IMPL_TASK_IO_SERVICE_HPP
diff --git a/ext/asio/asio/detail/impl/task_io_service.ipp b/ext/asio/asio/detail/impl/task_io_service.ipp
new file mode 100644
index 0000000..12a22be
--- /dev/null
+++ b/ext/asio/asio/detail/impl/task_io_service.ipp
@@ -0,0 +1,354 @@
+//
+// detail/impl/task_io_service.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_IMPL_TASK_IO_SERVICE_IPP
+#define ASIO_DETAIL_IMPL_TASK_IO_SERVICE_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if !defined(ASIO_HAS_IOCP)
+
+#include <boost/limits.hpp>
+#include "asio/detail/call_stack.hpp"
+#include "asio/detail/event.hpp"
+#include "asio/detail/reactor.hpp"
+#include "asio/detail/task_io_service.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+struct task_io_service::task_cleanup
+{
+  ~task_cleanup()
+  {
+    // Enqueue the completed operations and reinsert the task at the end of
+    // the operation queue.
+    lock_->lock();
+    task_io_service_->task_interrupted_ = true;
+    task_io_service_->op_queue_.push(*ops_);
+    task_io_service_->op_queue_.push(&task_io_service_->task_operation_);
+  }
+
+  task_io_service* task_io_service_;
+  mutex::scoped_lock* lock_;
+  op_queue<operation>* ops_;
+};
+
+struct task_io_service::work_finished_on_block_exit
+{
+  ~work_finished_on_block_exit()
+  {
+    task_io_service_->work_finished();
+  }
+
+  task_io_service* task_io_service_;
+};
+
+struct task_io_service::idle_thread_info
+{
+  event wakeup_event;
+  idle_thread_info* next;
+};
+
+task_io_service::task_io_service(asio::io_service& io_service)
+  : asio::detail::service_base<task_io_service>(io_service),
+    mutex_(),
+    task_(0),
+    task_interrupted_(true),
+    outstanding_work_(0),
+    stopped_(false),
+    shutdown_(false),
+    first_idle_thread_(0)
+{
+}
+
+void task_io_service::init(std::size_t /*concurrency_hint*/)
+{
+}
+
+void task_io_service::shutdown_service()
+{
+  mutex::scoped_lock lock(mutex_);
+  shutdown_ = true;
+  lock.unlock();
+
+  // Destroy handler objects.
+  while (!op_queue_.empty())
+  {
+    operation* o = op_queue_.front();
+    op_queue_.pop();
+    if (o != &task_operation_)
+      o->destroy();
+  }
+
+  // Reset to initial state.
+  task_ = 0;
+}
+
+void task_io_service::init_task()
+{
+  mutex::scoped_lock lock(mutex_);
+  if (!shutdown_ && !task_)
+  {
+    task_ = &use_service<reactor>(this->get_io_service());
+    op_queue_.push(&task_operation_);
+    wake_one_thread_and_unlock(lock);
+  }
+}
+
+std::size_t task_io_service::run(asio::error_code& ec)
+{
+  ec = asio::error_code();
+  if (outstanding_work_ == 0)
+  {
+    stop();
+    return 0;
+  }
+
+  call_stack<task_io_service>::context ctx(this);
+
+  idle_thread_info this_idle_thread;
+  this_idle_thread.next = 0;
+
+  mutex::scoped_lock lock(mutex_);
+
+  std::size_t n = 0;
+  for (; do_one(lock, &this_idle_thread); lock.lock())
+    if (n != (std::numeric_limits<std::size_t>::max)())
+      ++n;
+  return n;
+}
+
+std::size_t task_io_service::run_one(asio::error_code& ec)
+{
+  ec = asio::error_code();
+  if (outstanding_work_ == 0)
+  {
+    stop();
+    return 0;
+  }
+
+  call_stack<task_io_service>::context ctx(this);
+
+  idle_thread_info this_idle_thread;
+  this_idle_thread.next = 0;
+
+  mutex::scoped_lock lock(mutex_);
+
+  return do_one(lock, &this_idle_thread);
+}
+
+std::size_t task_io_service::poll(asio::error_code& ec)
+{
+  if (outstanding_work_ == 0)
+  {
+    stop();
+    ec = asio::error_code();
+    return 0;
+  }
+
+  call_stack<task_io_service>::context ctx(this);
+
+  mutex::scoped_lock lock(mutex_);
+
+  std::size_t n = 0;
+  for (; do_one(lock, 0); lock.lock())
+    if (n != (std::numeric_limits<std::size_t>::max)())
+      ++n;
+  return n;
+}
+
+std::size_t task_io_service::poll_one(asio::error_code& ec)
+{
+  ec = asio::error_code();
+  if (outstanding_work_ == 0)
+  {
+    stop();
+    return 0;
+  }
+
+  call_stack<task_io_service>::context ctx(this);
+
+  mutex::scoped_lock lock(mutex_);
+
+  return do_one(lock, 0);
+}
+
+void task_io_service::stop()
+{
+  mutex::scoped_lock lock(mutex_);
+  stop_all_threads(lock);
+}
+
+void task_io_service::reset()
+{
+  mutex::scoped_lock lock(mutex_);
+  stopped_ = false;
+}
+
+void task_io_service::post_immediate_completion(task_io_service::operation* op)
+{
+  work_started();
+  post_deferred_completion(op);
+}
+
+void task_io_service::post_deferred_completion(task_io_service::operation* op)
+{
+  mutex::scoped_lock lock(mutex_);
+  op_queue_.push(op);
+  wake_one_thread_and_unlock(lock);
+}
+
+void task_io_service::post_deferred_completions(
+    op_queue<task_io_service::operation>& ops)
+{
+  if (!ops.empty())
+  {
+    mutex::scoped_lock lock(mutex_);
+    op_queue_.push(ops);
+    wake_one_thread_and_unlock(lock);
+  }
+}
+
+std::size_t task_io_service::do_one(mutex::scoped_lock& lock,
+    task_io_service::idle_thread_info* this_idle_thread)
+{
+  bool polling = !this_idle_thread;
+  bool task_has_run = false;
+  while (!stopped_)
+  {
+    if (!op_queue_.empty())
+    {
+      // Prepare to execute first handler from queue.
+      operation* o = op_queue_.front();
+      op_queue_.pop();
+      bool more_handlers = (!op_queue_.empty());
+
+      if (o == &task_operation_)
+      {
+        task_interrupted_ = more_handlers || polling;
+
+        // If the task has already run and we're polling then we're done.
+        if (task_has_run && polling)
+        {
+          task_interrupted_ = true;
+          op_queue_.push(&task_operation_);
+          return 0;
+        }
+        task_has_run = true;
+
+        if (!more_handlers || !wake_one_idle_thread_and_unlock(lock))
+          lock.unlock();
+
+        op_queue<operation> completed_ops;
+        task_cleanup c = { this, &lock, &completed_ops };
+        (void)c;
+
+        // Run the task. May throw an exception. Only block if the operation
+        // queue is empty and we're not polling, otherwise we want to return
+        // as soon as possible.
+        task_->run(!more_handlers && !polling, completed_ops);
+      }
+      else
+      {
+        if (more_handlers)
+          wake_one_thread_and_unlock(lock);
+        else
+          lock.unlock();
+
+        // Ensure the count of outstanding work is decremented on block exit.
+        work_finished_on_block_exit on_exit = { this };
+        (void)on_exit;
+
+        // Complete the operation. May throw an exception.
+        o->complete(*this); // deletes the operation object
+
+        return 1;
+      }
+    }
+    else if (this_idle_thread)
+    {
+      // Nothing to run right now, so just wait for work to do.
+      this_idle_thread->next = first_idle_thread_;
+      first_idle_thread_ = this_idle_thread;
+      this_idle_thread->wakeup_event.clear(lock);
+      this_idle_thread->wakeup_event.wait(lock);
+    }
+    else
+    {
+      return 0;
+    }
+  }
+
+  return 0;
+}
+
+void task_io_service::stop_all_threads(
+    mutex::scoped_lock& lock)
+{
+  stopped_ = true;
+
+  while (first_idle_thread_)
+  {
+    idle_thread_info* idle_thread = first_idle_thread_;
+    first_idle_thread_ = idle_thread->next;
+    idle_thread->next = 0;
+    idle_thread->wakeup_event.signal(lock);
+  }
+
+  if (!task_interrupted_ && task_)
+  {
+    task_interrupted_ = true;
+    task_->interrupt();
+  }
+}
+
+bool task_io_service::wake_one_idle_thread_and_unlock(
+    mutex::scoped_lock& lock)
+{
+  if (first_idle_thread_)
+  {
+    idle_thread_info* idle_thread = first_idle_thread_;
+    first_idle_thread_ = idle_thread->next;
+    idle_thread->next = 0;
+    idle_thread->wakeup_event.signal_and_unlock(lock);
+    return true;
+  }
+  return false;
+}
+
+void task_io_service::wake_one_thread_and_unlock(
+    mutex::scoped_lock& lock)
+{
+  if (!wake_one_idle_thread_and_unlock(lock))
+  {
+    if (!task_interrupted_ && task_)
+    {
+      task_interrupted_ = true;
+      task_->interrupt();
+    }
+    lock.unlock();
+  }
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // !defined(ASIO_HAS_IOCP)
+
+#endif // ASIO_DETAIL_IMPL_TASK_IO_SERVICE_IPP
diff --git a/ext/asio/asio/detail/impl/throw_error.ipp b/ext/asio/asio/detail/impl/throw_error.ipp
new file mode 100644
index 0000000..a04fbf4
--- /dev/null
+++ b/ext/asio/asio/detail/impl/throw_error.ipp
@@ -0,0 +1,47 @@
+//
+// detail/impl/throw_error.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_IMPL_THROW_ERROR_IPP
+#define ASIO_DETAIL_IMPL_THROW_ERROR_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+#include <boost/throw_exception.hpp>
+#include "asio/detail/throw_error.hpp"
+#include "asio/system_error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+ASIO_DECL
+void do_throw_error(const asio::error_code& err)
+{
+  asio::system_error e(err);
+  boost::throw_exception(e);
+}
+
+ASIO_DECL
+void do_throw_error(const asio::error_code& err, const char* location)
+{
+  asio::system_error e(err, location);
+  boost::throw_exception(e);
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_IMPL_THROW_ERROR_IPP
diff --git a/ext/asio/asio/detail/impl/timer_queue.ipp b/ext/asio/asio/detail/impl/timer_queue.ipp
new file mode 100644
index 0000000..63fbd7e
--- /dev/null
+++ b/ext/asio/asio/detail/impl/timer_queue.ipp
@@ -0,0 +1,85 @@
+//
+// detail/impl/timer_queue.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_IMPL_TIMER_QUEUE_IPP
+#define ASIO_DETAIL_IMPL_TIMER_QUEUE_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if !defined(ASIO_HEADER_ONLY)
+
+#include "asio/detail/timer_queue.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+timer_queue<time_traits<boost::posix_time::ptime> >::timer_queue()
+{
+}
+
+timer_queue<time_traits<boost::posix_time::ptime> >::~timer_queue()
+{
+}
+
+bool timer_queue<time_traits<boost::posix_time::ptime> >::enqueue_timer(
+    const time_type& time, per_timer_data& timer, timer_op* op)
+{
+  return impl_.enqueue_timer(time, timer, op);
+}
+
+bool timer_queue<time_traits<boost::posix_time::ptime> >::empty() const
+{
+  return impl_.empty();
+}
+
+long timer_queue<time_traits<boost::posix_time::ptime> >::wait_duration_msec(
+    long max_duration) const
+{
+  return impl_.wait_duration_msec(max_duration);
+}
+
+long timer_queue<time_traits<boost::posix_time::ptime> >::wait_duration_usec(
+    long max_duration) const
+{
+  return impl_.wait_duration_usec(max_duration);
+}
+
+void timer_queue<time_traits<boost::posix_time::ptime> >::get_ready_timers(
+    op_queue<operation>& ops)
+{
+  impl_.get_ready_timers(ops);
+}
+
+void timer_queue<time_traits<boost::posix_time::ptime> >::get_all_timers(
+    op_queue<operation>& ops)
+{
+  impl_.get_all_timers(ops);
+}
+
+std::size_t timer_queue<time_traits<boost::posix_time::ptime> >::cancel_timer(
+    per_timer_data& timer, op_queue<operation>& ops)
+{
+  return impl_.cancel_timer(timer, ops);
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // !defined(ASIO_HEADER_ONLY)
+
+#endif // ASIO_DETAIL_IMPL_TIMER_QUEUE_IPP
diff --git a/ext/asio/asio/detail/impl/timer_queue_set.ipp b/ext/asio/asio/detail/impl/timer_queue_set.ipp
new file mode 100644
index 0000000..81ab5a9
--- /dev/null
+++ b/ext/asio/asio/detail/impl/timer_queue_set.ipp
@@ -0,0 +1,101 @@
+//
+// detail/impl/timer_queue_set.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_IMPL_TIMER_QUEUE_SET_IPP
+#define ASIO_DETAIL_IMPL_TIMER_QUEUE_SET_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+#include "asio/detail/timer_queue_set.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+timer_queue_set::timer_queue_set()
+  : first_(0)
+{
+}
+
+void timer_queue_set::insert(timer_queue_base* q)
+{
+  q->next_ = first_;
+  first_ = q;
+}
+
+void timer_queue_set::erase(timer_queue_base* q)
+{
+  if (first_)
+  {
+    if (q == first_)
+    {
+      first_ = q->next_;
+      q->next_ = 0;
+      return;
+    }
+
+    for (timer_queue_base* p = first_; p->next_; p = p->next_)
+    {
+      if (p->next_ == q)
+      {
+        p->next_ = q->next_;
+        q->next_ = 0;
+        return;
+      }
+    }
+  }
+}
+
+bool timer_queue_set::all_empty() const
+{
+  for (timer_queue_base* p = first_; p; p = p->next_)
+    if (!p->empty())
+      return false;
+  return true;
+}
+
+long timer_queue_set::wait_duration_msec(long max_duration) const
+{
+  long min_duration = max_duration;
+  for (timer_queue_base* p = first_; p; p = p->next_)
+    min_duration = p->wait_duration_msec(min_duration);
+  return min_duration;
+}
+
+long timer_queue_set::wait_duration_usec(long max_duration) const
+{
+  long min_duration = max_duration;
+  for (timer_queue_base* p = first_; p; p = p->next_)
+    min_duration = p->wait_duration_usec(min_duration);
+  return min_duration;
+}
+
+void timer_queue_set::get_ready_timers(op_queue<operation>& ops)
+{
+  for (timer_queue_base* p = first_; p; p = p->next_)
+    p->get_ready_timers(ops);
+}
+
+void timer_queue_set::get_all_timers(op_queue<operation>& ops)
+{
+  for (timer_queue_base* p = first_; p; p = p->next_)
+    p->get_all_timers(ops);
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_IMPL_TIMER_QUEUE_SET_IPP
diff --git a/ext/asio/asio/detail/impl/win_event.ipp b/ext/asio/asio/detail/impl/win_event.ipp
new file mode 100644
index 0000000..2b72f6e
--- /dev/null
+++ b/ext/asio/asio/detail/impl/win_event.ipp
@@ -0,0 +1,50 @@
+//
+// detail/win_event.ipp
+// ~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_IMPL_WIN_EVENT_IPP
+#define ASIO_DETAIL_IMPL_WIN_EVENT_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(BOOST_WINDOWS)
+
+#include "asio/detail/throw_error.hpp"
+#include "asio/detail/win_event.hpp"
+#include "asio/error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+win_event::win_event()
+  : event_(::CreateEvent(0, true, false, 0))
+{
+  if (!event_)
+  {
+    DWORD last_error = ::GetLastError();
+    asio::error_code ec(last_error,
+        asio::error::get_system_category());
+    asio::detail::throw_error(ec, "event");
+  }
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(BOOST_WINDOWS)
+
+#endif // ASIO_DETAIL_IMPL_WIN_EVENT_IPP
diff --git a/ext/asio/asio/detail/impl/win_iocp_handle_service.ipp b/ext/asio/asio/detail/impl/win_iocp_handle_service.ipp
new file mode 100644
index 0000000..3b30b1d
--- /dev/null
+++ b/ext/asio/asio/detail/impl/win_iocp_handle_service.ipp
@@ -0,0 +1,452 @@
+//
+// detail/impl/win_iocp_handle_service.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2008 Rep Invariant Systems, Inc. (info at repinvariant.com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_IMPL_WIN_IOCP_HANDLE_SERVICE_IPP
+#define ASIO_DETAIL_IMPL_WIN_IOCP_HANDLE_SERVICE_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(ASIO_HAS_IOCP)
+
+#include "asio/detail/win_iocp_handle_service.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+class win_iocp_handle_service::overlapped_wrapper
+  : public OVERLAPPED
+{
+public:
+  explicit overlapped_wrapper(asio::error_code& ec)
+  {
+    Internal = 0;
+    InternalHigh = 0;
+    Offset = 0;
+    OffsetHigh = 0;
+
+    // Create a non-signalled manual-reset event, for GetOverlappedResult.
+    hEvent = ::CreateEvent(0, TRUE, FALSE, 0);
+    if (hEvent)
+    {
+      // As documented in GetQueuedCompletionStatus, setting the low order
+      // bit of this event prevents our synchronous writes from being treated
+      // as completion port events.
+      *reinterpret_cast<DWORD_PTR*>(&hEvent) |= 1;
+    }
+    else
+    {
+      DWORD last_error = ::GetLastError();
+      ec = asio::error_code(last_error,
+          asio::error::get_system_category());
+    }
+  }
+
+  ~overlapped_wrapper()
+  {
+    if (hEvent)
+    {
+      ::CloseHandle(hEvent);
+    }
+  }
+};
+
+win_iocp_handle_service::win_iocp_handle_service(
+    asio::io_service& io_service)
+  : iocp_service_(asio::use_service<win_iocp_io_service>(io_service)),
+    mutex_(),
+    impl_list_(0)
+{
+}
+
+void win_iocp_handle_service::shutdown_service()
+{
+  // Close all implementations, causing all operations to complete.
+  asio::detail::mutex::scoped_lock lock(mutex_);
+  implementation_type* impl = impl_list_;
+  while (impl)
+  {
+    close_for_destruction(*impl);
+    impl = impl->next_;
+  }
+}
+
+void win_iocp_handle_service::construct(
+    win_iocp_handle_service::implementation_type& impl)
+{
+  impl.handle_ = INVALID_HANDLE_VALUE;
+  impl.safe_cancellation_thread_id_ = 0;
+
+  // Insert implementation into linked list of all implementations.
+  asio::detail::mutex::scoped_lock lock(mutex_);
+  impl.next_ = impl_list_;
+  impl.prev_ = 0;
+  if (impl_list_)
+    impl_list_->prev_ = &impl;
+  impl_list_ = &impl;
+}
+
+void win_iocp_handle_service::destroy(
+    win_iocp_handle_service::implementation_type& impl)
+{
+  close_for_destruction(impl);
+  
+  // Remove implementation from linked list of all implementations.
+  asio::detail::mutex::scoped_lock lock(mutex_);
+  if (impl_list_ == &impl)
+    impl_list_ = impl.next_;
+  if (impl.prev_)
+    impl.prev_->next_ = impl.next_;
+  if (impl.next_)
+    impl.next_->prev_= impl.prev_;
+  impl.next_ = 0;
+  impl.prev_ = 0;
+}
+
+asio::error_code win_iocp_handle_service::assign(
+    win_iocp_handle_service::implementation_type& impl,
+    const native_type& native_handle, asio::error_code& ec)
+{
+  if (is_open(impl))
+  {
+    ec = asio::error::already_open;
+    return ec;
+  }
+
+  if (iocp_service_.register_handle(native_handle, ec))
+    return ec;
+
+  impl.handle_ = native_handle;
+  ec = asio::error_code();
+  return ec;
+}
+
+asio::error_code win_iocp_handle_service::close(
+    win_iocp_handle_service::implementation_type& impl,
+    asio::error_code& ec)
+{
+  if (is_open(impl))
+  {
+    if (!::CloseHandle(impl.handle_))
+    {
+      DWORD last_error = ::GetLastError();
+      ec = asio::error_code(last_error,
+          asio::error::get_system_category());
+      return ec;
+    }
+
+    impl.handle_ = INVALID_HANDLE_VALUE;
+    impl.safe_cancellation_thread_id_ = 0;
+  }
+
+  ec = asio::error_code();
+  return ec;
+}
+
+asio::error_code win_iocp_handle_service::cancel(
+    win_iocp_handle_service::implementation_type& impl,
+    asio::error_code& ec)
+{
+  if (!is_open(impl))
+  {
+    ec = asio::error::bad_descriptor;
+  }
+  else if (FARPROC cancel_io_ex_ptr = ::GetProcAddress(
+        ::GetModuleHandleA("KERNEL32"), "CancelIoEx"))
+  {
+    // The version of Windows supports cancellation from any thread.
+    typedef BOOL (WINAPI* cancel_io_ex_t)(HANDLE, LPOVERLAPPED);
+    cancel_io_ex_t cancel_io_ex = (cancel_io_ex_t)cancel_io_ex_ptr;
+    if (!cancel_io_ex(impl.handle_, 0))
+    {
+      DWORD last_error = ::GetLastError();
+      if (last_error == ERROR_NOT_FOUND)
+      {
+        // ERROR_NOT_FOUND means that there were no operations to be
+        // cancelled. We swallow this error to match the behaviour on other
+        // platforms.
+        ec = asio::error_code();
+      }
+      else
+      {
+        ec = asio::error_code(last_error,
+            asio::error::get_system_category());
+      }
+    }
+    else
+    {
+      ec = asio::error_code();
+    }
+  }
+  else if (impl.safe_cancellation_thread_id_ == 0)
+  {
+    // No operations have been started, so there's nothing to cancel.
+    ec = asio::error_code();
+  }
+  else if (impl.safe_cancellation_thread_id_ == ::GetCurrentThreadId())
+  {
+    // Asynchronous operations have been started from the current thread only,
+    // so it is safe to try to cancel them using CancelIo.
+    if (!::CancelIo(impl.handle_))
+    {
+      DWORD last_error = ::GetLastError();
+      ec = asio::error_code(last_error,
+          asio::error::get_system_category());
+    }
+    else
+    {
+      ec = asio::error_code();
+    }
+  }
+  else
+  {
+    // Asynchronous operations have been started from more than one thread,
+    // so cancellation is not safe.
+    ec = asio::error::operation_not_supported;
+  }
+
+  return ec;
+}
+
+size_t win_iocp_handle_service::do_write(
+    win_iocp_handle_service::implementation_type& impl, boost::uint64_t offset,
+    const asio::const_buffer& buffer, asio::error_code& ec)
+{
+  if (!is_open(impl))
+  {
+    ec = asio::error::bad_descriptor;
+    return 0;
+  }
+
+  // A request to write 0 bytes on a handle is a no-op.
+  if (asio::buffer_size(buffer) == 0)
+  {
+    ec = asio::error_code();
+    return 0;
+  }
+
+  overlapped_wrapper overlapped(ec);
+  if (ec)
+  {
+    return 0;
+  }
+
+  // Write the data. 
+  overlapped.Offset = offset & 0xFFFFFFFF;
+  overlapped.OffsetHigh = (offset >> 32) & 0xFFFFFFFF;
+  BOOL ok = ::WriteFile(impl.handle_,
+      asio::buffer_cast<LPCVOID>(buffer),
+      static_cast<DWORD>(asio::buffer_size(buffer)), 0, &overlapped);
+  if (!ok) 
+  {
+    DWORD last_error = ::GetLastError();
+    if (last_error != ERROR_IO_PENDING)
+    {
+      ec = asio::error_code(last_error,
+          asio::error::get_system_category());
+      return 0;
+    }
+  }
+
+  // Wait for the operation to complete.
+  DWORD bytes_transferred = 0;
+  ok = ::GetOverlappedResult(impl.handle_,
+      &overlapped, &bytes_transferred, TRUE);
+  if (!ok)
+  {
+    DWORD last_error = ::GetLastError();
+    ec = asio::error_code(last_error,
+        asio::error::get_system_category());
+    return 0;
+  }
+
+  ec = asio::error_code();
+  return bytes_transferred;
+}
+
+void win_iocp_handle_service::start_write_op(
+    win_iocp_handle_service::implementation_type& impl, boost::uint64_t offset,
+    const asio::const_buffer& buffer, operation* op)
+{
+  update_cancellation_thread_id(impl);
+  iocp_service_.work_started();
+
+  if (!is_open(impl))
+  {
+    iocp_service_.on_completion(op, asio::error::bad_descriptor);
+  }
+  else if (asio::buffer_size(buffer) == 0)
+  {
+    // A request to write 0 bytes on a handle is a no-op.
+    iocp_service_.on_completion(op);
+  }
+  else
+  {
+    DWORD bytes_transferred = 0;
+    op->Offset = offset & 0xFFFFFFFF;
+    op->OffsetHigh = (offset >> 32) & 0xFFFFFFFF;
+    BOOL ok = ::WriteFile(impl.handle_,
+        asio::buffer_cast<LPCVOID>(buffer),
+        static_cast<DWORD>(asio::buffer_size(buffer)),
+        &bytes_transferred, op);
+    DWORD last_error = ::GetLastError();
+    if (!ok && last_error != ERROR_IO_PENDING
+        && last_error != ERROR_MORE_DATA)
+    {
+      iocp_service_.on_completion(op, last_error, bytes_transferred);
+    }
+    else
+    {
+      iocp_service_.on_pending(op);
+    }
+  }
+}
+
+size_t win_iocp_handle_service::do_read(
+    win_iocp_handle_service::implementation_type& impl, boost::uint64_t offset,
+    const asio::mutable_buffer& buffer, asio::error_code& ec)
+{
+  if (!is_open(impl))
+  {
+    ec = asio::error::bad_descriptor;
+    return 0;
+  }
+  
+  // A request to read 0 bytes on a stream handle is a no-op.
+  if (asio::buffer_size(buffer) == 0)
+  {
+    ec = asio::error_code();
+    return 0;
+  }
+
+  overlapped_wrapper overlapped(ec);
+  if (ec)
+  {
+    return 0;
+  }
+
+  // Read some data.
+  overlapped.Offset = offset & 0xFFFFFFFF;
+  overlapped.OffsetHigh = (offset >> 32) & 0xFFFFFFFF;
+  BOOL ok = ::ReadFile(impl.handle_,
+      asio::buffer_cast<LPVOID>(buffer),
+      static_cast<DWORD>(asio::buffer_size(buffer)), 0, &overlapped);
+  if (!ok) 
+  {
+    DWORD last_error = ::GetLastError();
+    if (last_error != ERROR_IO_PENDING && last_error != ERROR_MORE_DATA)
+    {
+      if (last_error == ERROR_HANDLE_EOF)
+      {
+        ec = asio::error::eof;
+      }
+      else
+      {
+        ec = asio::error_code(last_error,
+            asio::error::get_system_category());
+      }
+      return 0;
+    }
+  }
+
+  // Wait for the operation to complete.
+  DWORD bytes_transferred = 0;
+  ok = ::GetOverlappedResult(impl.handle_,
+      &overlapped, &bytes_transferred, TRUE);
+  if (!ok)
+  {
+    DWORD last_error = ::GetLastError();
+    if (last_error == ERROR_HANDLE_EOF)
+    {
+      ec = asio::error::eof;
+    }
+    else
+    {
+      ec = asio::error_code(last_error,
+          asio::error::get_system_category());
+    }
+    return 0;
+  }
+
+  ec = asio::error_code();
+  return bytes_transferred;
+}
+
+void win_iocp_handle_service::start_read_op(
+    win_iocp_handle_service::implementation_type& impl, boost::uint64_t offset,
+    const asio::mutable_buffer& buffer, operation* op)
+{
+  update_cancellation_thread_id(impl);
+  iocp_service_.work_started();
+
+  if (!is_open(impl))
+  {
+    iocp_service_.on_completion(op, asio::error::bad_descriptor);
+  }
+  else if (asio::buffer_size(buffer) == 0)
+  {
+    // A request to read 0 bytes on a handle is a no-op.
+    iocp_service_.on_completion(op);
+  }
+  else
+  {
+    DWORD bytes_transferred = 0;
+    op->Offset = offset & 0xFFFFFFFF;
+    op->OffsetHigh = (offset >> 32) & 0xFFFFFFFF;
+    BOOL ok = ::ReadFile(impl.handle_,
+        asio::buffer_cast<LPVOID>(buffer),
+        static_cast<DWORD>(asio::buffer_size(buffer)),
+        &bytes_transferred, op);
+    DWORD last_error = ::GetLastError();
+    if (!ok && last_error != ERROR_IO_PENDING
+        && last_error != ERROR_MORE_DATA)
+    {
+      iocp_service_.on_completion(op, last_error, bytes_transferred);
+    }
+    else
+    {
+      iocp_service_.on_pending(op);
+    }
+  }
+}
+
+void win_iocp_handle_service::update_cancellation_thread_id(
+    win_iocp_handle_service::implementation_type& impl)
+{
+  if (impl.safe_cancellation_thread_id_ == 0)
+    impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId();
+  else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId())
+    impl.safe_cancellation_thread_id_ = ~DWORD(0);
+}
+
+void win_iocp_handle_service::close_for_destruction(implementation_type& impl)
+{
+  if (is_open(impl))
+  {
+    ::CloseHandle(impl.handle_);
+    impl.handle_ = INVALID_HANDLE_VALUE;
+    impl.safe_cancellation_thread_id_ = 0;
+  }
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(ASIO_HAS_IOCP)
+
+#endif // ASIO_DETAIL_IMPL_WIN_IOCP_HANDLE_SERVICE_IPP
diff --git a/ext/asio/asio/detail/impl/win_iocp_io_service.hpp b/ext/asio/asio/detail/impl/win_iocp_io_service.hpp
new file mode 100644
index 0000000..ab23547
--- /dev/null
+++ b/ext/asio/asio/detail/impl/win_iocp_io_service.hpp
@@ -0,0 +1,115 @@
+//
+// detail/impl/win_iocp_io_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_IMPL_WIN_IOCP_IO_SERVICE_HPP
+#define ASIO_DETAIL_IMPL_WIN_IOCP_IO_SERVICE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(ASIO_HAS_IOCP)
+
+#include "asio/detail/call_stack.hpp"
+#include "asio/detail/completion_handler.hpp"
+#include "asio/detail/fenced_block.hpp"
+#include "asio/detail/handler_alloc_helpers.hpp"
+#include "asio/detail/handler_invoke_helpers.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename Handler>
+void win_iocp_io_service::dispatch(Handler handler)
+{
+  if (call_stack<win_iocp_io_service>::contains(this))
+  {
+    asio::detail::fenced_block b;
+    asio_handler_invoke_helpers::invoke(handler, handler);
+  }
+  else
+    post(handler);
+}
+
+template <typename Handler>
+void win_iocp_io_service::post(Handler handler)
+{
+  // Allocate and construct an operation to wrap the handler.
+  typedef completion_handler<Handler> op;
+  typename op::ptr p = { boost::addressof(handler),
+    asio_handler_alloc_helpers::allocate(
+      sizeof(op), handler), 0 };
+  p.p = new (p.v) op(handler);
+
+  post_immediate_completion(p.p);
+  p.v = p.p = 0;
+}
+
+template <typename Time_Traits>
+void win_iocp_io_service::add_timer_queue(
+    timer_queue<Time_Traits>& queue)
+{
+  do_add_timer_queue(queue);
+}
+
+template <typename Time_Traits>
+void win_iocp_io_service::remove_timer_queue(
+    timer_queue<Time_Traits>& queue)
+{
+  do_remove_timer_queue(queue);
+}
+
+template <typename Time_Traits>
+void win_iocp_io_service::schedule_timer(timer_queue<Time_Traits>& queue,
+    const typename Time_Traits::time_type& time,
+    typename timer_queue<Time_Traits>::per_timer_data& timer, timer_op* op)
+{
+  // If the service has been shut down we silently discard the timer.
+  if (::InterlockedExchangeAdd(&shutdown_, 0) != 0)
+  {
+    post_immediate_completion(op);
+    return;
+  }
+
+  mutex::scoped_lock lock(dispatch_mutex_);
+
+  bool earliest = queue.enqueue_timer(time, timer, op);
+  work_started();
+  if (earliest)
+    update_timeout();
+}
+
+template <typename Time_Traits>
+std::size_t win_iocp_io_service::cancel_timer(timer_queue<Time_Traits>& queue,
+    typename timer_queue<Time_Traits>::per_timer_data& timer)
+{
+  // If the service has been shut down we silently ignore the cancellation.
+  if (::InterlockedExchangeAdd(&shutdown_, 0) != 0)
+    return 0;
+
+  mutex::scoped_lock lock(dispatch_mutex_);
+  op_queue<win_iocp_operation> ops;
+  std::size_t n = queue.cancel_timer(timer, ops);
+  post_deferred_completions(ops);
+  return n;
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(ASIO_HAS_IOCP)
+
+#endif // ASIO_DETAIL_IMPL_WIN_IOCP_IO_SERVICE_HPP
diff --git a/ext/asio/asio/detail/impl/win_iocp_io_service.ipp b/ext/asio/asio/detail/impl/win_iocp_io_service.ipp
new file mode 100644
index 0000000..890e32f
--- /dev/null
+++ b/ext/asio/asio/detail/impl/win_iocp_io_service.ipp
@@ -0,0 +1,496 @@
+//
+// detail/impl/win_iocp_io_service.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_IMPL_WIN_IOCP_IO_SERVICE_IPP
+#define ASIO_DETAIL_IMPL_WIN_IOCP_IO_SERVICE_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(ASIO_HAS_IOCP)
+
+#include <boost/limits.hpp>
+#include "asio/error.hpp"
+#include "asio/io_service.hpp"
+#include "asio/detail/handler_alloc_helpers.hpp"
+#include "asio/detail/handler_invoke_helpers.hpp"
+#include "asio/detail/throw_error.hpp"
+#include "asio/detail/win_iocp_io_service.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+struct win_iocp_io_service::work_finished_on_block_exit
+{
+  ~work_finished_on_block_exit()
+  {
+    io_service_->work_finished();
+  }
+
+  win_iocp_io_service* io_service_;
+};
+
+struct win_iocp_io_service::timer_thread_function
+{
+  void operator()()
+  {
+    while (::InterlockedExchangeAdd(&io_service_->shutdown_, 0) == 0)
+    {
+      if (::WaitForSingleObject(io_service_->waitable_timer_.handle,
+            INFINITE) == WAIT_OBJECT_0)
+      {
+        ::InterlockedExchange(&io_service_->dispatch_required_, 1);
+        ::PostQueuedCompletionStatus(io_service_->iocp_.handle,
+            0, wake_for_dispatch, 0);
+      }
+    }
+  }
+
+  win_iocp_io_service* io_service_;
+};
+
+win_iocp_io_service::win_iocp_io_service(asio::io_service& io_service)
+  : asio::detail::service_base<win_iocp_io_service>(io_service),
+    iocp_(),
+    outstanding_work_(0),
+    stopped_(0),
+    shutdown_(0),
+    dispatch_required_(0)
+{
+}
+
+void win_iocp_io_service::init(size_t concurrency_hint)
+{
+  iocp_.handle = ::CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0,
+      static_cast<DWORD>((std::min<size_t>)(concurrency_hint, DWORD(~0))));
+  if (!iocp_.handle)
+  {
+    DWORD last_error = ::GetLastError();
+    asio::error_code ec(last_error,
+        asio::error::get_system_category());
+    asio::detail::throw_error(ec, "iocp");
+  }
+}
+
+void win_iocp_io_service::shutdown_service()
+{
+  ::InterlockedExchange(&shutdown_, 1);
+
+  if (timer_thread_)
+  {
+    LARGE_INTEGER timeout;
+    timeout.QuadPart = 1;
+    ::SetWaitableTimer(waitable_timer_.handle, &timeout, 1, 0, 0, FALSE);
+  }
+
+  while (::InterlockedExchangeAdd(&outstanding_work_, 0) > 0)
+  {
+    op_queue<win_iocp_operation> ops;
+    timer_queues_.get_all_timers(ops);
+    ops.push(completed_ops_);
+    if (!ops.empty())
+    {
+      while (win_iocp_operation* op = ops.front())
+      {
+        ops.pop();
+        ::InterlockedDecrement(&outstanding_work_);
+        op->destroy();
+      }
+    }
+    else
+    {
+      DWORD bytes_transferred = 0;
+      dword_ptr_t completion_key = 0;
+      LPOVERLAPPED overlapped = 0;
+      ::GetQueuedCompletionStatus(iocp_.handle, &bytes_transferred,
+          &completion_key, &overlapped, gqcs_timeout);
+      if (overlapped)
+      {
+        ::InterlockedDecrement(&outstanding_work_);
+        static_cast<win_iocp_operation*>(overlapped)->destroy();
+      }
+    }
+  }
+
+  if (timer_thread_)
+    timer_thread_->join();
+}
+
+asio::error_code win_iocp_io_service::register_handle(
+    HANDLE handle, asio::error_code& ec)
+{
+  if (::CreateIoCompletionPort(handle, iocp_.handle, 0, 0) == 0)
+  {
+    DWORD last_error = ::GetLastError();
+    ec = asio::error_code(last_error,
+        asio::error::get_system_category());
+  }
+  else
+  {
+    ec = asio::error_code();
+  }
+  return ec;
+}
+
+size_t win_iocp_io_service::run(asio::error_code& ec)
+{
+  if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0)
+  {
+    stop();
+    ec = asio::error_code();
+    return 0;
+  }
+
+  call_stack<win_iocp_io_service>::context ctx(this);
+
+  size_t n = 0;
+  while (do_one(true, ec))
+    if (n != (std::numeric_limits<size_t>::max)())
+      ++n;
+  return n;
+}
+
+size_t win_iocp_io_service::run_one(asio::error_code& ec)
+{
+  if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0)
+  {
+    stop();
+    ec = asio::error_code();
+    return 0;
+  }
+
+  call_stack<win_iocp_io_service>::context ctx(this);
+
+  return do_one(true, ec);
+}
+
+size_t win_iocp_io_service::poll(asio::error_code& ec)
+{
+  if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0)
+  {
+    stop();
+    ec = asio::error_code();
+    return 0;
+  }
+
+  call_stack<win_iocp_io_service>::context ctx(this);
+
+  size_t n = 0;
+  while (do_one(false, ec))
+    if (n != (std::numeric_limits<size_t>::max)())
+      ++n;
+  return n;
+}
+
+size_t win_iocp_io_service::poll_one(asio::error_code& ec)
+{
+  if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0)
+  {
+    stop();
+    ec = asio::error_code();
+    return 0;
+  }
+
+  call_stack<win_iocp_io_service>::context ctx(this);
+
+  return do_one(false, ec);
+}
+
+void win_iocp_io_service::stop()
+{
+  if (::InterlockedExchange(&stopped_, 1) == 0)
+  {
+    if (!::PostQueuedCompletionStatus(iocp_.handle, 0, 0, 0))
+    {
+      DWORD last_error = ::GetLastError();
+      asio::error_code ec(last_error,
+          asio::error::get_system_category());
+      asio::detail::throw_error(ec, "pqcs");
+    }
+  }
+}
+
+void win_iocp_io_service::post_deferred_completion(win_iocp_operation* op)
+{
+  // Flag the operation as ready.
+  op->ready_ = 1;
+
+  // Enqueue the operation on the I/O completion port.
+  if (!::PostQueuedCompletionStatus(iocp_.handle,
+        0, overlapped_contains_result, op))
+  {
+    // Out of resources. Put on completed queue instead.
+    mutex::scoped_lock lock(dispatch_mutex_);
+    completed_ops_.push(op);
+    ::InterlockedExchange(&dispatch_required_, 1);
+  }
+}
+
+void win_iocp_io_service::post_deferred_completions(
+    op_queue<win_iocp_operation>& ops)
+{
+  while (win_iocp_operation* op = ops.front())
+  {
+    ops.pop();
+
+    // Flag the operation as ready.
+    op->ready_ = 1;
+
+    // Enqueue the operation on the I/O completion port.
+    if (!::PostQueuedCompletionStatus(iocp_.handle,
+          0, overlapped_contains_result, op))
+    {
+      // Out of resources. Put on completed queue instead.
+      mutex::scoped_lock lock(dispatch_mutex_);
+      completed_ops_.push(op);
+      completed_ops_.push(ops);
+      ::InterlockedExchange(&dispatch_required_, 1);
+    }
+  }
+}
+
+void win_iocp_io_service::on_pending(win_iocp_operation* op)
+{
+  if (::InterlockedCompareExchange(&op->ready_, 1, 0) == 1)
+  {
+    // Enqueue the operation on the I/O completion port.
+    if (!::PostQueuedCompletionStatus(iocp_.handle,
+          0, overlapped_contains_result, op))
+    {
+      // Out of resources. Put on completed queue instead.
+      mutex::scoped_lock lock(dispatch_mutex_);
+      completed_ops_.push(op);
+      ::InterlockedExchange(&dispatch_required_, 1);
+    }
+  }
+}
+
+void win_iocp_io_service::on_completion(win_iocp_operation* op,
+    DWORD last_error, DWORD bytes_transferred)
+{
+  // Flag that the operation is ready for invocation.
+  op->ready_ = 1;
+
+  // Store results in the OVERLAPPED structure.
+  op->Internal = asio::error::get_system_category();
+  op->Offset = last_error;
+  op->OffsetHigh = bytes_transferred;
+
+  // Enqueue the operation on the I/O completion port.
+  if (!::PostQueuedCompletionStatus(iocp_.handle,
+        0, overlapped_contains_result, op))
+  {
+    // Out of resources. Put on completed queue instead.
+    mutex::scoped_lock lock(dispatch_mutex_);
+    completed_ops_.push(op);
+    ::InterlockedExchange(&dispatch_required_, 1);
+  }
+}
+
+void win_iocp_io_service::on_completion(win_iocp_operation* op,
+    const asio::error_code& ec, DWORD bytes_transferred)
+{
+  // Flag that the operation is ready for invocation.
+  op->ready_ = 1;
+
+  // Store results in the OVERLAPPED structure.
+  op->Internal = ec.category();
+  op->Offset = ec.value();
+  op->OffsetHigh = bytes_transferred;
+
+  // Enqueue the operation on the I/O completion port.
+  if (!::PostQueuedCompletionStatus(iocp_.handle,
+        0, overlapped_contains_result, op))
+  {
+    // Out of resources. Put on completed queue instead.
+    mutex::scoped_lock lock(dispatch_mutex_);
+    completed_ops_.push(op);
+    ::InterlockedExchange(&dispatch_required_, 1);
+  }
+}
+
+size_t win_iocp_io_service::do_one(bool block, asio::error_code& ec)
+{
+  for (;;)
+  {
+    // Try to acquire responsibility for dispatching timers and completed ops.
+    if (::InterlockedCompareExchange(&dispatch_required_, 0, 1) == 1)
+    {
+      mutex::scoped_lock lock(dispatch_mutex_);
+
+      // Dispatch pending timers and operations.
+      op_queue<win_iocp_operation> ops;
+      ops.push(completed_ops_);
+      timer_queues_.get_ready_timers(ops);
+      post_deferred_completions(ops);
+      update_timeout();
+    }
+
+    // Get the next operation from the queue.
+    DWORD bytes_transferred = 0;
+    dword_ptr_t completion_key = 0;
+    LPOVERLAPPED overlapped = 0;
+    ::SetLastError(0);
+    BOOL ok = ::GetQueuedCompletionStatus(iocp_.handle, &bytes_transferred,
+        &completion_key, &overlapped, block ? gqcs_timeout : 0);
+    DWORD last_error = ::GetLastError();
+
+    if (overlapped)
+    {
+      win_iocp_operation* op = static_cast<win_iocp_operation*>(overlapped);
+      asio::error_code result_ec(last_error,
+          asio::error::get_system_category());
+
+      // We may have been passed the last_error and bytes_transferred in the
+      // OVERLAPPED structure itself.
+      if (completion_key == overlapped_contains_result)
+      {
+        result_ec = asio::error_code(static_cast<int>(op->Offset),
+            static_cast<asio::error_category>(op->Internal));
+        bytes_transferred = op->OffsetHigh;
+      }
+
+      // Otherwise ensure any result has been saved into the OVERLAPPED
+      // structure.
+      else
+      {
+        op->Internal = result_ec.category();
+        op->Offset = result_ec.value();
+        op->OffsetHigh = bytes_transferred;
+      }
+
+      // Dispatch the operation only if ready. The operation may not be ready
+      // if the initiating function (e.g. a call to WSARecv) has not yet
+      // returned. This is because the initiating function still wants access
+      // to the operation's OVERLAPPED structure.
+      if (::InterlockedCompareExchange(&op->ready_, 1, 0) == 1)
+      {
+        // Ensure the count of outstanding work is decremented on block exit.
+        work_finished_on_block_exit on_exit = { this };
+        (void)on_exit;
+
+        op->complete(*this, result_ec, bytes_transferred);
+        ec = asio::error_code();
+        return 1;
+      }
+    }
+    else if (!ok)
+    {
+      if (last_error != WAIT_TIMEOUT)
+      {
+        ec = asio::error_code(last_error,
+            asio::error::get_system_category());
+        return 0;
+      }
+
+      // If we're not polling we need to keep going until we get a real handler.
+      if (block)
+        continue;
+
+      ec = asio::error_code();
+      return 0;
+    }
+    else if (completion_key == wake_for_dispatch)
+    {
+      // We have been woken up to try to acquire responsibility for dispatching
+      // timers and completed operations.
+    }
+    else
+    {
+      // The stopped_ flag is always checked to ensure that any leftover
+      // interrupts from a previous run invocation are ignored.
+      if (::InterlockedExchangeAdd(&stopped_, 0) != 0)
+      {
+        // Wake up next thread that is blocked on GetQueuedCompletionStatus.
+        if (!::PostQueuedCompletionStatus(iocp_.handle, 0, 0, 0))
+        {
+          last_error = ::GetLastError();
+          ec = asio::error_code(last_error,
+              asio::error::get_system_category());
+          return 0;
+        }
+
+        ec = asio::error_code();
+        return 0;
+      }
+    }
+  }
+}
+
+void win_iocp_io_service::do_add_timer_queue(timer_queue_base& queue)
+{
+  mutex::scoped_lock lock(dispatch_mutex_);
+
+  timer_queues_.insert(&queue);
+
+  if (!waitable_timer_.handle)
+  {
+    waitable_timer_.handle = ::CreateWaitableTimer(0, FALSE, 0);
+    if (waitable_timer_.handle == 0)
+    {
+      DWORD last_error = ::GetLastError();
+      asio::error_code ec(last_error,
+          asio::error::get_system_category());
+      asio::detail::throw_error(ec, "timer");
+    }
+
+    LARGE_INTEGER timeout;
+    timeout.QuadPart = -max_timeout_usec;
+    timeout.QuadPart *= 10;
+    ::SetWaitableTimer(waitable_timer_.handle,
+        &timeout, max_timeout_msec, 0, 0, FALSE);
+  }
+
+  if (!timer_thread_)
+  {
+    timer_thread_function thread_function = { this };
+    timer_thread_.reset(new thread(thread_function, 65536));
+  }
+}
+
+void win_iocp_io_service::do_remove_timer_queue(timer_queue_base& queue)
+{
+  mutex::scoped_lock lock(dispatch_mutex_);
+
+  timer_queues_.erase(&queue);
+}
+
+void win_iocp_io_service::update_timeout()
+{
+  if (timer_thread_)
+  {
+    // There's no point updating the waitable timer if the new timeout period
+    // exceeds the maximum timeout. In that case, we might as well wait for the
+    // existing period of the timer to expire.
+    long timeout_usec = timer_queues_.wait_duration_usec(max_timeout_usec);
+    if (timeout_usec < max_timeout_usec)
+    {
+      LARGE_INTEGER timeout;
+      timeout.QuadPart = -timeout_usec;
+      timeout.QuadPart *= 10;
+      ::SetWaitableTimer(waitable_timer_.handle,
+          &timeout, max_timeout_msec, 0, 0, FALSE);
+    }
+  }
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(ASIO_HAS_IOCP)
+
+#endif // ASIO_DETAIL_IMPL_WIN_IOCP_IO_SERVICE_IPP
diff --git a/ext/asio/asio/detail/impl/win_iocp_serial_port_service.ipp b/ext/asio/asio/detail/impl/win_iocp_serial_port_service.ipp
new file mode 100644
index 0000000..7631514
--- /dev/null
+++ b/ext/asio/asio/detail/impl/win_iocp_serial_port_service.ipp
@@ -0,0 +1,180 @@
+//
+// detail/impl/win_iocp_serial_port_service.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2008 Rep Invariant Systems, Inc. (info at repinvariant.com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_IMPL_WIN_IOCP_SERIAL_PORT_SERVICE_IPP
+#define ASIO_DETAIL_IMPL_WIN_IOCP_SERIAL_PORT_SERVICE_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(ASIO_HAS_IOCP) && defined(ASIO_HAS_SERIAL_PORT)
+
+#include <cstring>
+#include "asio/detail/win_iocp_serial_port_service.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+win_iocp_serial_port_service::win_iocp_serial_port_service(
+    asio::io_service& io_service)
+  : handle_service_(io_service)
+{
+}
+
+void win_iocp_serial_port_service::shutdown_service()
+{
+}
+
+asio::error_code win_iocp_serial_port_service::open(
+    win_iocp_serial_port_service::implementation_type& impl,
+    const std::string& device, asio::error_code& ec)
+{
+  if (is_open(impl))
+  {
+    ec = asio::error::already_open;
+    return ec;
+  }
+
+  // For convenience, add a leading \\.\ sequence if not already present.
+  std::string name = (device[0] == '\\') ? device : "\\\\.\\" + device;
+
+  // Open a handle to the serial port.
+  ::HANDLE handle = ::CreateFileA(name.c_str(),
+      GENERIC_READ | GENERIC_WRITE, 0, 0,
+      OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
+  if (handle == INVALID_HANDLE_VALUE)
+  {
+    DWORD last_error = ::GetLastError();
+    ec = asio::error_code(last_error,
+        asio::error::get_system_category());
+    return ec;
+  }
+
+  // Determine the initial serial port parameters.
+  using namespace std; // For memset.
+  ::DCB dcb;
+  memset(&dcb, 0, sizeof(DCB));
+  dcb.DCBlength = sizeof(DCB);
+  if (!::GetCommState(handle, &dcb))
+  {
+    DWORD last_error = ::GetLastError();
+    ::CloseHandle(handle);
+    ec = asio::error_code(last_error,
+        asio::error::get_system_category());
+    return ec;
+  }
+
+  // Set some default serial port parameters. This implementation does not
+  // support changing these, so they might as well be in a known state.
+  dcb.fBinary = TRUE; // Win32 only supports binary mode.
+  dcb.fDsrSensitivity = FALSE;
+  dcb.fNull = FALSE; // Do not ignore NULL characters.
+  dcb.fAbortOnError = FALSE; // Ignore serial framing errors.
+  if (!::SetCommState(handle, &dcb))
+  {
+    DWORD last_error = ::GetLastError();
+    ::CloseHandle(handle);
+    ec = asio::error_code(last_error,
+        asio::error::get_system_category());
+    return ec;
+  }
+
+  // Set up timeouts so that the serial port will behave similarly to a
+  // network socket. Reads wait for at least one byte, then return with
+  // whatever they have. Writes return once everything is out the door.
+  ::COMMTIMEOUTS timeouts;
+  timeouts.ReadIntervalTimeout = 1;
+  timeouts.ReadTotalTimeoutMultiplier = 0;
+  timeouts.ReadTotalTimeoutConstant = 0;
+  timeouts.WriteTotalTimeoutMultiplier = 0;
+  timeouts.WriteTotalTimeoutConstant = 0;
+  if (!::SetCommTimeouts(handle, &timeouts))
+  {
+    DWORD last_error = ::GetLastError();
+    ::CloseHandle(handle);
+    ec = asio::error_code(last_error,
+        asio::error::get_system_category());
+    return ec;
+  }
+
+  // We're done. Take ownership of the serial port handle.
+  if (handle_service_.assign(impl, handle, ec))
+    ::CloseHandle(handle);
+  return ec;
+}
+
+asio::error_code win_iocp_serial_port_service::do_set_option(
+    win_iocp_serial_port_service::implementation_type& impl,
+    win_iocp_serial_port_service::store_function_type store,
+    const void* option, asio::error_code& ec)
+{
+  using namespace std; // For memcpy.
+
+  ::DCB dcb;
+  memset(&dcb, 0, sizeof(DCB));
+  dcb.DCBlength = sizeof(DCB);
+  if (!::GetCommState(handle_service_.native(impl), &dcb))
+  {
+    DWORD last_error = ::GetLastError();
+    ec = asio::error_code(last_error,
+        asio::error::get_system_category());
+    return ec;
+  }
+
+  if (store(option, dcb, ec))
+    return ec;
+
+  if (!::SetCommState(handle_service_.native(impl), &dcb))
+  {
+    DWORD last_error = ::GetLastError();
+    ec = asio::error_code(last_error,
+        asio::error::get_system_category());
+    return ec;
+  }
+
+  ec = asio::error_code();
+  return ec;
+}
+
+asio::error_code win_iocp_serial_port_service::do_get_option(
+    const win_iocp_serial_port_service::implementation_type& impl,
+    win_iocp_serial_port_service::load_function_type load,
+    void* option, asio::error_code& ec) const
+{
+  using namespace std; // For memset.
+
+  ::DCB dcb;
+  memset(&dcb, 0, sizeof(DCB));
+  dcb.DCBlength = sizeof(DCB);
+  if (!::GetCommState(handle_service_.native(impl), &dcb))
+  {
+    DWORD last_error = ::GetLastError();
+    ec = asio::error_code(last_error,
+        asio::error::get_system_category());
+    return ec;
+  }
+
+  return load(option, dcb, ec);
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(ASIO_HAS_IOCP) && defined(ASIO_HAS_SERIAL_PORT)
+
+#endif // ASIO_DETAIL_IMPL_WIN_IOCP_SERIAL_PORT_SERVICE_IPP
diff --git a/ext/asio/asio/detail/impl/win_iocp_socket_service_base.ipp b/ext/asio/asio/detail/impl/win_iocp_socket_service_base.ipp
new file mode 100644
index 0000000..37c6f63
--- /dev/null
+++ b/ext/asio/asio/detail/impl/win_iocp_socket_service_base.ipp
@@ -0,0 +1,575 @@
+//
+// detail/impl/win_iocp_socket_service_base.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_IMPL_WIN_IOCP_SOCKET_SERVICE_BASE_IPP
+#define ASIO_DETAIL_IMPL_WIN_IOCP_SOCKET_SERVICE_BASE_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(ASIO_HAS_IOCP)
+
+#include "asio/detail/win_iocp_socket_service_base.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+win_iocp_socket_service_base::win_iocp_socket_service_base(
+    asio::io_service& io_service)
+  : io_service_(io_service),
+    iocp_service_(use_service<win_iocp_io_service>(io_service)),
+    reactor_(0),
+    mutex_(),
+    impl_list_(0)
+{
+}
+
+void win_iocp_socket_service_base::shutdown_service()
+{
+  // Close all implementations, causing all operations to complete.
+  asio::detail::mutex::scoped_lock lock(mutex_);
+  base_implementation_type* impl = impl_list_;
+  while (impl)
+  {
+    asio::error_code ignored_ec;
+    close_for_destruction(*impl);
+    impl = impl->next_;
+  }
+}
+
+void win_iocp_socket_service_base::construct(
+    win_iocp_socket_service_base::base_implementation_type& impl)
+{
+  impl.socket_ = invalid_socket;
+  impl.state_ = 0;
+  impl.cancel_token_.reset();
+#if defined(ASIO_ENABLE_CANCELIO)
+  impl.safe_cancellation_thread_id_ = 0;
+#endif // defined(ASIO_ENABLE_CANCELIO)
+
+  // Insert implementation into linked list of all implementations.
+  asio::detail::mutex::scoped_lock lock(mutex_);
+  impl.next_ = impl_list_;
+  impl.prev_ = 0;
+  if (impl_list_)
+    impl_list_->prev_ = &impl;
+  impl_list_ = &impl;
+}
+
+void win_iocp_socket_service_base::destroy(
+    win_iocp_socket_service_base::base_implementation_type& impl)
+{
+  close_for_destruction(impl);
+
+  // Remove implementation from linked list of all implementations.
+  asio::detail::mutex::scoped_lock lock(mutex_);
+  if (impl_list_ == &impl)
+    impl_list_ = impl.next_;
+  if (impl.prev_)
+    impl.prev_->next_ = impl.next_;
+  if (impl.next_)
+    impl.next_->prev_= impl.prev_;
+  impl.next_ = 0;
+  impl.prev_ = 0;
+}
+
+asio::error_code win_iocp_socket_service_base::close(
+    win_iocp_socket_service_base::base_implementation_type& impl,
+    asio::error_code& ec)
+{
+  if (is_open(impl))
+  {
+    // Check if the reactor was created, in which case we need to close the
+    // socket on the reactor as well to cancel any operations that might be
+    // running there.
+    reactor* r = static_cast<reactor*>(
+          interlocked_compare_exchange_pointer(
+            reinterpret_cast<void**>(&reactor_), 0, 0));
+    if (r)
+      r->close_descriptor(impl.socket_, impl.reactor_data_);
+  }
+
+  if (socket_ops::close(impl.socket_, impl.state_, false, ec) == 0)
+  {
+    impl.socket_ = invalid_socket;
+    impl.state_ = 0;
+    impl.cancel_token_.reset();
+#if defined(ASIO_ENABLE_CANCELIO)
+    impl.safe_cancellation_thread_id_ = 0;
+#endif // defined(ASIO_ENABLE_CANCELIO)
+  }
+
+  return ec;
+}
+
+asio::error_code win_iocp_socket_service_base::cancel(
+    win_iocp_socket_service_base::base_implementation_type& impl,
+    asio::error_code& ec)
+{
+  if (!is_open(impl))
+  {
+    ec = asio::error::bad_descriptor;
+    return ec;
+  }
+  else if (FARPROC cancel_io_ex_ptr = ::GetProcAddress(
+        ::GetModuleHandleA("KERNEL32"), "CancelIoEx"))
+  {
+    // The version of Windows supports cancellation from any thread.
+    typedef BOOL (WINAPI* cancel_io_ex_t)(HANDLE, LPOVERLAPPED);
+    cancel_io_ex_t cancel_io_ex = (cancel_io_ex_t)cancel_io_ex_ptr;
+    socket_type sock = impl.socket_;
+    HANDLE sock_as_handle = reinterpret_cast<HANDLE>(sock);
+    if (!cancel_io_ex(sock_as_handle, 0))
+    {
+      DWORD last_error = ::GetLastError();
+      if (last_error == ERROR_NOT_FOUND)
+      {
+        // ERROR_NOT_FOUND means that there were no operations to be
+        // cancelled. We swallow this error to match the behaviour on other
+        // platforms.
+        ec = asio::error_code();
+      }
+      else
+      {
+        ec = asio::error_code(last_error,
+            asio::error::get_system_category());
+      }
+    }
+    else
+    {
+      ec = asio::error_code();
+    }
+  }
+#if defined(ASIO_ENABLE_CANCELIO)
+  else if (impl.safe_cancellation_thread_id_ == 0)
+  {
+    // No operations have been started, so there's nothing to cancel.
+    ec = asio::error_code();
+  }
+  else if (impl.safe_cancellation_thread_id_ == ::GetCurrentThreadId())
+  {
+    // Asynchronous operations have been started from the current thread only,
+    // so it is safe to try to cancel them using CancelIo.
+    socket_type sock = impl.socket_;
+    HANDLE sock_as_handle = reinterpret_cast<HANDLE>(sock);
+    if (!::CancelIo(sock_as_handle))
+    {
+      DWORD last_error = ::GetLastError();
+      ec = asio::error_code(last_error,
+          asio::error::get_system_category());
+    }
+    else
+    {
+      ec = asio::error_code();
+    }
+  }
+  else
+  {
+    // Asynchronous operations have been started from more than one thread,
+    // so cancellation is not safe.
+    ec = asio::error::operation_not_supported;
+  }
+#else // defined(ASIO_ENABLE_CANCELIO)
+  else
+  {
+    // Cancellation is not supported as CancelIo may not be used.
+    ec = asio::error::operation_not_supported;
+  }
+#endif // defined(ASIO_ENABLE_CANCELIO)
+
+  // Cancel any operations started via the reactor.
+  if (!ec)
+  {
+    reactor* r = static_cast<reactor*>(
+          interlocked_compare_exchange_pointer(
+            reinterpret_cast<void**>(&reactor_), 0, 0));
+    if (r)
+      r->cancel_ops(impl.socket_, impl.reactor_data_);
+  }
+
+  return ec;
+}
+
+asio::error_code win_iocp_socket_service_base::do_open(
+    win_iocp_socket_service_base::base_implementation_type& impl,
+    int family, int type, int protocol, asio::error_code& ec)
+{
+  if (is_open(impl))
+  {
+    ec = asio::error::already_open;
+    return ec;
+  }
+
+  socket_holder sock(socket_ops::socket(family, type, protocol, ec));
+  if (sock.get() == invalid_socket)
+    return ec;
+
+  HANDLE sock_as_handle = reinterpret_cast<HANDLE>(sock.get());
+  if (iocp_service_.register_handle(sock_as_handle, ec))
+    return ec;
+
+  impl.socket_ = sock.release();
+  switch (type)
+  {
+  case SOCK_STREAM: impl.state_ = socket_ops::stream_oriented; break;
+  case SOCK_DGRAM: impl.state_ = socket_ops::datagram_oriented; break;
+  default: impl.state_ = 0; break;
+  }
+  impl.cancel_token_.reset(static_cast<void*>(0), socket_ops::noop_deleter());
+  ec = asio::error_code();
+  return ec;
+}
+
+asio::error_code win_iocp_socket_service_base::do_assign(
+    win_iocp_socket_service_base::base_implementation_type& impl,
+    int type, socket_type native_socket, asio::error_code& ec)
+{
+  if (is_open(impl))
+  {
+    ec = asio::error::already_open;
+    return ec;
+  }
+
+  HANDLE sock_as_handle = reinterpret_cast<HANDLE>(native_socket);
+  if (iocp_service_.register_handle(sock_as_handle, ec))
+    return ec;
+
+  impl.socket_ = native_socket;
+  switch (type)
+  {
+  case SOCK_STREAM: impl.state_ = socket_ops::stream_oriented; break;
+  case SOCK_DGRAM: impl.state_ = socket_ops::datagram_oriented; break;
+  default: impl.state_ = 0; break;
+  }
+  impl.cancel_token_.reset(static_cast<void*>(0), socket_ops::noop_deleter());
+  ec = asio::error_code();
+  return ec;
+}
+
+void win_iocp_socket_service_base::start_send_op(
+    win_iocp_socket_service_base::base_implementation_type& impl,
+    WSABUF* buffers, std::size_t buffer_count,
+    socket_base::message_flags flags, bool noop, operation* op)
+{
+  update_cancellation_thread_id(impl);
+  iocp_service_.work_started();
+
+  if (noop)
+    iocp_service_.on_completion(op);
+  else if (!is_open(impl))
+    iocp_service_.on_completion(op, asio::error::bad_descriptor);
+  else
+  {
+    DWORD bytes_transferred = 0;
+    int result = ::WSASend(impl.socket_, buffers,
+        static_cast<DWORD>(buffer_count), &bytes_transferred, flags, op, 0);
+    DWORD last_error = ::WSAGetLastError();
+    if (last_error == ERROR_PORT_UNREACHABLE)
+      last_error = WSAECONNREFUSED;
+    if (result != 0 && last_error != WSA_IO_PENDING)
+      iocp_service_.on_completion(op, last_error, bytes_transferred);
+    else
+      iocp_service_.on_pending(op);
+  }
+}
+
+void win_iocp_socket_service_base::start_send_to_op(
+    win_iocp_socket_service_base::base_implementation_type& impl,
+    WSABUF* buffers, std::size_t buffer_count,
+    const socket_addr_type* addr, int addrlen,
+    socket_base::message_flags flags, operation* op)
+{
+  update_cancellation_thread_id(impl);
+  iocp_service_.work_started();
+
+  if (!is_open(impl))
+    iocp_service_.on_completion(op, asio::error::bad_descriptor);
+  else
+  {
+    DWORD bytes_transferred = 0;
+    int result = ::WSASendTo(impl.socket_, buffers,
+        static_cast<DWORD>(buffer_count),
+        &bytes_transferred, flags, addr, addrlen, op, 0);
+    DWORD last_error = ::WSAGetLastError();
+    if (last_error == ERROR_PORT_UNREACHABLE)
+      last_error = WSAECONNREFUSED;
+    if (result != 0 && last_error != WSA_IO_PENDING)
+      iocp_service_.on_completion(op, last_error, bytes_transferred);
+    else
+      iocp_service_.on_pending(op);
+  }
+}
+
+void win_iocp_socket_service_base::start_receive_op(
+    win_iocp_socket_service_base::base_implementation_type& impl,
+    WSABUF* buffers, std::size_t buffer_count,
+    socket_base::message_flags flags, bool noop, operation* op)
+{
+  update_cancellation_thread_id(impl);
+  iocp_service_.work_started();
+
+  if (noop)
+    iocp_service_.on_completion(op);
+  else if (!is_open(impl))
+    iocp_service_.on_completion(op, asio::error::bad_descriptor);
+  else
+  {
+    DWORD bytes_transferred = 0;
+    DWORD recv_flags = flags;
+    int result = ::WSARecv(impl.socket_, buffers,
+        static_cast<DWORD>(buffer_count),
+        &bytes_transferred, &recv_flags, op, 0);
+    DWORD last_error = ::WSAGetLastError();
+    if (last_error == ERROR_NETNAME_DELETED)
+      last_error = WSAECONNRESET;
+    else if (last_error == ERROR_PORT_UNREACHABLE)
+      last_error = WSAECONNREFUSED;
+    if (result != 0 && last_error != WSA_IO_PENDING)
+      iocp_service_.on_completion(op, last_error, bytes_transferred);
+    else
+      iocp_service_.on_pending(op);
+  }
+}
+
+void win_iocp_socket_service_base::start_null_buffers_receive_op(
+    win_iocp_socket_service_base::base_implementation_type& impl,
+    socket_base::message_flags flags, reactor_op* op)
+{
+  if ((impl.state_ & socket_ops::stream_oriented) != 0)
+  {
+    // For stream sockets on Windows, we may issue a 0-byte overlapped
+    // WSARecv to wait until there is data available on the socket.
+    ::WSABUF buf = { 0, 0 };
+    start_receive_op(impl, &buf, 1, flags, false, op);
+  }
+  else
+  {
+    start_reactor_op(impl,
+        (flags & socket_base::message_out_of_band)
+          ? reactor::except_op : reactor::read_op,
+        op);
+  }
+}
+
+void win_iocp_socket_service_base::start_receive_from_op(
+    win_iocp_socket_service_base::base_implementation_type& impl,
+    WSABUF* buffers, std::size_t buffer_count, socket_addr_type* addr,
+    socket_base::message_flags flags, int* addrlen, operation* op)
+{
+  update_cancellation_thread_id(impl);
+  iocp_service_.work_started();
+
+  if (!is_open(impl))
+    iocp_service_.on_completion(op, asio::error::bad_descriptor);
+  else
+  {
+    DWORD bytes_transferred = 0;
+    DWORD recv_flags = flags;
+    int result = ::WSARecvFrom(impl.socket_, buffers,
+        static_cast<DWORD>(buffer_count),
+        &bytes_transferred, &recv_flags, addr, addrlen, op, 0);
+    DWORD last_error = ::WSAGetLastError();
+    if (last_error == ERROR_PORT_UNREACHABLE)
+      last_error = WSAECONNREFUSED;
+    if (result != 0 && last_error != WSA_IO_PENDING)
+      iocp_service_.on_completion(op, last_error, bytes_transferred);
+    else
+      iocp_service_.on_pending(op);
+  }
+}
+
+void win_iocp_socket_service_base::start_accept_op(
+    win_iocp_socket_service_base::base_implementation_type& impl,
+    bool peer_is_open, socket_holder& new_socket, int family, int type,
+    int protocol, void* output_buffer, DWORD address_length, operation* op)
+{
+  update_cancellation_thread_id(impl);
+  iocp_service_.work_started();
+
+  if (!is_open(impl))
+    iocp_service_.on_completion(op, asio::error::bad_descriptor);
+  else if (peer_is_open)
+    iocp_service_.on_completion(op, asio::error::already_open);
+  else
+  {
+    asio::error_code ec;
+    new_socket.reset(socket_ops::socket(family, type, protocol, ec));
+    if (new_socket.get() == invalid_socket)
+      iocp_service_.on_completion(op, ec);
+    else
+    {
+      DWORD bytes_read = 0;
+      BOOL result = ::AcceptEx(impl.socket_, new_socket.get(), output_buffer,
+          0, address_length, address_length, &bytes_read, op);
+      DWORD last_error = ::WSAGetLastError();
+      if (!result && last_error != WSA_IO_PENDING)
+        iocp_service_.on_completion(op, last_error);
+      else
+        iocp_service_.on_pending(op);
+    }
+  }
+}
+
+void win_iocp_socket_service_base::restart_accept_op(
+    socket_type s, socket_holder& new_socket, int family, int type,
+    int protocol, void* output_buffer, DWORD address_length, operation* op)
+{
+  new_socket.reset();
+  iocp_service_.work_started();
+
+  asio::error_code ec;
+  new_socket.reset(socket_ops::socket(family, type, protocol, ec));
+  if (new_socket.get() == invalid_socket)
+    iocp_service_.on_completion(op, ec);
+  else
+  {
+    DWORD bytes_read = 0;
+    BOOL result = ::AcceptEx(s, new_socket.get(), output_buffer,
+        0, address_length, address_length, &bytes_read, op);
+    DWORD last_error = ::WSAGetLastError();
+    if (!result && last_error != WSA_IO_PENDING)
+      iocp_service_.on_completion(op, last_error);
+    else
+      iocp_service_.on_pending(op);
+  }
+}
+
+void win_iocp_socket_service_base::start_reactor_op(
+    win_iocp_socket_service_base::base_implementation_type& impl,
+    int op_type, reactor_op* op)
+{
+  reactor& r = get_reactor();
+  update_cancellation_thread_id(impl);
+
+  if (is_open(impl))
+  {
+    r.start_op(op_type, impl.socket_, impl.reactor_data_, op, false);
+    return;
+  }
+  else
+    op->ec_ = asio::error::bad_descriptor;
+
+  iocp_service_.post_immediate_completion(op);
+}
+
+void win_iocp_socket_service_base::start_connect_op(
+    win_iocp_socket_service_base::base_implementation_type& impl,
+    reactor_op* op, const socket_addr_type* addr, std::size_t addrlen)
+{
+  reactor& r = get_reactor();
+  update_cancellation_thread_id(impl);
+
+  if ((impl.state_ & socket_ops::non_blocking) != 0
+      || socket_ops::set_internal_non_blocking(
+        impl.socket_, impl.state_, op->ec_))
+  {
+    if (socket_ops::connect(impl.socket_, addr, addrlen, op->ec_) != 0)
+    {
+      if (op->ec_ == asio::error::in_progress
+          || op->ec_ == asio::error::would_block)
+      {
+        op->ec_ = asio::error_code();
+        r.start_op(reactor::connect_op, impl.socket_,
+            impl.reactor_data_, op, false);
+        return;
+      }
+    }
+  }
+
+  r.post_immediate_completion(op);
+}
+
+void win_iocp_socket_service_base::close_for_destruction(
+    win_iocp_socket_service_base::base_implementation_type& impl)
+{
+  if (is_open(impl))
+  {
+    // Check if the reactor was created, in which case we need to close the
+    // socket on the reactor as well to cancel any operations that might be
+    // running there.
+    reactor* r = static_cast<reactor*>(
+          interlocked_compare_exchange_pointer(
+            reinterpret_cast<void**>(&reactor_), 0, 0));
+    if (r)
+      r->close_descriptor(impl.socket_, impl.reactor_data_);
+  }
+
+  asio::error_code ignored_ec;
+  socket_ops::close(impl.socket_, impl.state_, true, ignored_ec);
+  impl.socket_ = invalid_socket;
+  impl.state_ = 0;
+  impl.cancel_token_.reset();
+#if defined(ASIO_ENABLE_CANCELIO)
+  impl.safe_cancellation_thread_id_ = 0;
+#endif // defined(ASIO_ENABLE_CANCELIO)
+}
+
+void win_iocp_socket_service_base::update_cancellation_thread_id(
+    win_iocp_socket_service_base::base_implementation_type& impl)
+{
+#if defined(ASIO_ENABLE_CANCELIO)
+  if (impl.safe_cancellation_thread_id_ == 0)
+    impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId();
+  else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId())
+    impl.safe_cancellation_thread_id_ = ~DWORD(0);
+#else // defined(ASIO_ENABLE_CANCELIO)
+  (void)impl;
+#endif // defined(ASIO_ENABLE_CANCELIO)
+}
+
+reactor& win_iocp_socket_service_base::get_reactor()
+{
+  reactor* r = static_cast<reactor*>(
+        interlocked_compare_exchange_pointer(
+          reinterpret_cast<void**>(&reactor_), 0, 0));
+  if (!r)
+  {
+    r = &(use_service<reactor>(io_service_));
+    interlocked_exchange_pointer(reinterpret_cast<void**>(&reactor_), r);
+  }
+  return *r;
+}
+
+void* win_iocp_socket_service_base::interlocked_compare_exchange_pointer(
+    void** dest, void* exch, void* cmp)
+{
+#if defined(_M_IX86)
+  return reinterpret_cast<void*>(InterlockedCompareExchange(
+        reinterpret_cast<PLONG>(dest), reinterpret_cast<LONG>(exch),
+        reinterpret_cast<LONG>(cmp)));
+#else
+  return InterlockedCompareExchangePointer(dest, exch, cmp);
+#endif
+}
+
+void* win_iocp_socket_service_base::interlocked_exchange_pointer(
+    void** dest, void* val)
+{
+#if defined(_M_IX86)
+  return reinterpret_cast<void*>(InterlockedExchange(
+        reinterpret_cast<PLONG>(dest), reinterpret_cast<LONG>(val)));
+#else
+  return InterlockedExchangePointer(dest, val);
+#endif
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(ASIO_HAS_IOCP)
+
+#endif // ASIO_DETAIL_IMPL_WIN_IOCP_SOCKET_SERVICE_BASE_IPP
diff --git a/ext/asio/asio/detail/impl/win_mutex.ipp b/ext/asio/asio/detail/impl/win_mutex.ipp
new file mode 100644
index 0000000..910cc23
--- /dev/null
+++ b/ext/asio/asio/detail/impl/win_mutex.ipp
@@ -0,0 +1,78 @@
+//
+// detail/impl/win_mutex.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_IMPL_WIN_MUTEX_IPP
+#define ASIO_DETAIL_IMPL_WIN_MUTEX_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(BOOST_WINDOWS)
+
+#include "asio/detail/throw_error.hpp"
+#include "asio/detail/win_mutex.hpp"
+#include "asio/error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+win_mutex::win_mutex()
+{
+  int error = do_init();
+  asio::error_code ec(error,
+      asio::error::get_system_category());
+  asio::detail::throw_error(ec, "mutex");
+}
+
+int win_mutex::do_init()
+{
+#if defined(__MINGW32__)
+  // Not sure if MinGW supports structured exception handling, so for now
+  // we'll just call the Windows API and hope.
+# if defined(UNDER_CE)
+  ::InitializeCriticalSection(&crit_section_);
+# else
+  if (!::InitializeCriticalSectionAndSpinCount(&crit_section_, 0x80000000))
+    return ::GetLastError();
+# endif
+  return 0;
+#else
+  __try
+  {
+# if defined(UNDER_CE)
+    ::InitializeCriticalSection(&crit_section_);
+# else
+    if (!::InitializeCriticalSectionAndSpinCount(&crit_section_, 0x80000000))
+      return ::GetLastError();
+# endif
+  }
+  __except(GetExceptionCode() == STATUS_NO_MEMORY
+      ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
+  {
+    return ERROR_OUTOFMEMORY;
+  }
+
+  return 0;
+#endif
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(BOOST_WINDOWS)
+
+#endif // ASIO_DETAIL_IMPL_WIN_MUTEX_IPP
diff --git a/ext/asio/asio/detail/impl/win_thread.ipp b/ext/asio/asio/detail/impl/win_thread.ipp
new file mode 100644
index 0000000..65844c8
--- /dev/null
+++ b/ext/asio/asio/detail/impl/win_thread.ipp
@@ -0,0 +1,138 @@
+//
+// detail/impl/win_thread.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_IMPL_WIN_THREAD_IPP
+#define ASIO_DETAIL_IMPL_WIN_THREAD_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(BOOST_WINDOWS) && !defined(UNDER_CE)
+
+#include <process.h>
+#include "asio/detail/throw_error.hpp"
+#include "asio/detail/win_thread.hpp"
+#include "asio/error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+win_thread::~win_thread()
+{
+  ::CloseHandle(thread_);
+
+  // The exit_event_ handle is deliberately allowed to leak here since it
+  // is an error for the owner of an internal thread not to join() it.
+}
+
+void win_thread::join()
+{
+  HANDLE handles[2] = { exit_event_, thread_ };
+  ::WaitForMultipleObjects(2, handles, FALSE, INFINITE);
+  ::CloseHandle(exit_event_);
+  if (terminate_threads())
+  {
+    ::TerminateThread(thread_, 0);
+  }
+  else
+  {
+    ::QueueUserAPC(apc_function, thread_, 0);
+    ::WaitForSingleObject(thread_, INFINITE);
+  }
+}
+
+void win_thread::start_thread(func_base* arg, unsigned int stack_size)
+{
+  ::HANDLE entry_event = 0;
+  arg->entry_event_ = entry_event = ::CreateEvent(0, true, false, 0);
+  if (!entry_event)
+  {
+    DWORD last_error = ::GetLastError();
+    delete arg;
+    asio::error_code ec(last_error,
+        asio::error::get_system_category());
+    asio::detail::throw_error(ec, "thread.entry_event");
+  }
+
+  arg->exit_event_ = exit_event_ = ::CreateEvent(0, true, false, 0);
+  if (!exit_event_)
+  {
+    DWORD last_error = ::GetLastError();
+    delete arg;
+    asio::error_code ec(last_error,
+        asio::error::get_system_category());
+    asio::detail::throw_error(ec, "thread.exit_event");
+  }
+
+  unsigned int thread_id = 0;
+  thread_ = reinterpret_cast<HANDLE>(::_beginthreadex(0,
+        stack_size, win_thread_function, arg, 0, &thread_id));
+  if (!thread_)
+  {
+    DWORD last_error = ::GetLastError();
+    delete arg;
+    if (entry_event)
+      ::CloseHandle(entry_event);
+    if (exit_event_)
+      ::CloseHandle(exit_event_);
+    asio::error_code ec(last_error,
+        asio::error::get_system_category());
+    asio::detail::throw_error(ec, "thread");
+  }
+
+  if (entry_event)
+  {
+    ::WaitForSingleObject(entry_event, INFINITE);
+    ::CloseHandle(entry_event);
+  }
+}
+
+unsigned int __stdcall win_thread_function(void* arg)
+{
+  std::auto_ptr<win_thread::func_base> func(
+      static_cast<win_thread::func_base*>(arg));
+
+  ::SetEvent(func->entry_event_);
+
+  func->run();
+
+  // Signal that the thread has finished its work, but rather than returning go
+  // to sleep to put the thread into a well known state. If the thread is being
+  // joined during global object destruction then it may be killed using
+  // TerminateThread (to avoid a deadlock in DllMain). Otherwise, the SleepEx
+  // call will be interrupted using QueueUserAPC and the thread will shut down
+  // cleanly.
+  HANDLE exit_event = func->exit_event_;
+  func.reset();
+  ::SetEvent(exit_event);
+  ::SleepEx(INFINITE, TRUE);
+
+  return 0;
+}
+
+#if defined(WINVER) && (WINVER < 0x0500)
+void __stdcall apc_function(ULONG) {}
+#else
+void __stdcall apc_function(ULONG_PTR) {}
+#endif
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(BOOST_WINDOWS) && !defined(UNDER_CE)
+
+#endif // ASIO_DETAIL_IMPL_WIN_THREAD_IPP
diff --git a/ext/asio/asio/detail/impl/win_tss_ptr.ipp b/ext/asio/asio/detail/impl/win_tss_ptr.ipp
new file mode 100644
index 0000000..de3ea3c
--- /dev/null
+++ b/ext/asio/asio/detail/impl/win_tss_ptr.ipp
@@ -0,0 +1,57 @@
+//
+// detail/impl/win_tss_ptr.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_IMPL_WIN_TSS_PTR_IPP
+#define ASIO_DETAIL_IMPL_WIN_TSS_PTR_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(BOOST_WINDOWS)
+
+#include "asio/detail/throw_error.hpp"
+#include "asio/detail/win_tss_ptr.hpp"
+#include "asio/error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+DWORD win_tss_ptr_create()
+{
+#if defined(UNDER_CE)
+  enum { out_of_indexes = 0xFFFFFFFF };
+#else
+  enum { out_of_indexes = TLS_OUT_OF_INDEXES };
+#endif
+
+  DWORD tss_key = ::TlsAlloc();
+  if (tss_key == out_of_indexes)
+  {
+    DWORD last_error = ::GetLastError();
+    asio::error_code ec(last_error,
+        asio::error::get_system_category());
+    asio::detail::throw_error(ec, "tss");
+  }
+  return tss_key;
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(BOOST_WINDOWS)
+
+#endif // ASIO_DETAIL_IMPL_WIN_TSS_PTR_IPP
diff --git a/ext/asio/asio/detail/impl/winsock_init.ipp b/ext/asio/asio/detail/impl/winsock_init.ipp
new file mode 100644
index 0000000..3b20c98
--- /dev/null
+++ b/ext/asio/asio/detail/impl/winsock_init.ipp
@@ -0,0 +1,69 @@
+//
+// detail/impl/winsock_init.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_IMPL_WINSOCK_INIT_IPP
+#define ASIO_DETAIL_IMPL_WINSOCK_INIT_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+
+#include "asio/detail/socket_types.hpp"
+#include "asio/detail/winsock_init.hpp"
+#include "asio/detail/throw_error.hpp"
+#include "asio/error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+void winsock_init_base::startup(data& d,
+    unsigned char major, unsigned char minor)
+{
+  if (::InterlockedIncrement(&d.init_count_) == 1)
+  {
+    WSADATA wsa_data;
+    long result = ::WSAStartup(MAKEWORD(major, minor), &wsa_data);
+    ::InterlockedExchange(&d.result_, result);
+  }
+}
+
+void winsock_init_base::cleanup(data& d)
+{
+  if (::InterlockedDecrement(&d.init_count_) == 0)
+  {
+    ::WSACleanup();
+  }
+}
+
+void winsock_init_base::throw_on_error(data& d)
+{
+  long result = ::InterlockedExchangeAdd(&d.result_, 0);
+  if (result != 0)
+  {
+    asio::error_code ec(result,
+        asio::error::get_system_category());
+    asio::detail::throw_error(ec, "winsock");
+  }
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+
+#endif // ASIO_DETAIL_IMPL_WINSOCK_INIT_IPP
diff --git a/ext/asio/asio/detail/io_control.hpp b/ext/asio/asio/detail/io_control.hpp
index df7171c..b3ef844 100644
--- a/ext/asio/asio/detail/io_control.hpp
+++ b/ext/asio/asio/detail/io_control.hpp
@@ -1,8 +1,8 @@
 //
-// io_control.hpp
-// ~~~~~~~~~~~~~~
+// detail/io_control.hpp
+// ~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,15 +15,13 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 #include <cstddef>
 #include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
-
 #include "asio/detail/socket_types.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 namespace detail {
 namespace io_control {
diff --git a/ext/asio/asio/detail/kqueue_reactor.hpp b/ext/asio/asio/detail/kqueue_reactor.hpp
index bfa004d..07087dd 100644
--- a/ext/asio/asio/detail/kqueue_reactor.hpp
+++ b/ext/asio/asio/detail/kqueue_reactor.hpp
@@ -1,8 +1,8 @@
 //
-// kqueue_reactor.hpp
-// ~~~~~~~~~~~~~~~~~~
+// detail/kqueue_reactor.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 // Copyright (c) 2005 Stefan Arentz (stefan at soze dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
@@ -16,41 +16,35 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/kqueue_reactor_fwd.hpp"
+#include "asio/detail/config.hpp"
 
 #if defined(ASIO_HAS_KQUEUE)
 
-#include "asio/detail/push_options.hpp"
 #include <cstddef>
 #include <sys/types.h>
 #include <sys/event.h>
 #include <sys/time.h>
-#include <boost/config.hpp>
-#include <boost/throw_exception.hpp>
-#include "asio/detail/pop_options.hpp"
-
-#include "asio/error.hpp"
-#include "asio/io_service.hpp"
-#include "asio/system_error.hpp"
-#include "asio/detail/hash_map.hpp"
+#include "asio/detail/kqueue_reactor_fwd.hpp"
 #include "asio/detail/mutex.hpp"
+#include "asio/detail/object_pool.hpp"
 #include "asio/detail/op_queue.hpp"
 #include "asio/detail/reactor_op.hpp"
 #include "asio/detail/select_interrupter.hpp"
-#include "asio/detail/service_base.hpp"
 #include "asio/detail/socket_types.hpp"
 #include "asio/detail/timer_op.hpp"
 #include "asio/detail/timer_queue_base.hpp"
 #include "asio/detail/timer_queue_fwd.hpp"
 #include "asio/detail/timer_queue_set.hpp"
+#include "asio/error.hpp"
+#include "asio/io_service.hpp"
 
 // Older versions of Mac OS X may not define EV_OOBAND.
 #if !defined(EV_OOBAND)
 # define EV_OOBAND EV_FLAG1
 #endif // !defined(EV_OOBAND)
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 namespace detail {
 
@@ -64,384 +58,98 @@ public:
   // Per-descriptor queues.
   struct descriptor_state
   {
-    descriptor_state() {}
-    descriptor_state(const descriptor_state&) {}
-    void operator=(const descriptor_state&) {}
-
+    friend class kqueue_reactor;
+    friend class object_pool_access;
     mutex mutex_;
     op_queue<reactor_op> op_queue_[max_ops];
     bool shutdown_;
+    descriptor_state* next_;
+    descriptor_state* prev_;
   };
 
   // Per-descriptor data.
   typedef descriptor_state* per_descriptor_data;
 
   // Constructor.
-  kqueue_reactor(asio::io_service& io_service)
-    : asio::detail::service_base<kqueue_reactor>(io_service),
-      io_service_(use_service<io_service_impl>(io_service)),
-      mutex_(),
-      kqueue_fd_(do_kqueue_create()),
-      interrupter_(),
-      shutdown_(false)
-  {
-    // The interrupter is put into a permanently readable state. Whenever we
-    // want to interrupt the blocked kevent call we register a one-shot read
-    // operation against the descriptor.
-    interrupter_.interrupt();
-  }
+  ASIO_DECL kqueue_reactor(asio::io_service& io_service);
 
   // Destructor.
-  ~kqueue_reactor()
-  {
-    close(kqueue_fd_);
-  }
+  ASIO_DECL ~kqueue_reactor();
 
   // Destroy all user-defined handler objects owned by the service.
-  void shutdown_service()
-  {
-    mutex::scoped_lock lock(mutex_);
-    shutdown_ = true;
-    lock.unlock();
-
-    op_queue<operation> ops;
-
-    descriptor_map::iterator iter = registered_descriptors_.begin();
-    descriptor_map::iterator end = registered_descriptors_.end();
-    while (iter != end)
-    {
-      for (int i = 0; i < max_ops; ++i)
-        ops.push(iter->second.op_queue_[i]);
-      iter->second.shutdown_ = true;
-      ++iter;
-    }
-
-    timer_queues_.get_all_timers(ops);
-  }
+  ASIO_DECL void shutdown_service();
 
   // Initialise the task.
-  void init_task()
-  {
-    io_service_.init_task();
-  }
+  ASIO_DECL void init_task();
 
   // Register a socket with the reactor. Returns 0 on success, system error
   // code on failure.
-  int register_descriptor(socket_type descriptor,
-      per_descriptor_data& descriptor_data)
-  {
-    mutex::scoped_lock lock(registered_descriptors_mutex_);
-
-    descriptor_map::iterator new_entry = registered_descriptors_.insert(
-          std::make_pair(descriptor, descriptor_state())).first;
-    descriptor_data = &new_entry->second;
+  ASIO_DECL int register_descriptor(socket_type descriptor,
+      per_descriptor_data& descriptor_data);
 
-    descriptor_data->shutdown_ = false;
-
-    return 0;
+  // Post a reactor operation for immediate completion.
+  void post_immediate_completion(reactor_op* op)
+  {
+    io_service_.post_immediate_completion(op);
   }
 
   // Start a new operation. The reactor operation will be performed when the
   // given descriptor is flagged as ready, or an error has occurred.
-  void start_op(int op_type, socket_type descriptor,
+  ASIO_DECL void start_op(int op_type, socket_type descriptor,
       per_descriptor_data& descriptor_data,
-      reactor_op* op, bool allow_speculative)
-  {
-    mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
-    if (descriptor_data->shutdown_)
-      return;
-
-    bool first = descriptor_data->op_queue_[op_type].empty();
-    if (first)
-    {
-      if (allow_speculative)
-      {
-        if (op_type != read_op || descriptor_data->op_queue_[except_op].empty())
-        {
-          if (op->perform())
-          {
-            descriptor_lock.unlock();
-            io_service_.post_immediate_completion(op);
-            return;
-          }
-        }
-      }
-    }
-
-    descriptor_data->op_queue_[op_type].push(op);
-    io_service_.work_started();
-
-    if (first)
-    {
-      struct kevent event;
-      switch (op_type)
-      {
-      case read_op:
-        EV_SET(&event, descriptor, EVFILT_READ,
-            EV_ADD | EV_ONESHOT, 0, 0, descriptor_data);
-        break;
-      case write_op:
-        EV_SET(&event, descriptor, EVFILT_WRITE,
-            EV_ADD | EV_ONESHOT, 0, 0, descriptor_data);
-        break;
-      case except_op:
-        if (!descriptor_data->op_queue_[read_op].empty())
-          return; // Already registered for read events.
-        EV_SET(&event, descriptor, EVFILT_READ,
-            EV_ADD | EV_ONESHOT, EV_OOBAND, 0, descriptor_data);
-        break;
-      }
-
-      if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1)
-      {
-        op->ec_ = asio::error_code(errno,
-            asio::error::get_system_category());
-        descriptor_data->op_queue_[op_type].pop();
-        io_service_.post_deferred_completion(op);
-      }
-    }
-  }
+      reactor_op* op, bool allow_speculative);
 
   // Cancel all operations associated with the given descriptor. The
   // handlers associated with the descriptor will be invoked with the
   // operation_aborted error.
-  void cancel_ops(socket_type , per_descriptor_data& descriptor_data)
-  {
-    mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
-
-    op_queue<operation> ops;
-    for (int i = 0; i < max_ops; ++i)
-    {
-      while (reactor_op* op = descriptor_data->op_queue_[i].front())
-      {
-        op->ec_ = asio::error::operation_aborted;
-        descriptor_data->op_queue_[i].pop();
-        ops.push(op);
-      }
-    }
-
-    descriptor_lock.unlock();
-
-    io_service_.post_deferred_completions(ops);
-  }
+  ASIO_DECL void cancel_ops(socket_type descriptor,
+      per_descriptor_data& descriptor_data);
 
   // Cancel any operations that are running against the descriptor and remove
   // its registration from the reactor.
-  void close_descriptor(socket_type descriptor,
-      per_descriptor_data& descriptor_data)
-  {
-    mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
-    mutex::scoped_lock descriptors_lock(registered_descriptors_mutex_);
-
-    // Remove the descriptor from the set of known descriptors. The descriptor
-    // will be automatically removed from the kqueue set when it is closed.
-    descriptor_data->shutdown_ = true;
-
-    op_queue<operation> ops;
-    for (int i = 0; i < max_ops; ++i)
-    {
-      while (reactor_op* op = descriptor_data->op_queue_[i].front())
-      {
-        op->ec_ = asio::error::operation_aborted;
-        descriptor_data->op_queue_[i].pop();
-        ops.push(op);
-      }
-    }
-
-    descriptor_lock.unlock();
-
-    registered_descriptors_.erase(descriptor);
-
-    descriptors_lock.unlock();
-
-    io_service_.post_deferred_completions(ops);
-  }
+  ASIO_DECL void close_descriptor(socket_type descriptor,
+      per_descriptor_data& descriptor_data);
 
   // Add a new timer queue to the reactor.
   template <typename Time_Traits>
-  void add_timer_queue(timer_queue<Time_Traits>& timer_queue)
-  {
-    mutex::scoped_lock lock(mutex_);
-    timer_queues_.insert(&timer_queue);
-  }
+  void add_timer_queue(timer_queue<Time_Traits>& queue);
 
   // Remove a timer queue from the reactor.
   template <typename Time_Traits>
-  void remove_timer_queue(timer_queue<Time_Traits>& timer_queue)
-  {
-    mutex::scoped_lock lock(mutex_);
-    timer_queues_.erase(&timer_queue);
-  }
+  void remove_timer_queue(timer_queue<Time_Traits>& queue);
 
   // Schedule a new operation in the given timer queue to expire at the
   // specified absolute time.
   template <typename Time_Traits>
-  void schedule_timer(timer_queue<Time_Traits>& timer_queue,
-      const typename Time_Traits::time_type& time, timer_op* op, void* token)
-  {
-    mutex::scoped_lock lock(mutex_);
-    if (!shutdown_)
-    {
-      bool earliest = timer_queue.enqueue_timer(time, op, token);
-      io_service_.work_started();
-      if (earliest)
-        interrupt();
-    }
-  }
+  void schedule_timer(timer_queue<Time_Traits>& queue,
+      const typename Time_Traits::time_type& time,
+      typename timer_queue<Time_Traits>::per_timer_data& timer, timer_op* op);
 
   // Cancel the timer operations associated with the given token. Returns the
   // number of operations that have been posted or dispatched.
   template <typename Time_Traits>
-  std::size_t cancel_timer(timer_queue<Time_Traits>& timer_queue, void* token)
-  {
-    mutex::scoped_lock lock(mutex_);
-    op_queue<operation> ops;
-    std::size_t n = timer_queue.cancel_timer(token, ops);
-    lock.unlock();
-    io_service_.post_deferred_completions(ops);
-    return n;
-  }
+  std::size_t cancel_timer(timer_queue<Time_Traits>& queue,
+      typename timer_queue<Time_Traits>::per_timer_data& timer);
 
   // Run the kqueue loop.
-  void run(bool block, op_queue<operation>& ops)
-  {
-    mutex::scoped_lock lock(mutex_);
-
-    // Determine how long to block while waiting for events.
-    timespec timeout_buf = { 0, 0 };
-    timespec* timeout = block ? get_timeout(timeout_buf) : &timeout_buf;
-
-    lock.unlock();
-
-    // Block on the kqueue descriptor.
-    struct kevent events[128];
-    int num_events = kevent(kqueue_fd_, 0, 0, events, 128, timeout);
-
-    // Dispatch the waiting events.
-    for (int i = 0; i < num_events; ++i)
-    {
-      int descriptor = events[i].ident;
-      void* ptr = events[i].udata;
-      if (ptr == &interrupter_)
-      {
-        // No need to reset the interrupter since we're leaving the descriptor
-        // in a ready-to-read state and relying on one-shot notifications.
-      }
-      else
-      {
-        descriptor_state* descriptor_data = static_cast<descriptor_state*>(ptr);
-        mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
-
-        // Exception operations must be processed first to ensure that any
-        // out-of-band data is read before normal data.
-        static const int filter[max_ops] =
-          { EVFILT_READ, EVFILT_WRITE, EVFILT_READ };
-        for (int j = max_ops - 1; j >= 0; --j)
-        {
-          if (events[i].filter == filter[j])
-          {
-            if (j != except_op || events[i].flags & EV_OOBAND)
-            {
-              while (reactor_op* op = descriptor_data->op_queue_[j].front())
-              {
-                if (events[i].flags & EV_ERROR)
-                {
-                  op->ec_ = asio::error_code(events[i].data,
-                      asio::error::get_system_category());
-                  descriptor_data->op_queue_[j].pop();
-                  ops.push(op);
-                }
-                if (op->perform())
-                {
-                  descriptor_data->op_queue_[j].pop();
-                  ops.push(op);
-                }
-                else
-                  break;
-              }
-            }
-          }
-        }
-
-        // Renew registration for event notifications.
-        struct kevent event;
-        switch (events[i].filter)
-        {
-        case EVFILT_READ:
-          if (!descriptor_data->op_queue_[read_op].empty())
-            EV_SET(&event, descriptor, EVFILT_READ,
-                EV_ADD | EV_ONESHOT, 0, 0, descriptor_data);
-          else if (!descriptor_data->op_queue_[except_op].empty())
-            EV_SET(&event, descriptor, EVFILT_READ,
-                EV_ADD | EV_ONESHOT, EV_OOBAND, 0, descriptor_data);
-          else
-            continue;
-        case EVFILT_WRITE:
-          if (!descriptor_data->op_queue_[write_op].empty())
-            EV_SET(&event, descriptor, EVFILT_WRITE,
-                EV_ADD | EV_ONESHOT, 0, 0, descriptor_data);
-          else
-            continue;
-        default:
-          break;
-        }
-        if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1)
-        {
-          asio::error_code error(errno,
-              asio::error::get_system_category());
-          for (int j = 0; j < max_ops; ++j)
-          {
-            while (reactor_op* op = descriptor_data->op_queue_[j].front())
-            {
-              op->ec_ = error;
-              descriptor_data->op_queue_[j].pop();
-              ops.push(op);
-            }
-          }
-        }
-      }
-    }
-
-    lock.lock();
-    timer_queues_.get_ready_timers(ops);
-  }
+  ASIO_DECL void run(bool block, op_queue<operation>& ops);
 
   // Interrupt the kqueue loop.
-  void interrupt()
-  {
-    struct kevent event;
-    EV_SET(&event, interrupter_.read_descriptor(),
-        EVFILT_READ, EV_ADD | EV_ONESHOT, 0, 0, &interrupter_);
-    ::kevent(kqueue_fd_, &event, 1, 0, 0, 0);
-  }
+  ASIO_DECL void interrupt();
 
 private:
   // Create the kqueue file descriptor. Throws an exception if the descriptor
   // cannot be created.
-  static int do_kqueue_create()
-  {
-    int fd = kqueue();
-    if (fd == -1)
-    {
-      boost::throw_exception(
-          asio::system_error(
-            asio::error_code(errno,
-              asio::error::get_system_category()),
-            "kqueue"));
-    }
-    return fd;
-  }
+  ASIO_DECL static int do_kqueue_create();
+
+  // Helper function to add a new timer queue.
+  ASIO_DECL void do_add_timer_queue(timer_queue_base& queue);
+
+  // Helper function to remove a timer queue.
+  ASIO_DECL void do_remove_timer_queue(timer_queue_base& queue);
 
   // Get the timeout value for the kevent call.
-  timespec* get_timeout(timespec& ts)
-  {
-    // By default we will wait no longer than 5 minutes. This will ensure that
-    // any changes to the system clock are detected after no longer than this.
-    long usec = timer_queues_.wait_duration_usec(5 * 60 * 1000 * 1000);
-    ts.tv_sec = usec / 1000000;
-    ts.tv_nsec = (usec % 1000000) * 1000;
-    return &ts;
-  }
+  ASIO_DECL timespec* get_timeout(timespec& ts);
 
   // The io_service implementation used to post completions.
   io_service_impl& io_service_;
@@ -464,22 +172,20 @@ private:
   // Mutex to protect access to the registered descriptors.
   mutex registered_descriptors_mutex_;
 
-  // Keep track of all registered descriptors. This code relies on the fact that
-  // the hash_map implementation pools deleted nodes, meaning that we can assume
-  // our descriptor_state pointer remains valid even after the entry is removed.
-  // Technically this is not true for C++98, as that standard says that spliced
-  // elements in a list are invalidated. However, C++0x fixes this shortcoming
-  // so we'll just assume that C++98 std::list implementations will do the right
-  // thing anyway.
-  typedef detail::hash_map<socket_type, descriptor_state> descriptor_map;
-  descriptor_map registered_descriptors_;
+  // Keep track of all registered descriptors.
+  object_pool<descriptor_state> registered_descriptors_;
 };
 
 } // namespace detail
 } // namespace asio
 
-#endif // defined(ASIO_HAS_KQUEUE)
-
 #include "asio/detail/pop_options.hpp"
 
+#include "asio/detail/impl/kqueue_reactor.hpp"
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/detail/impl/kqueue_reactor.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
+#endif // defined(ASIO_HAS_KQUEUE)
+
 #endif // ASIO_DETAIL_KQUEUE_REACTOR_HPP
diff --git a/ext/asio/asio/detail/kqueue_reactor_fwd.hpp b/ext/asio/asio/detail/kqueue_reactor_fwd.hpp
index abbc0c7..fda59ce 100644
--- a/ext/asio/asio/detail/kqueue_reactor_fwd.hpp
+++ b/ext/asio/asio/detail/kqueue_reactor_fwd.hpp
@@ -1,8 +1,8 @@
 //
-// kqueue_reactor_fwd.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~
+// detail/kqueue_reactor_fwd.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 // Copyright (c) 2005 Stefan Arentz (stefan at soze dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
@@ -16,15 +16,9 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 
-#if !defined(ASIO_DISABLE_KQUEUE)
-
-#if (defined(__MACH__) && defined(__APPLE__)) \
-  || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
-
-// Define this to indicate that kqueue is supported on the target platform.
-#define ASIO_HAS_KQUEUE 1
+#if defined(ASIO_HAS_KQUEUE)
 
 namespace asio {
 namespace detail {
@@ -34,11 +28,6 @@ class kqueue_reactor;
 } // namespace detail
 } // namespace asio
 
-#endif // (defined(__MACH__) && defined(__APPLE__))
-       // || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
-
-#endif // !defined(ASIO_DISABLE_KQUEUE)
-
-#include "asio/detail/pop_options.hpp"
+#endif // defined(ASIO_HAS_KQUEUE)
 
 #endif // ASIO_DETAIL_KQUEUE_REACTOR_FWD_HPP
diff --git a/ext/asio/asio/detail/local_free_on_block_exit.hpp b/ext/asio/asio/detail/local_free_on_block_exit.hpp
index 554943c..a55bd4b 100644
--- a/ext/asio/asio/detail/local_free_on_block_exit.hpp
+++ b/ext/asio/asio/detail/local_free_on_block_exit.hpp
@@ -1,8 +1,8 @@
 //
-// local_free_on_block_exit.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// detail/local_free_on_block_exit.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,17 +15,15 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
+#include "asio/detail/config.hpp"
 
 #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
 
 #include "asio/detail/noncopyable.hpp"
 #include "asio/detail/socket_types.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 namespace detail {
 
@@ -52,8 +50,8 @@ private:
 } // namespace detail
 } // namespace asio
 
-#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-
 #include "asio/detail/pop_options.hpp"
 
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+
 #endif // ASIO_DETAIL_LOCAL_FREE_ON_BLOCK_EXIT_HPP
diff --git a/ext/asio/asio/detail/macos_fenced_block.hpp b/ext/asio/asio/detail/macos_fenced_block.hpp
index 3c303d6..fcb8bfc 100644
--- a/ext/asio/asio/detail/macos_fenced_block.hpp
+++ b/ext/asio/asio/detail/macos_fenced_block.hpp
@@ -1,8 +1,8 @@
 //
-// macos_fenced_block.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~
+// detail/macos_fenced_block.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,17 +15,13 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
+#include "asio/detail/config.hpp"
 
 #if defined(__MACH__) && defined(__APPLE__)
 
-#include "asio/detail/push_options.hpp"
 #include <libkern/OSAtomic.h>
-#include "asio/detail/pop_options.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 namespace detail {
@@ -50,8 +46,8 @@ public:
 } // namespace detail
 } // namespace asio
 
-#endif // defined(__MACH__) && defined(__APPLE__)
-
 #include "asio/detail/pop_options.hpp"
 
+#endif // defined(__MACH__) && defined(__APPLE__)
+
 #endif // ASIO_DETAIL_MACOS_FENCED_BLOCK_HPP
diff --git a/ext/asio/asio/detail/mutex.hpp b/ext/asio/asio/detail/mutex.hpp
index 024ec7f..dc478ff 100644
--- a/ext/asio/asio/detail/mutex.hpp
+++ b/ext/asio/asio/detail/mutex.hpp
@@ -1,8 +1,8 @@
 //
-// mutex.hpp
-// ~~~~~~~~~
+// detail/mutex.hpp
+// ~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,11 +15,7 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
+#include "asio/detail/config.hpp"
 
 #if !defined(BOOST_HAS_THREADS) || defined(ASIO_DISABLE_THREADS)
 # include "asio/detail/null_mutex.hpp"
@@ -45,6 +41,4 @@ typedef posix_mutex mutex;
 } // namespace detail
 } // namespace asio
 
-#include "asio/detail/pop_options.hpp"
-
 #endif // ASIO_DETAIL_MUTEX_HPP
diff --git a/ext/asio/asio/detail/noncopyable.hpp b/ext/asio/asio/detail/noncopyable.hpp
index 8b73ff0..e7f6437 100644
--- a/ext/asio/asio/detail/noncopyable.hpp
+++ b/ext/asio/asio/detail/noncopyable.hpp
@@ -1,8 +1,8 @@
 //
-// noncopyable.hpp
-// ~~~~~~~~~~~~~~~
+// detail/noncopyable.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,13 +15,11 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
+#include "asio/detail/config.hpp"
 #include <boost/noncopyable.hpp>
 #include <boost/detail/workaround.hpp>
-#include "asio/detail/pop_options.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 namespace detail {
diff --git a/ext/asio/asio/detail/null_event.hpp b/ext/asio/asio/detail/null_event.hpp
index bcea31b..db7b747 100644
--- a/ext/asio/asio/detail/null_event.hpp
+++ b/ext/asio/asio/detail/null_event.hpp
@@ -1,8 +1,8 @@
 //
-// null_event.hpp
-// ~~~~~~~~~~~~~~
+// detail/null_event.hpp
+// ~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,16 +15,14 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
+#include "asio/detail/config.hpp"
 
 #if !defined(BOOST_HAS_THREADS) || defined(ASIO_DISABLE_THREADS)
 
 #include "asio/detail/noncopyable.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 namespace detail {
 
@@ -70,8 +68,8 @@ public:
 } // namespace detail
 } // namespace asio
 
-#endif // !defined(BOOST_HAS_THREADS) || defined(ASIO_DISABLE_THREADS)
-
 #include "asio/detail/pop_options.hpp"
 
+#endif // !defined(BOOST_HAS_THREADS) || defined(ASIO_DISABLE_THREADS)
+
 #endif // ASIO_DETAIL_NULL_EVENT_HPP
diff --git a/ext/asio/asio/detail/null_fenced_block.hpp b/ext/asio/asio/detail/null_fenced_block.hpp
index dd9a095..fbd025f 100644
--- a/ext/asio/asio/detail/null_fenced_block.hpp
+++ b/ext/asio/asio/detail/null_fenced_block.hpp
@@ -1,8 +1,8 @@
 //
-// null_fenced_block.hpp
-// ~~~~~~~~~~~~~~~~~~~~~
+// detail/null_fenced_block.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/ext/asio/asio/detail/null_mutex.hpp b/ext/asio/asio/detail/null_mutex.hpp
index 6661ef8..bbceb7c 100644
--- a/ext/asio/asio/detail/null_mutex.hpp
+++ b/ext/asio/asio/detail/null_mutex.hpp
@@ -1,8 +1,8 @@
 //
-// null_mutex.hpp
-// ~~~~~~~~~~~~~~
+// detail/null_mutex.hpp
+// ~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,17 +15,15 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
+#include "asio/detail/config.hpp"
 
 #if !defined(BOOST_HAS_THREADS) || defined(ASIO_DISABLE_THREADS)
 
 #include "asio/detail/noncopyable.hpp"
 #include "asio/detail/scoped_lock.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 namespace detail {
 
@@ -59,8 +57,8 @@ public:
 } // namespace detail
 } // namespace asio
 
-#endif // !defined(BOOST_HAS_THREADS) || defined(ASIO_DISABLE_THREADS)
-
 #include "asio/detail/pop_options.hpp"
 
+#endif // !defined(BOOST_HAS_THREADS) || defined(ASIO_DISABLE_THREADS)
+
 #endif // ASIO_DETAIL_NULL_MUTEX_HPP
diff --git a/ext/asio/asio/detail/null_signal_blocker.hpp b/ext/asio/asio/detail/null_signal_blocker.hpp
index a5db315..e0d996f 100644
--- a/ext/asio/asio/detail/null_signal_blocker.hpp
+++ b/ext/asio/asio/detail/null_signal_blocker.hpp
@@ -1,8 +1,8 @@
 //
-// null_signal_blocker.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~
+// detail/null_signal_blocker.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,16 +15,18 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
+#include "asio/detail/config.hpp"
 
-#if !defined(BOOST_HAS_THREADS) || defined(ASIO_DISABLE_THREADS)
+#if !defined(BOOST_HAS_THREADS) \
+  || defined(ASIO_DISABLE_THREADS) \
+  || defined(BOOST_WINDOWS) \
+  || defined(__CYGWIN__) \
+  || defined(__SYMBIAN32__)
 
 #include "asio/detail/noncopyable.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 namespace detail {
 
@@ -56,8 +58,12 @@ public:
 } // namespace detail
 } // namespace asio
 
-#endif // !defined(BOOST_HAS_THREADS) || defined(ASIO_DISABLE_THREADS)
-
 #include "asio/detail/pop_options.hpp"
 
+#endif // !defined(BOOST_HAS_THREADS)
+       // || defined(ASIO_DISABLE_THREADS)
+       // || defined(BOOST_WINDOWS)
+       // || defined(__CYGWIN__)
+       // || defined(__SYMBIAN32__)
+
 #endif // ASIO_DETAIL_NULL_SIGNAL_BLOCKER_HPP
diff --git a/ext/asio/asio/detail/null_thread.hpp b/ext/asio/asio/detail/null_thread.hpp
index ce3d470..bfe918e 100644
--- a/ext/asio/asio/detail/null_thread.hpp
+++ b/ext/asio/asio/detail/null_thread.hpp
@@ -1,8 +1,8 @@
 //
-// null_thread.hpp
-// ~~~~~~~~~~~~~~~
+// detail/null_thread.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,21 +15,15 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
+#include "asio/detail/config.hpp"
 
 #if !defined(BOOST_HAS_THREADS) || defined(ASIO_DISABLE_THREADS)
 
-#include "asio/detail/push_options.hpp"
-#include <boost/throw_exception.hpp>
-#include "asio/detail/pop_options.hpp"
-
-#include "asio/error.hpp"
-#include "asio/system_error.hpp"
 #include "asio/detail/noncopyable.hpp"
+#include "asio/detail/throw_error.hpp"
+#include "asio/error.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 namespace detail {
@@ -40,11 +34,10 @@ class null_thread
 public:
   // Constructor.
   template <typename Function>
-  null_thread(Function )
+  null_thread(Function, unsigned int = 0)
   {
-    asio::system_error e(
+    asio::detail::throw_error(
         asio::error::operation_not_supported, "thread");
-    boost::throw_exception(e);
   }
 
   // Destructor.
@@ -61,8 +54,8 @@ public:
 } // namespace detail
 } // namespace asio
 
-#endif // !defined(BOOST_HAS_THREADS) || defined(ASIO_DISABLE_THREADS)
-
 #include "asio/detail/pop_options.hpp"
 
+#endif // !defined(BOOST_HAS_THREADS) || defined(ASIO_DISABLE_THREADS)
+
 #endif // ASIO_DETAIL_NULL_THREAD_HPP
diff --git a/ext/asio/asio/detail/null_tss_ptr.hpp b/ext/asio/asio/detail/null_tss_ptr.hpp
index 112b476..d3456e6 100644
--- a/ext/asio/asio/detail/null_tss_ptr.hpp
+++ b/ext/asio/asio/detail/null_tss_ptr.hpp
@@ -1,8 +1,8 @@
 //
-// null_tss_ptr.hpp
-// ~~~~~~~~~~~~~~~~
+// detail/null_tss_ptr.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,16 +15,14 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
+#include "asio/detail/config.hpp"
 
 #if !defined(BOOST_HAS_THREADS) || defined(ASIO_DISABLE_THREADS)
 
 #include "asio/detail/noncopyable.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 namespace detail {
 
@@ -63,8 +61,8 @@ private:
 } // namespace detail
 } // namespace asio
 
-#endif // !defined(BOOST_HAS_THREADS) || defined(ASIO_DISABLE_THREADS)
-
 #include "asio/detail/pop_options.hpp"
 
+#endif // !defined(BOOST_HAS_THREADS) || defined(ASIO_DISABLE_THREADS)
+
 #endif // ASIO_DETAIL_NULL_TSS_PTR_HPP
diff --git a/ext/asio/asio/detail/object_pool.hpp b/ext/asio/asio/detail/object_pool.hpp
new file mode 100644
index 0000000..dc50feb
--- /dev/null
+++ b/ext/asio/asio/detail/object_pool.hpp
@@ -0,0 +1,146 @@
+//
+// detail/object_pool.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_OBJECT_POOL_HPP
+#define ASIO_DETAIL_OBJECT_POOL_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/noncopyable.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename Object>
+class object_pool;
+
+class object_pool_access
+{
+public:
+  template <typename Object>
+  static Object* create()
+  {
+    return new Object;
+  }
+
+  template <typename Object>
+  static void destroy(Object* o)
+  {
+    delete o;
+  }
+
+  template <typename Object>
+  static Object*& next(Object* o)
+  {
+    return o->next_;
+  }
+
+  template <typename Object>
+  static Object*& prev(Object* o)
+  {
+    return o->prev_;
+  }
+};
+
+template <typename Object>
+class object_pool
+  : private noncopyable
+{
+public:
+  // Constructor.
+  object_pool()
+    : live_list_(0),
+      free_list_(0)
+  {
+  }
+
+  // Destructor destroys all objects.
+  ~object_pool()
+  {
+    destroy_list(live_list_);
+    destroy_list(free_list_);
+  }
+
+  // Get the object at the start of the live list.
+  Object* first()
+  {
+    return live_list_;
+  }
+
+  // Allocate a new object.
+  Object* alloc()
+  {
+    Object* o = free_list_;
+    if (o)
+      free_list_ = object_pool_access::next(free_list_);
+    else
+      o = object_pool_access::create<Object>();
+
+    object_pool_access::next(o) = live_list_;
+    object_pool_access::prev(o) = 0;
+    if (live_list_)
+      object_pool_access::prev(live_list_) = o;
+    live_list_ = o;
+
+    return o;
+  }
+
+  // Free an object. Moves it to the free list. No destructors are run.
+  void free(Object* o)
+  {
+    if (live_list_ == o)
+      live_list_ = object_pool_access::next(o);
+
+    if (object_pool_access::prev(o))
+    {
+      object_pool_access::next(object_pool_access::prev(o))
+        = object_pool_access::next(o);
+    }
+
+    if (object_pool_access::next(o))
+    {
+      object_pool_access::prev(object_pool_access::next(o))
+        = object_pool_access::prev(o);
+    }
+
+    object_pool_access::next(o) = free_list_;
+    object_pool_access::prev(o) = 0;
+    free_list_ = o;
+  }
+
+private:
+  // Helper function to destroy all elements in a list.
+  void destroy_list(Object* list)
+  {
+    while (list)
+    {
+      Object* o = list;
+      list = object_pool_access::next(o);
+      object_pool_access::destroy(o);
+    }
+  }
+
+  // The list of live objects.
+  Object* live_list_;
+
+  // The free list.
+  Object* free_list_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_OBJECT_POOL_HPP
diff --git a/ext/asio/asio/detail/old_win_sdk_compat.hpp b/ext/asio/asio/detail/old_win_sdk_compat.hpp
index 70e5916..fb75579 100644
--- a/ext/asio/asio/detail/old_win_sdk_compat.hpp
+++ b/ext/asio/asio/detail/old_win_sdk_compat.hpp
@@ -1,8 +1,8 @@
 //
-// old_win_sdk_compat.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~
+// detail/old_win_sdk_compat.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,11 +15,7 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
+#include "asio/detail/config.hpp"
 
 #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
 
@@ -36,6 +32,8 @@
 // a recent (i.e. Vista or later) SDK, as the SDK does not provide IPv6 support
 // in that case.
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 namespace detail {
 
@@ -321,6 +319,8 @@ inline int IN6_IS_ADDR_MC_GLOBAL(const in6_addr_emulation* a)
 } // namespace detail
 } // namespace asio
 
+#include "asio/detail/pop_options.hpp"
+
 #endif // defined(ASIO_HAS_OLD_WIN_SDK)
 
 // Even newer Platform SDKs that support IPv6 may not define IPV6_V6ONLY.
@@ -335,6 +335,4 @@ inline int IN6_IS_ADDR_MC_GLOBAL(const in6_addr_emulation* a)
 
 #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
 
-#include "asio/detail/pop_options.hpp"
-
 #endif // ASIO_DETAIL_OLD_WIN_SDK_COMPAT_HPP
diff --git a/ext/asio/asio/detail/op_queue.hpp b/ext/asio/asio/detail/op_queue.hpp
index ccf8b9a..38278ea 100644
--- a/ext/asio/asio/detail/op_queue.hpp
+++ b/ext/asio/asio/detail/op_queue.hpp
@@ -1,8 +1,8 @@
 //
-// op_queue.hpp
-// ~~~~~~~~~~~~
+// detail/op_queue.hpp
+// ~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,10 +15,10 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
 #include "asio/detail/noncopyable.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 namespace detail {
 
diff --git a/ext/asio/asio/detail/operation.hpp b/ext/asio/asio/detail/operation.hpp
index 6aba361..3435c05 100644
--- a/ext/asio/asio/detail/operation.hpp
+++ b/ext/asio/asio/detail/operation.hpp
@@ -1,8 +1,8 @@
 //
-// operation.hpp
-// ~~~~~~~~~~~~~
+// detail/operation.hpp
+// ~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,14 +15,11 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/win_iocp_io_service_fwd.hpp"
+#include "asio/detail/config.hpp"
 
 #if defined(ASIO_HAS_IOCP)
 # include "asio/detail/win_iocp_operation.hpp"
 #else
-# include "asio/detail/reactor_fwd.hpp"
 # include "asio/detail/task_io_service_operation.hpp"
 #endif
 
@@ -32,12 +29,10 @@ namespace detail {
 #if defined(ASIO_HAS_IOCP)
 typedef win_iocp_operation operation;
 #else
-typedef task_io_service_operation<reactor> operation;
+typedef task_io_service_operation operation;
 #endif
 
 } // namespace detail
 } // namespace asio
 
-#include "asio/detail/pop_options.hpp"
-
 #endif // ASIO_DETAIL_OPERATION_HPP
diff --git a/ext/asio/asio/detail/pipe_select_interrupter.hpp b/ext/asio/asio/detail/pipe_select_interrupter.hpp
index 7469599..bf39426 100644
--- a/ext/asio/asio/detail/pipe_select_interrupter.hpp
+++ b/ext/asio/asio/detail/pipe_select_interrupter.hpp
@@ -1,8 +1,8 @@
 //
-// pipe_select_interrupter.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// detail/pipe_select_interrupter.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,22 +15,14 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include <boost/throw_exception.hpp>
-#include "asio/detail/pop_options.hpp"
-
-#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+#if !defined(BOOST_WINDOWS)
+#if !defined(__CYGWIN__)
+#if !defined(__SYMBIAN32__)
+#if !defined(ASIO_HAS_EVENTFD)
 
 #include "asio/detail/push_options.hpp"
-#include <fcntl.h>
-#include "asio/detail/pop_options.hpp"
-
-#include "asio/error.hpp"
-#include "asio/system_error.hpp"
-#include "asio/detail/socket_types.hpp"
 
 namespace asio {
 namespace detail {
@@ -39,57 +31,16 @@ class pipe_select_interrupter
 {
 public:
   // Constructor.
-  pipe_select_interrupter()
-  {
-    int pipe_fds[2];
-    if (pipe(pipe_fds) == 0)
-    {
-      read_descriptor_ = pipe_fds[0];
-      ::fcntl(read_descriptor_, F_SETFL, O_NONBLOCK);
-      write_descriptor_ = pipe_fds[1];
-      ::fcntl(write_descriptor_, F_SETFL, O_NONBLOCK);
-    }
-    else
-    {
-      asio::error_code ec(errno,
-          asio::error::get_system_category());
-      asio::system_error e(ec, "pipe_select_interrupter");
-      boost::throw_exception(e);
-    }
-  }
+  ASIO_DECL pipe_select_interrupter();
 
   // Destructor.
-  ~pipe_select_interrupter()
-  {
-    if (read_descriptor_ != -1)
-      ::close(read_descriptor_);
-    if (write_descriptor_ != -1)
-      ::close(write_descriptor_);
-  }
+  ASIO_DECL ~pipe_select_interrupter();
 
   // Interrupt the select call.
-  void interrupt()
-  {
-    char byte = 0;
-    int result = ::write(write_descriptor_, &byte, 1);
-    (void)result;
-  }
+  ASIO_DECL void interrupt();
 
   // Reset the select interrupt. Returns true if the call was interrupted.
-  bool reset()
-  {
-    for (;;)
-    {
-      char data[1024];
-      int bytes_read = ::read(read_descriptor_, data, sizeof(data));
-      if (bytes_read < 0 && errno == EINTR)
-        continue;
-      bool was_interrupted = (bytes_read > 0);
-      while (bytes_read == sizeof(data))
-        bytes_read = ::read(read_descriptor_, data, sizeof(data));
-      return was_interrupted;
-    }
-  }
+  ASIO_DECL bool reset();
 
   // Get the read descriptor to be passed to select.
   int read_descriptor() const
@@ -113,8 +64,15 @@ private:
 } // namespace detail
 } // namespace asio
 
-#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
-
 #include "asio/detail/pop_options.hpp"
 
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/detail/impl/pipe_select_interrupter.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
+#endif // !defined(ASIO_HAS_EVENTFD)
+#endif // !defined(__SYMBIAN32__)
+#endif // !defined(__CYGWIN__)
+#endif // !defined(BOOST_WINDOWS)
+
 #endif // ASIO_DETAIL_PIPE_SELECT_INTERRUPTER_HPP
diff --git a/ext/asio/asio/detail/pop_options.hpp b/ext/asio/asio/detail/pop_options.hpp
index a26b203..4e19336 100644
--- a/ext/asio/asio/detail/pop_options.hpp
+++ b/ext/asio/asio/detail/pop_options.hpp
@@ -1,8 +1,8 @@
 //
-// pop_options.hpp
-// ~~~~~~~~~~~~~~~
+// detail/pop_options.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -31,6 +31,16 @@
 #  pragma pack (pop)
 # endif
 
+# if defined(__OBJC__)
+#  if !defined(__APPLE_CC__) || (__APPLE_CC__ <= 1)
+#   if defined(ASIO_OBJC_WORKAROUND)
+#    undef Protocol
+#    undef id
+#    undef ASIO_OBJC_WORKAROUND
+#   endif
+#  endif
+# endif
+
 #elif defined(__KCC)
 
 // Kai C++
diff --git a/ext/asio/asio/detail/posix_event.hpp b/ext/asio/asio/detail/posix_event.hpp
index 49c15aa..d0ec8b0 100644
--- a/ext/asio/asio/detail/posix_event.hpp
+++ b/ext/asio/asio/detail/posix_event.hpp
@@ -1,8 +1,8 @@
 //
-// posix_event.hpp
-// ~~~~~~~~~~~~~~~
+// detail/posix_event.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,24 +15,16 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
+#include "asio/detail/config.hpp"
 
-#if defined(BOOST_HAS_PTHREADS)
+#if defined(BOOST_HAS_PTHREADS) && !defined(ASIO_DISABLE_THREADS)
 
-#include "asio/detail/push_options.hpp"
 #include <boost/assert.hpp>
-#include <boost/throw_exception.hpp>
 #include <pthread.h>
-#include "asio/detail/pop_options.hpp"
-
-#include "asio/error.hpp"
-#include "asio/system_error.hpp"
 #include "asio/detail/noncopyable.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 namespace detail {
 
@@ -41,19 +33,7 @@ class posix_event
 {
 public:
   // Constructor.
-  posix_event()
-    : signalled_(false)
-  {
-    int error = ::pthread_cond_init(&cond_, 0);
-    if (error != 0)
-    {
-      asio::system_error e(
-          asio::error_code(error,
-            asio::error::get_system_category()),
-          "event");
-      boost::throw_exception(e);
-    }
-  }
+  ASIO_DECL posix_event();
 
   // Destructor.
   ~posix_event()
@@ -107,8 +87,12 @@ private:
 } // namespace detail
 } // namespace asio
 
-#endif // defined(BOOST_HAS_PTHREADS)
-
 #include "asio/detail/pop_options.hpp"
 
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/detail/impl/posix_event.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
+#endif // defined(BOOST_HAS_PTHREADS) && !defined(ASIO_DISABLE_THREADS)
+
 #endif // ASIO_DETAIL_POSIX_EVENT_HPP
diff --git a/ext/asio/asio/detail/posix_fd_set_adapter.hpp b/ext/asio/asio/detail/posix_fd_set_adapter.hpp
index 17ef269..92d6bba 100644
--- a/ext/asio/asio/detail/posix_fd_set_adapter.hpp
+++ b/ext/asio/asio/detail/posix_fd_set_adapter.hpp
@@ -1,8 +1,8 @@
 //
-// posix_fd_set_adapter.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~
+// detail/posix_fd_set_adapter.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,15 +15,14 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 
-#include "asio/detail/push_options.hpp"
-#include <cstring>
-#include "asio/detail/pop_options.hpp"
+#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
 
+#include <cstring>
 #include "asio/detail/socket_types.hpp"
 
-#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 namespace detail {
@@ -74,8 +73,8 @@ private:
 } // namespace detail
 } // namespace asio
 
-#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
-
 #include "asio/detail/pop_options.hpp"
 
+#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
 #endif // ASIO_DETAIL_POSIX_FD_SET_ADAPTER_HPP
diff --git a/ext/asio/asio/detail/posix_mutex.hpp b/ext/asio/asio/detail/posix_mutex.hpp
index 230b83a..bcdf6b2 100644
--- a/ext/asio/asio/detail/posix_mutex.hpp
+++ b/ext/asio/asio/detail/posix_mutex.hpp
@@ -1,8 +1,8 @@
 //
-// posix_mutex.hpp
-// ~~~~~~~~~~~~~~~
+// detail/posix_mutex.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,24 +15,16 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
+#include "asio/detail/config.hpp"
 
-#if defined(BOOST_HAS_PTHREADS)
+#if defined(BOOST_HAS_PTHREADS) && !defined(ASIO_DISABLE_THREADS)
 
-#include "asio/detail/push_options.hpp"
-#include <boost/throw_exception.hpp>
 #include <pthread.h>
-#include "asio/detail/pop_options.hpp"
-
-#include "asio/error.hpp"
-#include "asio/system_error.hpp"
 #include "asio/detail/noncopyable.hpp"
 #include "asio/detail/scoped_lock.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 namespace detail {
 
@@ -45,18 +37,7 @@ public:
   typedef asio::detail::scoped_lock<posix_mutex> scoped_lock;
 
   // Constructor.
-  posix_mutex()
-  {
-    int error = ::pthread_mutex_init(&mutex_, 0);
-    if (error != 0)
-    {
-      asio::system_error e(
-          asio::error_code(error,
-            asio::error::get_system_category()),
-          "mutex");
-      boost::throw_exception(e);
-    }
-  }
+  ASIO_DECL posix_mutex();
 
   // Destructor.
   ~posix_mutex()
@@ -84,8 +65,12 @@ private:
 } // namespace detail
 } // namespace asio
 
-#endif // defined(BOOST_HAS_PTHREADS)
-
 #include "asio/detail/pop_options.hpp"
 
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/detail/impl/posix_mutex.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
+#endif // defined(BOOST_HAS_PTHREADS) && !defined(ASIO_DISABLE_THREADS)
+
 #endif // ASIO_DETAIL_POSIX_MUTEX_HPP
diff --git a/ext/asio/asio/detail/posix_signal_blocker.hpp b/ext/asio/asio/detail/posix_signal_blocker.hpp
index 135ca41..d41f128 100644
--- a/ext/asio/asio/detail/posix_signal_blocker.hpp
+++ b/ext/asio/asio/detail/posix_signal_blocker.hpp
@@ -1,8 +1,8 @@
 //
-// posix_signal_blocker.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~
+// detail/posix_signal_blocker.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,22 +15,17 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
+#include "asio/detail/config.hpp"
 
-#if defined(BOOST_HAS_PTHREADS)
+#if defined(BOOST_HAS_PTHREADS) && !defined(ASIO_DISABLE_THREADS)
 
-#include "asio/detail/push_options.hpp"
 #include <csignal>
 #include <pthread.h>
 #include <signal.h>
-#include "asio/detail/pop_options.hpp"
-
 #include "asio/detail/noncopyable.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 namespace detail {
 
@@ -83,8 +78,8 @@ private:
 } // namespace detail
 } // namespace asio
 
-#endif // defined(BOOST_HAS_PTHREADS)
-
 #include "asio/detail/pop_options.hpp"
 
+#endif // defined(BOOST_HAS_PTHREADS) && !defined(ASIO_DISABLE_THREADS)
+
 #endif // ASIO_DETAIL_POSIX_SIGNAL_BLOCKER_HPP
diff --git a/ext/asio/asio/detail/posix_thread.hpp b/ext/asio/asio/detail/posix_thread.hpp
index e0fea75..743417c 100644
--- a/ext/asio/asio/detail/posix_thread.hpp
+++ b/ext/asio/asio/detail/posix_thread.hpp
@@ -1,8 +1,8 @@
 //
-// posix_thread.hpp
-// ~~~~~~~~~~~~~~~~
+// detail/posix_thread.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,28 +15,22 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
+#include "asio/detail/config.hpp"
 
-#if defined(BOOST_HAS_PTHREADS)
+#if defined(BOOST_HAS_PTHREADS) && !defined(ASIO_DISABLE_THREADS)
 
-#include "asio/detail/push_options.hpp"
-#include <memory>
-#include <boost/throw_exception.hpp>
 #include <pthread.h>
-#include "asio/detail/pop_options.hpp"
-
-#include "asio/error.hpp"
-#include "asio/system_error.hpp"
 #include "asio/detail/noncopyable.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 namespace detail {
 
-extern "C" void* asio_detail_posix_thread_function(void* arg);
+extern "C"
+{
+  ASIO_DECL void* asio_detail_posix_thread_function(void* arg);
+}
 
 class posix_thread
   : private noncopyable
@@ -47,36 +41,14 @@ public:
   posix_thread(Function f)
     : joined_(false)
   {
-    std::auto_ptr<func_base> arg(new func<Function>(f));
-    int error = ::pthread_create(&thread_, 0,
-          asio_detail_posix_thread_function, arg.get());
-    if (error != 0)
-    {
-      asio::system_error e(
-          asio::error_code(error,
-            asio::error::get_system_category()),
-          "thread");
-      boost::throw_exception(e);
-    }
-    arg.release();
+    start_thread(new func<Function>(f));
   }
 
   // Destructor.
-  ~posix_thread()
-  {
-    if (!joined_)
-      ::pthread_detach(thread_);
-  }
+  ASIO_DECL ~posix_thread();
 
   // Wait for the thread to exit.
-  void join()
-  {
-    if (!joined_)
-    {
-      ::pthread_join(thread_, 0);
-      joined_ = true;
-    }
-  }
+  ASIO_DECL void join();
 
 private:
   friend void* asio_detail_posix_thread_function(void* arg);
@@ -88,6 +60,12 @@ private:
     virtual void run() = 0;
   };
 
+  struct auto_func_base_ptr
+  {
+    func_base* ptr;
+    ~auto_func_base_ptr() { delete ptr; }
+  };
+
   template <typename Function>
   class func
     : public func_base
@@ -107,23 +85,21 @@ private:
     Function f_;
   };
 
+  ASIO_DECL void start_thread(func_base* arg);
+
   ::pthread_t thread_;
   bool joined_;
 };
 
-inline void* asio_detail_posix_thread_function(void* arg)
-{
-  std::auto_ptr<posix_thread::func_base> f(
-      static_cast<posix_thread::func_base*>(arg));
-  f->run();
-  return 0;
-}
-
 } // namespace detail
 } // namespace asio
 
-#endif // defined(BOOST_HAS_PTHREADS)
-
 #include "asio/detail/pop_options.hpp"
 
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/detail/impl/posix_thread.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
+#endif // defined(BOOST_HAS_PTHREADS) && !defined(ASIO_DISABLE_THREADS)
+
 #endif // ASIO_DETAIL_POSIX_THREAD_HPP
diff --git a/ext/asio/asio/detail/posix_tss_ptr.hpp b/ext/asio/asio/detail/posix_tss_ptr.hpp
index 3b4ba07..30d9705 100644
--- a/ext/asio/asio/detail/posix_tss_ptr.hpp
+++ b/ext/asio/asio/detail/posix_tss_ptr.hpp
@@ -1,8 +1,8 @@
 //
-// posix_tss_ptr.hpp
-// ~~~~~~~~~~~~~~~~~
+// detail/posix_tss_ptr.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,26 +15,21 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
+#include "asio/detail/config.hpp"
 
-#if defined(BOOST_HAS_PTHREADS)
+#if defined(BOOST_HAS_PTHREADS) && !defined(ASIO_DISABLE_THREADS)
 
-#include "asio/detail/push_options.hpp"
-#include <boost/throw_exception.hpp>
 #include <pthread.h>
-#include "asio/detail/pop_options.hpp"
-
-#include "asio/error.hpp"
-#include "asio/system_error.hpp"
 #include "asio/detail/noncopyable.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 namespace detail {
 
+// Helper function to create thread-specific storage.
+ASIO_DECL void posix_tss_ptr_create(pthread_key_t& key);
+
 template <typename T>
 class posix_tss_ptr
   : private noncopyable
@@ -43,15 +38,7 @@ public:
   // Constructor.
   posix_tss_ptr()
   {
-    int error = ::pthread_key_create(&tss_key_, 0);
-    if (error != 0)
-    {
-      asio::system_error e(
-          asio::error_code(error,
-            asio::error::get_system_category()),
-          "tss");
-      boost::throw_exception(e);
-    }
+    posix_tss_ptr_create(tss_key_);
   }
 
   // Destructor.
@@ -76,13 +63,18 @@ private:
   // Thread-specific storage to allow unlocked access to determine whether a
   // thread is a member of the pool.
   pthread_key_t tss_key_;
+
 };
 
 } // namespace detail
 } // namespace asio
 
-#endif // defined(BOOST_HAS_PTHREADS)
-
 #include "asio/detail/pop_options.hpp"
 
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/detail/impl/posix_tss_ptr.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
+#endif // defined(BOOST_HAS_PTHREADS) && !defined(ASIO_DISABLE_THREADS)
+
 #endif // ASIO_DETAIL_POSIX_TSS_PTR_HPP
diff --git a/ext/asio/asio/detail/push_options.hpp b/ext/asio/asio/detail/push_options.hpp
index cb0e902..ebb3276 100644
--- a/ext/asio/asio/detail/push_options.hpp
+++ b/ext/asio/asio/detail/push_options.hpp
@@ -1,8 +1,8 @@
 //
-// push_options.hpp
-// ~~~~~~~~~~~~~~~~
+// detail/push_options.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -31,6 +31,18 @@
 #  pragma pack (push, 8)
 # endif
 
+# if defined(__OBJC__)
+#  if !defined(__APPLE_CC__) || (__APPLE_CC__ <= 1)
+#   if !defined(ASIO_DISABLE_OBJC_WORKAROUND)
+#    if !defined(Protocol) && !defined(id)
+#     define Protocol cpp_Protocol
+#     define id cpp_id
+#     define ASIO_OBJC_WORKAROUND
+#    endif
+#   endif
+#  endif
+# endif
+
 #elif defined(__KCC)
 
 // Kai C++
diff --git a/ext/asio/asio/detail/reactive_descriptor_service.hpp b/ext/asio/asio/detail/reactive_descriptor_service.hpp
index 7ad368d..f7e8bf5 100644
--- a/ext/asio/asio/detail/reactive_descriptor_service.hpp
+++ b/ext/asio/asio/detail/reactive_descriptor_service.hpp
@@ -1,8 +1,8 @@
 //
-// reactive_descriptor_service.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// detail/reactive_descriptor_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,21 +15,24 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
+
+#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
 
+#include <boost/utility/addressof.hpp>
 #include "asio/buffer.hpp"
-#include "asio/error.hpp"
 #include "asio/io_service.hpp"
 #include "asio/detail/bind_handler.hpp"
 #include "asio/detail/buffer_sequence_adapter.hpp"
 #include "asio/detail/descriptor_ops.hpp"
+#include "asio/detail/descriptor_read_op.hpp"
+#include "asio/detail/descriptor_write_op.hpp"
 #include "asio/detail/fenced_block.hpp"
 #include "asio/detail/noncopyable.hpp"
-#include "asio/detail/null_buffers_op.hpp"
+#include "asio/detail/reactive_null_buffers_op.hpp"
 #include "asio/detail/reactor.hpp"
-#include "asio/detail/reactor_op.hpp"
 
-#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 namespace detail {
@@ -48,7 +51,7 @@ public:
     // Default constructor.
     implementation_type()
       : descriptor_(-1),
-        flags_(0)
+        state_(0)
     {
     }
 
@@ -59,94 +62,29 @@ public:
     // The native descriptor representation.
     int descriptor_;
 
-    enum
-    {
-      // The user wants a non-blocking descriptor.
-      user_set_non_blocking = 1,
-
-      // The descriptor has been set non-blocking.
-      internal_non_blocking = 2,
-
-      // Helper "flag" used to determine whether the descriptor is non-blocking.
-      non_blocking = user_set_non_blocking | internal_non_blocking
-    };
-
-    // Flags indicating the current state of the descriptor.
-    unsigned char flags_;
+    // The current state of the descriptor.
+    descriptor_ops::state_type state_;
 
     // Per-descriptor data used by the reactor.
     reactor::per_descriptor_data reactor_data_;
   };
 
-  // The maximum number of buffers to support in a single operation.
-  enum { max_buffers = 64 < max_iov_len ? 64 : max_iov_len };
-
   // Constructor.
-  reactive_descriptor_service(asio::io_service& io_service)
-    : io_service_impl_(asio::use_service<io_service_impl>(io_service)),
-      reactor_(asio::use_service<reactor>(io_service))
-  {
-    reactor_.init_task();
-  }
+  ASIO_DECL reactive_descriptor_service(
+      asio::io_service& io_service);
 
   // Destroy all user-defined handler objects owned by the service.
-  void shutdown_service()
-  {
-  }
+  ASIO_DECL void shutdown_service();
 
   // Construct a new descriptor implementation.
-  void construct(implementation_type& impl)
-  {
-    impl.descriptor_ = -1;
-    impl.flags_ = 0;
-  }
+  ASIO_DECL void construct(implementation_type& impl);
 
   // Destroy a descriptor implementation.
-  void destroy(implementation_type& impl)
-  {
-    if (impl.descriptor_ != -1)
-    {
-      reactor_.close_descriptor(impl.descriptor_, impl.reactor_data_);
-
-      if (impl.flags_ & implementation_type::internal_non_blocking)
-      {
-        ioctl_arg_type non_blocking = 0;
-        asio::error_code ignored_ec;
-        descriptor_ops::ioctl(impl.descriptor_,
-            FIONBIO, &non_blocking, ignored_ec);
-        impl.flags_ &= ~implementation_type::internal_non_blocking;
-      }
-
-      asio::error_code ignored_ec;
-      descriptor_ops::close(impl.descriptor_, ignored_ec);
-
-      impl.descriptor_ = -1;
-    }
-  }
+  ASIO_DECL void destroy(implementation_type& impl);
 
   // Assign a native descriptor to a descriptor implementation.
-  asio::error_code assign(implementation_type& impl,
-      const native_type& native_descriptor, asio::error_code& ec)
-  {
-    if (is_open(impl))
-    {
-      ec = asio::error::already_open;
-      return ec;
-    }
-
-    if (int err = reactor_.register_descriptor(
-          native_descriptor, impl.reactor_data_))
-    {
-      ec = asio::error_code(err,
-          asio::error::get_system_category());
-      return ec;
-    }
-
-    impl.descriptor_ = native_descriptor;
-    impl.flags_ = 0;
-    ec = asio::error_code();
-    return ec;
-  }
+  ASIO_DECL asio::error_code assign(implementation_type& impl,
+      const native_type& native_descriptor, asio::error_code& ec);
 
   // Determine whether the descriptor is open.
   bool is_open(const implementation_type& impl) const
@@ -155,31 +93,8 @@ public:
   }
 
   // Destroy a descriptor implementation.
-  asio::error_code close(implementation_type& impl,
-      asio::error_code& ec)
-  {
-    if (is_open(impl))
-    {
-      reactor_.close_descriptor(impl.descriptor_, impl.reactor_data_);
-
-      if (impl.flags_ & implementation_type::internal_non_blocking)
-      {
-        ioctl_arg_type non_blocking = 0;
-        asio::error_code ignored_ec;
-        descriptor_ops::ioctl(impl.descriptor_,
-            FIONBIO, &non_blocking, ignored_ec);
-        impl.flags_ &= ~implementation_type::internal_non_blocking;
-      }
-
-      if (descriptor_ops::close(impl.descriptor_, ec) == -1)
-        return ec;
-
-      impl.descriptor_ = -1;
-    }
-
-    ec = asio::error_code();
-    return ec;
-  }
+  ASIO_DECL asio::error_code close(implementation_type& impl,
+      asio::error_code& ec);
 
   // Get the native descriptor representation.
   native_type native(const implementation_type& impl) const
@@ -188,56 +103,16 @@ public:
   }
 
   // Cancel all operations associated with the descriptor.
-  asio::error_code cancel(implementation_type& impl,
-      asio::error_code& ec)
-  {
-    if (!is_open(impl))
-    {
-      ec = asio::error::bad_descriptor;
-      return ec;
-    }
-
-    reactor_.cancel_ops(impl.descriptor_, impl.reactor_data_);
-    ec = asio::error_code();
-    return ec;
-  }
+  ASIO_DECL asio::error_code cancel(implementation_type& impl,
+      asio::error_code& ec);
 
   // Perform an IO control command on the descriptor.
   template <typename IO_Control_Command>
   asio::error_code io_control(implementation_type& impl,
       IO_Control_Command& command, asio::error_code& ec)
   {
-    if (!is_open(impl))
-    {
-      ec = asio::error::bad_descriptor;
-      return ec;
-    }
-
-    descriptor_ops::ioctl(impl.descriptor_, command.name(),
-        static_cast<ioctl_arg_type*>(command.data()), ec);
-
-    // When updating the non-blocking mode we always perform the ioctl syscall,
-    // even if the flags would otherwise indicate that the descriptor is
-    // already in the correct state. This ensures that the underlying
-    // descriptor is put into the state that has been requested by the user. If
-    // the ioctl syscall was successful then we need to update the flags to
-    // match.
-    if (!ec && command.name() == static_cast<int>(FIONBIO))
-    {
-      if (*static_cast<ioctl_arg_type*>(command.data()))
-      {
-        impl.flags_ |= implementation_type::user_set_non_blocking;
-      }
-      else
-      {
-        // Clearing the non-blocking mode always overrides any internally-set
-        // non-blocking flag. Any subsequent asynchronous operations will need
-        // to re-enable non-blocking I/O.
-        impl.flags_ &= ~(implementation_type::user_set_non_blocking
-            | implementation_type::internal_non_blocking);
-      }
-    }
-
+    descriptor_ops::ioctl(impl.descriptor_, impl.state_,
+        command.name(), static_cast<ioctl_arg_type*>(command.data()), ec);
     return ec;
   }
 
@@ -246,148 +121,23 @@ public:
   size_t write_some(implementation_type& impl,
       const ConstBufferSequence& buffers, asio::error_code& ec)
   {
-    if (!is_open(impl))
-    {
-      ec = asio::error::bad_descriptor;
-      return 0;
-    }
-
     buffer_sequence_adapter<asio::const_buffer,
         ConstBufferSequence> bufs(buffers);
 
-    // A request to read_some 0 bytes on a stream is a no-op.
-    if (bufs.all_empty())
-    {
-      ec = asio::error_code();
-      return 0;
-    }
-
-    // Send the data.
-    for (;;)
-    {
-      // Try to complete the operation without blocking.
-      int bytes_sent = descriptor_ops::gather_write(
-          impl.descriptor_, bufs.buffers(), bufs.count(), ec);
-
-      // Check if operation succeeded.
-      if (bytes_sent >= 0)
-        return bytes_sent;
-
-      // Operation failed.
-      if ((impl.flags_ & implementation_type::user_set_non_blocking)
-          || (ec != asio::error::would_block
-            && ec != asio::error::try_again))
-        return 0;
-
-      // Wait for descriptor to become ready.
-      if (descriptor_ops::poll_write(impl.descriptor_, ec) < 0)
-        return 0;
-    }
+    return descriptor_ops::sync_write(impl.descriptor_, impl.state_,
+        bufs.buffers(), bufs.count(), bufs.all_empty(), ec);
   }
 
   // Wait until data can be written without blocking.
   size_t write_some(implementation_type& impl,
       const null_buffers&, asio::error_code& ec)
   {
-    if (!is_open(impl))
-    {
-      ec = asio::error::bad_descriptor;
-      return 0;
-    }
-
     // Wait for descriptor to become ready.
     descriptor_ops::poll_write(impl.descriptor_, ec);
 
     return 0;
   }
 
-  template <typename ConstBufferSequence>
-  class write_op_base : public reactor_op
-  {
-  public:
-    write_op_base(int descriptor,
-        const ConstBufferSequence& buffers, func_type complete_func)
-      : reactor_op(&write_op_base::do_perform, complete_func),
-        descriptor_(descriptor),
-        buffers_(buffers)
-    {
-    }
-
-    static bool do_perform(reactor_op* base)
-    {
-      write_op_base* o(static_cast<write_op_base*>(base));
-
-      buffer_sequence_adapter<asio::const_buffer,
-          ConstBufferSequence> bufs(o->buffers_);
-
-      for (;;)
-      {
-        // Write the data.
-        asio::error_code ec;
-        int bytes = descriptor_ops::gather_write(
-            o->descriptor_, bufs.buffers(), bufs.count(), ec);
-
-        // Retry operation if interrupted by signal.
-        if (ec == asio::error::interrupted)
-          continue;
-
-        // Check if we need to run the operation again.
-        if (ec == asio::error::would_block
-            || ec == asio::error::try_again)
-          return false;
-
-        o->ec_ = ec;
-        o->bytes_transferred_ = (bytes < 0 ? 0 : bytes);
-        return true;
-      }
-    }
-
-  private:
-    int descriptor_;
-    ConstBufferSequence buffers_;
-  };
-
-  template <typename ConstBufferSequence, typename Handler>
-  class write_op : public write_op_base<ConstBufferSequence>
-  {
-  public:
-    write_op(int descriptor,
-        const ConstBufferSequence& buffers, Handler handler)
-      : write_op_base<ConstBufferSequence>(
-          descriptor, buffers, &write_op::do_complete),
-        handler_(handler)
-    {
-    }
-
-    static void do_complete(io_service_impl* owner, operation* base,
-        asio::error_code /*ec*/, std::size_t /*bytes_transferred*/)
-    {
-      // Take ownership of the handler object.
-      write_op* o(static_cast<write_op*>(base));
-      typedef handler_alloc_traits<Handler, write_op> alloc_traits;
-      handler_ptr<alloc_traits> ptr(o->handler_, o);
-
-      // Make the upcall if required.
-      if (owner)
-      {
-        // Make a copy of the handler so that the memory can be deallocated
-        // before the upcall is made. Even if we're not about to make an
-        // upcall, a sub-object of the handler may be the true owner of the
-        // memory associated with the handler. Consequently, a local copy of
-        // the handler is required to ensure that any owning sub-object remains
-        // valid until after we have deallocated the memory here.
-        detail::binder2<Handler, asio::error_code, std::size_t>
-          handler(o->handler_, o->ec_, o->bytes_transferred_);
-        ptr.reset();
-        asio::detail::fenced_block b;
-        asio_handler_invoke_helpers::invoke(handler, handler);
-      }
-    }
-
-  private:
-    Handler handler_;
-  };
-
   // Start an asynchronous write. The data being sent must be valid for the
   // lifetime of the asynchronous operation.
   template <typename ConstBufferSequence, typename Handler>
@@ -395,15 +145,16 @@ public:
       const ConstBufferSequence& buffers, Handler handler)
   {
     // Allocate and construct an operation to wrap the handler.
-    typedef write_op<ConstBufferSequence, Handler> value_type;
-    typedef handler_alloc_traits<Handler, value_type> alloc_traits;
-    raw_handler_ptr<alloc_traits> raw_ptr(handler);
-    handler_ptr<alloc_traits> ptr(raw_ptr, impl.descriptor_, buffers, handler);
+    typedef descriptor_write_op<ConstBufferSequence, Handler> op;
+    typename op::ptr p = { boost::addressof(handler),
+      asio_handler_alloc_helpers::allocate(
+        sizeof(op), handler), 0 };
+    p.p = new (p.v) op(impl.descriptor_, buffers, handler);
 
-    start_op(impl, reactor::write_op, ptr.get(), true,
+    start_op(impl, reactor::write_op, p.p, true,
         buffer_sequence_adapter<asio::const_buffer,
           ConstBufferSequence>::all_empty(buffers));
-    ptr.release();
+    p.v = p.p = 0;
   }
 
   // Start an asynchronous wait until data can be written without blocking.
@@ -412,13 +163,14 @@ public:
       const null_buffers&, Handler handler)
   {
     // Allocate and construct an operation to wrap the handler.
-    typedef null_buffers_op<Handler> value_type;
-    typedef handler_alloc_traits<Handler, value_type> alloc_traits;
-    raw_handler_ptr<alloc_traits> raw_ptr(handler);
-    handler_ptr<alloc_traits> ptr(raw_ptr, handler);
+    typedef reactive_null_buffers_op<Handler> op;
+    typename op::ptr p = { boost::addressof(handler),
+      asio_handler_alloc_helpers::allocate(
+        sizeof(op), handler), 0 };
+    p.p = new (p.v) op(handler);
 
-    start_op(impl, reactor::write_op, ptr.get(), false, false);
-    ptr.release();
+    start_op(impl, reactor::write_op, p.p, false, false);
+    p.v = p.p = 0;
   }
 
   // Read some data from the stream. Returns the number of bytes read.
@@ -426,157 +178,23 @@ public:
   size_t read_some(implementation_type& impl,
       const MutableBufferSequence& buffers, asio::error_code& ec)
   {
-    if (!is_open(impl))
-    {
-      ec = asio::error::bad_descriptor;
-      return 0;
-    }
-
     buffer_sequence_adapter<asio::mutable_buffer,
         MutableBufferSequence> bufs(buffers);
 
-    // A request to read_some 0 bytes on a stream is a no-op.
-    if (bufs.all_empty())
-    {
-      ec = asio::error_code();
-      return 0;
-    }
-
-    // Read some data.
-    for (;;)
-    {
-      // Try to complete the operation without blocking.
-      int bytes_read = descriptor_ops::scatter_read(
-          impl.descriptor_, bufs.buffers(), bufs.count(), ec);
-
-      // Check if operation succeeded.
-      if (bytes_read > 0)
-        return bytes_read;
-
-      // Check for EOF.
-      if (bytes_read == 0)
-      {
-        ec = asio::error::eof;
-        return 0;
-      }
-
-      // Operation failed.
-      if ((impl.flags_ & implementation_type::user_set_non_blocking)
-          || (ec != asio::error::would_block
-            && ec != asio::error::try_again))
-        return 0;
-
-      // Wait for descriptor to become ready.
-      if (descriptor_ops::poll_read(impl.descriptor_, ec) < 0)
-        return 0;
-    }
+    return descriptor_ops::sync_read(impl.descriptor_, impl.state_,
+        bufs.buffers(), bufs.count(), bufs.all_empty(), ec);
   }
 
   // Wait until data can be read without blocking.
   size_t read_some(implementation_type& impl,
       const null_buffers&, asio::error_code& ec)
   {
-    if (!is_open(impl))
-    {
-      ec = asio::error::bad_descriptor;
-      return 0;
-    }
-
     // Wait for descriptor to become ready.
     descriptor_ops::poll_read(impl.descriptor_, ec);
 
     return 0;
   }
 
-  template <typename MutableBufferSequence>
-  class read_op_base : public reactor_op
-  {
-  public:
-    read_op_base(int descriptor,
-        const MutableBufferSequence& buffers, func_type complete_func)
-      : reactor_op(&read_op_base::do_perform, complete_func),
-        descriptor_(descriptor),
-        buffers_(buffers)
-    {
-    }
-
-    static bool do_perform(reactor_op* base)
-    {
-      read_op_base* o(static_cast<read_op_base*>(base));
-
-      buffer_sequence_adapter<asio::mutable_buffer,
-          MutableBufferSequence> bufs(o->buffers_);
-
-      for (;;)
-      {
-        // Read some data.
-        asio::error_code ec;
-        int bytes = descriptor_ops::scatter_read(
-            o->descriptor_, bufs.buffers(), bufs.count(), ec);
-        if (bytes == 0)
-          ec = asio::error::eof;
-
-        // Retry operation if interrupted by signal.
-        if (ec == asio::error::interrupted)
-          continue;
-
-        // Check if we need to run the operation again.
-        if (ec == asio::error::would_block
-            || ec == asio::error::try_again)
-          return false;
-
-        o->ec_ = ec;
-        o->bytes_transferred_ = (bytes < 0 ? 0 : bytes);
-        return true;
-      }
-    }
-
-  private:
-    int descriptor_;
-    MutableBufferSequence buffers_;
-  };
-
-  template <typename MutableBufferSequence, typename Handler>
-  class read_op : public read_op_base<MutableBufferSequence>
-  {
-  public:
-    read_op(int descriptor,
-        const MutableBufferSequence& buffers, Handler handler)
-      : read_op_base<MutableBufferSequence>(
-          descriptor, buffers, &read_op::do_complete),
-        handler_(handler)
-    {
-    }
-
-    static void do_complete(io_service_impl* owner, operation* base,
-        asio::error_code /*ec*/, std::size_t /*bytes_transferred*/)
-    {
-      // Take ownership of the handler object.
-      read_op* o(static_cast<read_op*>(base));
-      typedef handler_alloc_traits<Handler, read_op> alloc_traits;
-      handler_ptr<alloc_traits> ptr(o->handler_, o);
-
-      // Make the upcall if required.
-      if (owner)
-      {
-        // Make a copy of the handler so that the memory can be deallocated
-        // before the upcall is made. Even if we're not about to make an
-        // upcall, a sub-object of the handler may be the true owner of the
-        // memory associated with the handler. Consequently, a local copy of
-        // the handler is required to ensure that any owning sub-object remains
-        // valid until after we have deallocated the memory here.
-        detail::binder2<Handler, asio::error_code, std::size_t>
-          handler(o->handler_, o->ec_, o->bytes_transferred_);
-        ptr.reset();
-        asio::detail::fenced_block b;
-        asio_handler_invoke_helpers::invoke(handler, handler);
-      }
-    }
-
-  private:
-    Handler handler_;
-  };
-
   // Start an asynchronous read. The buffer for the data being read must be
   // valid for the lifetime of the asynchronous operation.
   template <typename MutableBufferSequence, typename Handler>
@@ -584,16 +202,16 @@ public:
       const MutableBufferSequence& buffers, Handler handler)
   {
     // Allocate and construct an operation to wrap the handler.
-    typedef read_op<MutableBufferSequence, Handler> value_type;
-    typedef handler_alloc_traits<Handler, value_type> alloc_traits;
-    raw_handler_ptr<alloc_traits> raw_ptr(handler);
-    handler_ptr<alloc_traits> ptr(raw_ptr,
-        impl.descriptor_, buffers, handler);
+    typedef descriptor_read_op<MutableBufferSequence, Handler> op;
+    typename op::ptr p = { boost::addressof(handler),
+      asio_handler_alloc_helpers::allocate(
+        sizeof(op), handler), 0 };
+    p.p = new (p.v) op(impl.descriptor_, buffers, handler);
 
-    start_op(impl, reactor::read_op, ptr.get(), true,
+    start_op(impl, reactor::read_op, p.p, true,
         buffer_sequence_adapter<asio::mutable_buffer,
           MutableBufferSequence>::all_empty(buffers));
-    ptr.release();
+    p.v = p.p = 0;
   }
 
   // Wait until data can be read without blocking.
@@ -602,57 +220,20 @@ public:
       const null_buffers&, Handler handler)
   {
     // Allocate and construct an operation to wrap the handler.
-    typedef null_buffers_op<Handler> value_type;
-    typedef handler_alloc_traits<Handler, value_type> alloc_traits;
-    raw_handler_ptr<alloc_traits> raw_ptr(handler);
-    handler_ptr<alloc_traits> ptr(raw_ptr, handler);
+    typedef reactive_null_buffers_op<Handler> op;
+    typename op::ptr p = { boost::addressof(handler),
+      asio_handler_alloc_helpers::allocate(
+        sizeof(op), handler), 0 };
+    p.p = new (p.v) op(handler);
 
-    start_op(impl, reactor::read_op, ptr.get(), false, false);
-    ptr.release();
+    start_op(impl, reactor::read_op, p.p, false, false);
+    p.v = p.p = 0;
   }
 
 private:
   // Start the asynchronous operation.
-  void start_op(implementation_type& impl, int op_type,
-      reactor_op* op, bool non_blocking, bool noop)
-  {
-    if (!noop)
-    {
-      if (is_open(impl))
-      {
-        if (is_non_blocking(impl) || set_non_blocking(impl, op->ec_))
-        {
-          reactor_.start_op(op_type, impl.descriptor_,
-              impl.reactor_data_, op, non_blocking);
-          return;
-        }
-      }
-      else
-        op->ec_ = asio::error::bad_descriptor;
-    }
-
-    io_service_impl_.post_immediate_completion(op);
-  }
-
-  // Determine whether the descriptor has been set non-blocking.
-  bool is_non_blocking(implementation_type& impl) const
-  {
-    return (impl.flags_ & implementation_type::non_blocking);
-  }
-
-  // Set the internal non-blocking flag.
-  bool set_non_blocking(implementation_type& impl,
-      asio::error_code& ec)
-  {
-    ioctl_arg_type non_blocking = 1;
-    if (descriptor_ops::ioctl(impl.descriptor_, FIONBIO, &non_blocking, ec))
-      return false;
-    impl.flags_ |= implementation_type::internal_non_blocking;
-    return true;
-  }
-
-  // The io_service implementation used to post completions.
-  io_service_impl& io_service_impl_;
+  ASIO_DECL void start_op(implementation_type& impl, int op_type,
+      reactor_op* op, bool non_blocking, bool noop);
 
   // The selector that performs event demultiplexing for the service.
   reactor& reactor_;
@@ -661,8 +242,12 @@ private:
 } // namespace detail
 } // namespace asio
 
-#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
-
 #include "asio/detail/pop_options.hpp"
 
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/detail/impl/reactive_descriptor_service.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
+#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
 #endif // ASIO_DETAIL_REACTIVE_DESCRIPTOR_SERVICE_HPP
diff --git a/ext/asio/asio/detail/reactive_null_buffers_op.hpp b/ext/asio/asio/detail/reactive_null_buffers_op.hpp
new file mode 100644
index 0000000..0c83c61
--- /dev/null
+++ b/ext/asio/asio/detail/reactive_null_buffers_op.hpp
@@ -0,0 +1,83 @@
+//
+// detail/reactive_null_buffers_op.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_REACTIVE_NULL_BUFFERS_OP_HPP
+#define ASIO_DETAIL_REACTIVE_NULL_BUFFERS_OP_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+#include <boost/utility/addressof.hpp>
+#include "asio/detail/fenced_block.hpp"
+#include "asio/detail/handler_alloc_helpers.hpp"
+#include "asio/detail/handler_invoke_helpers.hpp"
+#include "asio/detail/reactor_op.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename Handler>
+class reactive_null_buffers_op : public reactor_op
+{
+public:
+  ASIO_DEFINE_HANDLER_PTR(reactive_null_buffers_op);
+
+  reactive_null_buffers_op(Handler handler)
+    : reactor_op(&reactive_null_buffers_op::do_perform,
+        &reactive_null_buffers_op::do_complete),
+      handler_(handler)
+  {
+  }
+
+  static bool do_perform(reactor_op*)
+  {
+    return true;
+  }
+
+  static void do_complete(io_service_impl* owner, operation* base,
+      asio::error_code /*ec*/, std::size_t /*bytes_transferred*/)
+  {
+    // Take ownership of the handler object.
+    reactive_null_buffers_op* o(static_cast<reactive_null_buffers_op*>(base));
+    ptr p = { boost::addressof(o->handler_), o, o };
+
+    // Make a copy of the handler so that the memory can be deallocated before
+    // the upcall is made. Even if we're not about to make an upcall, a
+    // sub-object of the handler may be the true owner of the memory associated
+    // with the handler. Consequently, a local copy of the handler is required
+    // to ensure that any owning sub-object remains valid until after we have
+    // deallocated the memory here.
+    detail::binder2<Handler, asio::error_code, std::size_t>
+      handler(o->handler_, o->ec_, o->bytes_transferred_);
+    p.h = boost::addressof(handler.handler_);
+    p.reset();
+
+    // Make the upcall if required.
+    if (owner)
+    {
+      asio::detail::fenced_block b;
+      asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+    }
+  }
+
+private:
+  Handler handler_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_REACTIVE_NULL_BUFFERS_OP_HPP
diff --git a/ext/asio/asio/detail/reactive_serial_port_service.hpp b/ext/asio/asio/detail/reactive_serial_port_service.hpp
index 186460f..556ea06 100644
--- a/ext/asio/asio/detail/reactive_serial_port_service.hpp
+++ b/ext/asio/asio/detail/reactive_serial_port_service.hpp
@@ -1,8 +1,8 @@
 //
-// reactive_serial_port_service.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// detail/reactive_serial_port_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 // Copyright (c) 2008 Rep Invariant Systems, Inc. (info at repinvariant.com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
@@ -16,23 +16,20 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <cstring>
-#include <string>
-#include "asio/detail/pop_options.hpp"
+#include "asio/detail/config.hpp"
 
-#include "asio/serial_port_base.hpp"
-
-#if defined(ASIO_HAS_SERIAL_PORT) \
-  && !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+#if defined(ASIO_HAS_SERIAL_PORT)
+#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
 
+#include <string>
 #include "asio/error.hpp"
 #include "asio/io_service.hpp"
+#include "asio/serial_port_base.hpp"
 #include "asio/detail/descriptor_ops.hpp"
 #include "asio/detail/reactive_descriptor_service.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 namespace detail {
 
@@ -46,119 +43,55 @@ public:
   // The implementation type of the serial port.
   typedef reactive_descriptor_service::implementation_type implementation_type;
 
-  reactive_serial_port_service(asio::io_service& io_service)
-    : descriptor_service_(io_service)
-  {
-  }
+  ASIO_DECL reactive_serial_port_service(
+      asio::io_service& io_service);
 
   // Destroy all user-defined handler objects owned by the service.
-  void shutdown_service()
-  {
-    descriptor_service_.shutdown_service();
-  }
+  ASIO_DECL void shutdown_service();
 
-  // Construct a new handle implementation.
+  // Construct a new serial port implementation.
   void construct(implementation_type& impl)
   {
     descriptor_service_.construct(impl);
   }
 
-  // Destroy a handle implementation.
+  // Destroy a serial port implementation.
   void destroy(implementation_type& impl)
   {
     descriptor_service_.destroy(impl);
   }
 
   // Open the serial port using the specified device name.
-  asio::error_code open(implementation_type& impl,
-      const std::string& device, asio::error_code& ec)
-  {
-    if (is_open(impl))
-    {
-      ec = asio::error::already_open;
-      return ec;
-    }
-
-    int fd = descriptor_ops::open(device.c_str(),
-        O_RDWR | O_NONBLOCK | O_NOCTTY, ec);
-    if (fd < 0)
-      return ec;
-
-    int s = descriptor_ops::fcntl(fd, F_GETFL, ec);
-    if (s >= 0)
-      s = descriptor_ops::fcntl(fd, F_SETFL, s | O_NONBLOCK, ec);
-    if (s < 0)
-    {
-      asio::error_code ignored_ec;
-      descriptor_ops::close(fd, ignored_ec);
-      return ec;
-    }
-  
-    // Set up default serial port options.
-    termios ios;
-    descriptor_ops::clear_error(ec);
-    s = descriptor_ops::error_wrapper(::tcgetattr(fd, &ios), ec);
-    if (s >= 0)
-    {
-#if defined(_BSD_SOURCE)
-      ::cfmakeraw(&ios);
-#else
-      ios.c_iflag &= ~(IGNBRK | BRKINT | PARMRK
-          | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
-      ios.c_oflag &= ~OPOST;
-      ios.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
-      ios.c_cflag &= ~(CSIZE | PARENB);
-      ios.c_cflag |= CS8;
-#endif
-      ios.c_iflag |= IGNPAR;
-      ios.c_cflag |= CREAD | CLOCAL;
-      descriptor_ops::clear_error(ec);
-      s = descriptor_ops::error_wrapper(::tcsetattr(fd, TCSANOW, &ios), ec);
-    }
-    if (s < 0)
-    {
-      asio::error_code ignored_ec;
-      descriptor_ops::close(fd, ignored_ec);
-      return ec;
-    }
-  
-    // We're done. Take ownership of the serial port descriptor.
-    if (descriptor_service_.assign(impl, fd, ec))
-    {
-      asio::error_code ignored_ec;
-      descriptor_ops::close(fd, ignored_ec);
-    }
-
-    return ec;
-  }
+  ASIO_DECL asio::error_code open(implementation_type& impl,
+      const std::string& device, asio::error_code& ec);
 
-  // Assign a native handle to a handle implementation.
+  // Assign a native descriptor to a serial port implementation.
   asio::error_code assign(implementation_type& impl,
       const native_type& native_descriptor, asio::error_code& ec)
   {
     return descriptor_service_.assign(impl, native_descriptor, ec);
   }
 
-  // Determine whether the handle is open.
+  // Determine whether the serial port is open.
   bool is_open(const implementation_type& impl) const
   {
     return descriptor_service_.is_open(impl);
   }
 
-  // Destroy a handle implementation.
+  // Destroy a serial port implementation.
   asio::error_code close(implementation_type& impl,
       asio::error_code& ec)
   {
     return descriptor_service_.close(impl, ec);
   }
 
-  // Get the native handle representation.
+  // Get the native serial port representation.
   native_type native(implementation_type& impl)
   {
     return descriptor_service_.native(impl);
   }
 
-  // Cancel all operations associated with the handle.
+  // Cancel all operations associated with the serial port.
   asio::error_code cancel(implementation_type& impl,
       asio::error_code& ec)
   {
@@ -170,20 +103,9 @@ public:
   asio::error_code set_option(implementation_type& impl,
       const SettableSerialPortOption& option, asio::error_code& ec)
   {
-    termios ios;
-    descriptor_ops::clear_error(ec);
-    descriptor_ops::error_wrapper(::tcgetattr(
-          descriptor_service_.native(impl), &ios), ec);
-    if (ec)
-      return ec;
-
-    if (option.store(ios, ec))
-      return ec;
-
-    descriptor_ops::clear_error(ec);
-    descriptor_ops::error_wrapper(::tcsetattr(
-          descriptor_service_.native(impl), TCSANOW, &ios), ec);
-    return ec;
+    return do_set_option(impl,
+        &reactive_serial_port_service::store_option<SettableSerialPortOption>,
+        &option, ec);
   }
 
   // Get an option from the serial port.
@@ -191,21 +113,16 @@ public:
   asio::error_code get_option(const implementation_type& impl,
       GettableSerialPortOption& option, asio::error_code& ec) const
   {
-    termios ios;
-    descriptor_ops::clear_error(ec);
-    descriptor_ops::error_wrapper(::tcgetattr(
-          descriptor_service_.native(impl), &ios), ec);
-    if (ec)
-      return ec;
-
-    return option.load(ios, ec);
+    return do_get_option(impl,
+        &reactive_serial_port_service::load_option<GettableSerialPortOption>,
+        &option, ec);
   }
 
   // Send a break sequence to the serial port.
   asio::error_code send_break(implementation_type& impl,
       asio::error_code& ec)
   {
-    descriptor_ops::clear_error(ec);
+    errno = 0;
     descriptor_ops::error_wrapper(::tcsendbreak(
           descriptor_service_.native(impl), 0), ec);
     return ec;
@@ -246,6 +163,41 @@ public:
   }
 
 private:
+  // Function pointer type for storing a serial port option.
+  typedef asio::error_code (*store_function_type)(
+      const void*, termios&, asio::error_code&);
+
+  // Helper function template to store a serial port option.
+  template <typename SettableSerialPortOption>
+  static asio::error_code store_option(const void* option,
+      termios& storage, asio::error_code& ec)
+  {
+    return static_cast<const SettableSerialPortOption*>(option)->store(
+        storage, ec);
+  }
+
+  // Helper function to set a serial port option.
+  ASIO_DECL asio::error_code do_set_option(
+      implementation_type& impl, store_function_type store,
+      const void* option, asio::error_code& ec);
+
+  // Function pointer type for loading a serial port option.
+  typedef asio::error_code (*load_function_type)(
+      void*, const termios&, asio::error_code&);
+
+  // Helper function template to load a serial port option.
+  template <typename GettableSerialPortOption>
+  static asio::error_code load_option(void* option,
+      const termios& storage, asio::error_code& ec)
+  {
+    return static_cast<GettableSerialPortOption*>(option)->load(storage, ec);
+  }
+
+  // Helper function to get a serial port option.
+  ASIO_DECL asio::error_code do_get_option(
+      const implementation_type& impl, load_function_type load,
+      void* option, asio::error_code& ec) const;
+
   // The implementation used for initiating asynchronous operations.
   reactive_descriptor_service descriptor_service_;
 };
@@ -253,9 +205,13 @@ private:
 } // namespace detail
 } // namespace asio
 
-#endif // defined(ASIO_HAS_SERIAL_PORT)
-       //   && !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
-
 #include "asio/detail/pop_options.hpp"
 
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/detail/impl/reactive_serial_port_service.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
+#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+#endif // defined(ASIO_HAS_SERIAL_PORT)
+
 #endif // ASIO_DETAIL_REACTIVE_SERIAL_PORT_SERVICE_HPP
diff --git a/ext/asio/asio/detail/reactive_socket_accept_op.hpp b/ext/asio/asio/detail/reactive_socket_accept_op.hpp
new file mode 100644
index 0000000..76c6741
--- /dev/null
+++ b/ext/asio/asio/detail/reactive_socket_accept_op.hpp
@@ -0,0 +1,131 @@
+//
+// detail/reactive_socket_accept_op.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_REACTIVE_SOCKET_ACCEPT_OP_HPP
+#define ASIO_DETAIL_REACTIVE_SOCKET_ACCEPT_OP_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+#include <boost/utility/addressof.hpp>
+#include "asio/detail/bind_handler.hpp"
+#include "asio/detail/buffer_sequence_adapter.hpp"
+#include "asio/detail/fenced_block.hpp"
+#include "asio/detail/reactor_op.hpp"
+#include "asio/detail/socket_holder.hpp"
+#include "asio/detail/socket_ops.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename Socket, typename Protocol>
+class reactive_socket_accept_op_base : public reactor_op
+{
+public:
+  reactive_socket_accept_op_base(socket_type socket,
+      socket_ops::state_type state, Socket& peer, const Protocol& protocol,
+      typename Protocol::endpoint* peer_endpoint, func_type complete_func)
+    : reactor_op(&reactive_socket_accept_op_base::do_perform, complete_func),
+      socket_(socket),
+      state_(state),
+      peer_(peer),
+      protocol_(protocol),
+      peer_endpoint_(peer_endpoint)
+  {
+  }
+
+  static bool do_perform(reactor_op* base)
+  {
+    reactive_socket_accept_op_base* o(
+        static_cast<reactive_socket_accept_op_base*>(base));
+
+    std::size_t addrlen = o->peer_endpoint_ ? o->peer_endpoint_->capacity() : 0;
+    socket_type new_socket = invalid_socket;
+    bool result = socket_ops::non_blocking_accept(o->socket_,
+          o->state_, o->peer_endpoint_ ? o->peer_endpoint_->data() : 0,
+          o->peer_endpoint_ ? &addrlen : 0, o->ec_, new_socket);
+
+    // On success, assign new connection to peer socket object.
+    if (new_socket >= 0)
+    {
+      socket_holder new_socket_holder(new_socket);
+      if (o->peer_endpoint_)
+        o->peer_endpoint_->resize(addrlen);
+      if (!o->peer_.assign(o->protocol_, new_socket, o->ec_))
+        new_socket_holder.release();
+    }
+
+    return result;
+  }
+
+private:
+  socket_type socket_;
+  socket_ops::state_type state_;
+  Socket& peer_;
+  Protocol protocol_;
+  typename Protocol::endpoint* peer_endpoint_;
+};
+
+template <typename Socket, typename Protocol, typename Handler>
+class reactive_socket_accept_op :
+  public reactive_socket_accept_op_base<Socket, Protocol>
+{
+public:
+  ASIO_DEFINE_HANDLER_PTR(reactive_socket_accept_op);
+
+  reactive_socket_accept_op(socket_type socket,
+      socket_ops::state_type state, Socket& peer, const Protocol& protocol,
+      typename Protocol::endpoint* peer_endpoint, Handler handler)
+    : reactive_socket_accept_op_base<Socket, Protocol>(socket, state, peer,
+        protocol, peer_endpoint, &reactive_socket_accept_op::do_complete),
+      handler_(handler)
+  {
+  }
+
+  static void do_complete(io_service_impl* owner, operation* base,
+      asio::error_code /*ec*/, std::size_t /*bytes_transferred*/)
+  {
+    // Take ownership of the handler object.
+    reactive_socket_accept_op* o(static_cast<reactive_socket_accept_op*>(base));
+    ptr p = { boost::addressof(o->handler_), o, o };
+
+    // Make a copy of the handler so that the memory can be deallocated before
+    // the upcall is made. Even if we're not about to make an upcall, a
+    // sub-object of the handler may be the true owner of the memory associated
+    // with the handler. Consequently, a local copy of the handler is required
+    // to ensure that any owning sub-object remains valid until after we have
+    // deallocated the memory here.
+    detail::binder1<Handler, asio::error_code>
+      handler(o->handler_, o->ec_);
+    p.h = boost::addressof(handler.handler_);
+    p.reset();
+
+    // Make the upcall if required.
+    if (owner)
+    {
+      asio::detail::fenced_block b;
+      asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+    }
+  }
+
+private:
+  Handler handler_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_REACTIVE_SOCKET_ACCEPT_OP_HPP
diff --git a/ext/asio/asio/detail/reactive_socket_connect_op.hpp b/ext/asio/asio/detail/reactive_socket_connect_op.hpp
new file mode 100644
index 0000000..8267091
--- /dev/null
+++ b/ext/asio/asio/detail/reactive_socket_connect_op.hpp
@@ -0,0 +1,101 @@
+//
+// detail/reactive_socket_connect_op.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_REACTIVE_SOCKET_CONNECT_OP_HPP
+#define ASIO_DETAIL_REACTIVE_SOCKET_CONNECT_OP_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+#include <boost/utility/addressof.hpp>
+#include "asio/detail/bind_handler.hpp"
+#include "asio/detail/buffer_sequence_adapter.hpp"
+#include "asio/detail/fenced_block.hpp"
+#include "asio/detail/reactor_op.hpp"
+#include "asio/detail/socket_ops.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+class reactive_socket_connect_op_base : public reactor_op
+{
+public:
+  reactive_socket_connect_op_base(socket_type socket, func_type complete_func)
+    : reactor_op(&reactive_socket_connect_op_base::do_perform, complete_func),
+      socket_(socket)
+  {
+  }
+
+  static bool do_perform(reactor_op* base)
+  {
+    reactive_socket_connect_op_base* o(
+        static_cast<reactive_socket_connect_op_base*>(base));
+
+    return socket_ops::non_blocking_connect(o->socket_, o->ec_);
+  }
+
+private:
+  socket_type socket_;
+};
+
+template <typename Handler>
+class reactive_socket_connect_op : public reactive_socket_connect_op_base
+{
+public:
+  ASIO_DEFINE_HANDLER_PTR(reactive_socket_connect_op);
+
+  reactive_socket_connect_op(socket_type socket, Handler handler)
+    : reactive_socket_connect_op_base(socket,
+        &reactive_socket_connect_op::do_complete),
+      handler_(handler)
+  {
+  }
+
+  static void do_complete(io_service_impl* owner, operation* base,
+      asio::error_code /*ec*/, std::size_t /*bytes_transferred*/)
+  {
+    // Take ownership of the handler object.
+    reactive_socket_connect_op* o
+      (static_cast<reactive_socket_connect_op*>(base));
+    ptr p = { boost::addressof(o->handler_), o, o };
+
+    // Make a copy of the handler so that the memory can be deallocated before
+    // the upcall is made. Even if we're not about to make an upcall, a
+    // sub-object of the handler may be the true owner of the memory associated
+    // with the handler. Consequently, a local copy of the handler is required
+    // to ensure that any owning sub-object remains valid until after we have
+    // deallocated the memory here.
+    detail::binder1<Handler, asio::error_code>
+      handler(o->handler_, o->ec_);
+    p.h = boost::addressof(handler.handler_);
+    p.reset();
+
+    // Make the upcall if required.
+    if (owner)
+    {
+      asio::detail::fenced_block b;
+      asio_handler_invoke_helpers::invoke(handler, handler);
+    }
+  }
+
+private:
+  Handler handler_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_REACTIVE_SOCKET_CONNECT_OP_HPP
diff --git a/ext/asio/asio/detail/reactive_socket_recv_op.hpp b/ext/asio/asio/detail/reactive_socket_recv_op.hpp
new file mode 100644
index 0000000..91a30a8
--- /dev/null
+++ b/ext/asio/asio/detail/reactive_socket_recv_op.hpp
@@ -0,0 +1,118 @@
+//
+// detail/reactive_socket_recv_op.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_REACTIVE_SOCKET_RECV_OP_HPP
+#define ASIO_DETAIL_REACTIVE_SOCKET_RECV_OP_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+#include <boost/utility/addressof.hpp>
+#include "asio/detail/bind_handler.hpp"
+#include "asio/detail/buffer_sequence_adapter.hpp"
+#include "asio/detail/fenced_block.hpp"
+#include "asio/detail/reactor_op.hpp"
+#include "asio/detail/socket_ops.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename MutableBufferSequence>
+class reactive_socket_recv_op_base : public reactor_op
+{
+public:
+  reactive_socket_recv_op_base(socket_type socket,
+      socket_ops::state_type state, const MutableBufferSequence& buffers,
+      socket_base::message_flags flags, func_type complete_func)
+    : reactor_op(&reactive_socket_recv_op_base::do_perform, complete_func),
+      socket_(socket),
+      state_(state),
+      buffers_(buffers),
+      flags_(flags)
+  {
+  }
+
+  static bool do_perform(reactor_op* base)
+  {
+    reactive_socket_recv_op_base* o(
+        static_cast<reactive_socket_recv_op_base*>(base));
+
+    buffer_sequence_adapter<asio::mutable_buffer,
+        MutableBufferSequence> bufs(o->buffers_);
+
+    return socket_ops::non_blocking_recv(o->socket_,
+        bufs.buffers(), bufs.count(), o->flags_,
+        (o->state_ & socket_ops::stream_oriented),
+        o->ec_, o->bytes_transferred_);
+  }
+
+private:
+  socket_type socket_;
+  socket_ops::state_type state_;
+  MutableBufferSequence buffers_;
+  socket_base::message_flags flags_;
+};
+
+template <typename MutableBufferSequence, typename Handler>
+class reactive_socket_recv_op :
+  public reactive_socket_recv_op_base<MutableBufferSequence>
+{
+public:
+  ASIO_DEFINE_HANDLER_PTR(reactive_socket_recv_op);
+
+  reactive_socket_recv_op(socket_type socket,
+      socket_ops::state_type state, const MutableBufferSequence& buffers,
+      socket_base::message_flags flags, Handler handler)
+    : reactive_socket_recv_op_base<MutableBufferSequence>(socket, state,
+        buffers, flags, &reactive_socket_recv_op::do_complete),
+      handler_(handler)
+  {
+  }
+
+  static void do_complete(io_service_impl* owner, operation* base,
+      asio::error_code /*ec*/, std::size_t /*bytes_transferred*/)
+  {
+    // Take ownership of the handler object.
+    reactive_socket_recv_op* o(static_cast<reactive_socket_recv_op*>(base));
+    ptr p = { boost::addressof(o->handler_), o, o };
+
+    // Make a copy of the handler so that the memory can be deallocated before
+    // the upcall is made. Even if we're not about to make an upcall, a
+    // sub-object of the handler may be the true owner of the memory associated
+    // with the handler. Consequently, a local copy of the handler is required
+    // to ensure that any owning sub-object remains valid until after we have
+    // deallocated the memory here.
+    detail::binder2<Handler, asio::error_code, std::size_t>
+      handler(o->handler_, o->ec_, o->bytes_transferred_);
+    p.h = boost::addressof(handler.handler_);
+    p.reset();
+
+    // Make the upcall if required.
+    if (owner)
+    {
+      asio::detail::fenced_block b;
+      asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+    }
+  }
+
+private:
+  Handler handler_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_REACTIVE_SOCKET_RECV_OP_HPP
diff --git a/ext/asio/asio/detail/reactive_socket_recvfrom_op.hpp b/ext/asio/asio/detail/reactive_socket_recvfrom_op.hpp
new file mode 100644
index 0000000..121d6ec
--- /dev/null
+++ b/ext/asio/asio/detail/reactive_socket_recvfrom_op.hpp
@@ -0,0 +1,128 @@
+//
+// detail/reactive_socket_recvfrom_op.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_REACTIVE_SOCKET_RECVFROM_OP_HPP
+#define ASIO_DETAIL_REACTIVE_SOCKET_RECVFROM_OP_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+#include <boost/utility/addressof.hpp>
+#include "asio/detail/bind_handler.hpp"
+#include "asio/detail/buffer_sequence_adapter.hpp"
+#include "asio/detail/fenced_block.hpp"
+#include "asio/detail/reactor_op.hpp"
+#include "asio/detail/socket_ops.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename MutableBufferSequence, typename Endpoint>
+class reactive_socket_recvfrom_op_base : public reactor_op
+{
+public:
+  reactive_socket_recvfrom_op_base(socket_type socket, int protocol_type,
+      const MutableBufferSequence& buffers, Endpoint& endpoint,
+      socket_base::message_flags flags, func_type complete_func)
+    : reactor_op(&reactive_socket_recvfrom_op_base::do_perform, complete_func),
+      socket_(socket),
+      protocol_type_(protocol_type),
+      buffers_(buffers),
+      sender_endpoint_(endpoint),
+      flags_(flags)
+  {
+  }
+
+  static bool do_perform(reactor_op* base)
+  {
+    reactive_socket_recvfrom_op_base* o(
+        static_cast<reactive_socket_recvfrom_op_base*>(base));
+
+    buffer_sequence_adapter<asio::mutable_buffer,
+        MutableBufferSequence> bufs(o->buffers_);
+
+    std::size_t addr_len = o->sender_endpoint_.capacity();
+    bool result = socket_ops::non_blocking_recvfrom(o->socket_,
+        bufs.buffers(), bufs.count(), o->flags_,
+        o->sender_endpoint_.data(), &addr_len,
+        o->ec_, o->bytes_transferred_);
+
+    if (result && !o->ec_)
+      o->sender_endpoint_.resize(addr_len);
+
+    return result;
+  }
+
+private:
+  socket_type socket_;
+  int protocol_type_;
+  MutableBufferSequence buffers_;
+  Endpoint& sender_endpoint_;
+  socket_base::message_flags flags_;
+};
+
+template <typename MutableBufferSequence, typename Endpoint, typename Handler>
+class reactive_socket_recvfrom_op :
+  public reactive_socket_recvfrom_op_base<MutableBufferSequence, Endpoint>
+{
+public:
+  ASIO_DEFINE_HANDLER_PTR(reactive_socket_recvfrom_op);
+
+  reactive_socket_recvfrom_op(socket_type socket, int protocol_type,
+      const MutableBufferSequence& buffers, Endpoint& endpoint,
+      socket_base::message_flags flags, Handler handler)
+    : reactive_socket_recvfrom_op_base<MutableBufferSequence, Endpoint>(
+        socket, protocol_type, buffers, endpoint, flags,
+        &reactive_socket_recvfrom_op::do_complete),
+      handler_(handler)
+  {
+  }
+
+  static void do_complete(io_service_impl* owner, operation* base,
+      asio::error_code /*ec*/, std::size_t /*bytes_transferred*/)
+  {
+    // Take ownership of the handler object.
+    reactive_socket_recvfrom_op* o(
+        static_cast<reactive_socket_recvfrom_op*>(base));
+    ptr p = { boost::addressof(o->handler_), o, o };
+
+    // Make a copy of the handler so that the memory can be deallocated before
+    // the upcall is made. Even if we're not about to make an upcall, a
+    // sub-object of the handler may be the true owner of the memory associated
+    // with the handler. Consequently, a local copy of the handler is required
+    // to ensure that any owning sub-object remains valid until after we have
+    // deallocated the memory here.
+    detail::binder2<Handler, asio::error_code, std::size_t>
+      handler(o->handler_, o->ec_, o->bytes_transferred_);
+    p.h = boost::addressof(handler.handler_);
+    p.reset();
+
+    // Make the upcall if required.
+    if (owner)
+    {
+      asio::detail::fenced_block b;
+      asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+    }
+  }
+
+private:
+  Handler handler_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_REACTIVE_SOCKET_RECVFROM_OP_HPP
diff --git a/ext/asio/asio/detail/reactive_socket_send_op.hpp b/ext/asio/asio/detail/reactive_socket_send_op.hpp
new file mode 100644
index 0000000..9a68dac
--- /dev/null
+++ b/ext/asio/asio/detail/reactive_socket_send_op.hpp
@@ -0,0 +1,115 @@
+//
+// detail/reactive_socket_send_op.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_REACTIVE_SOCKET_SEND_OP_HPP
+#define ASIO_DETAIL_REACTIVE_SOCKET_SEND_OP_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+#include <boost/utility/addressof.hpp>
+#include "asio/detail/bind_handler.hpp"
+#include "asio/detail/buffer_sequence_adapter.hpp"
+#include "asio/detail/fenced_block.hpp"
+#include "asio/detail/reactor_op.hpp"
+#include "asio/detail/socket_ops.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename ConstBufferSequence>
+class reactive_socket_send_op_base : public reactor_op
+{
+public:
+  reactive_socket_send_op_base(socket_type socket,
+      const ConstBufferSequence& buffers,
+      socket_base::message_flags flags, func_type complete_func)
+    : reactor_op(&reactive_socket_send_op_base::do_perform, complete_func),
+      socket_(socket),
+      buffers_(buffers),
+      flags_(flags)
+  {
+  }
+
+  static bool do_perform(reactor_op* base)
+  {
+    reactive_socket_send_op_base* o(
+        static_cast<reactive_socket_send_op_base*>(base));
+
+    buffer_sequence_adapter<asio::const_buffer,
+        ConstBufferSequence> bufs(o->buffers_);
+
+    return socket_ops::non_blocking_send(o->socket_,
+          bufs.buffers(), bufs.count(), o->flags_,
+          o->ec_, o->bytes_transferred_);
+  }
+
+private:
+  socket_type socket_;
+  ConstBufferSequence buffers_;
+  socket_base::message_flags flags_;
+};
+
+template <typename ConstBufferSequence, typename Handler>
+class reactive_socket_send_op :
+  public reactive_socket_send_op_base<ConstBufferSequence>
+{
+public:
+  ASIO_DEFINE_HANDLER_PTR(reactive_socket_send_op);
+
+  reactive_socket_send_op(socket_type socket,
+      const ConstBufferSequence& buffers,
+      socket_base::message_flags flags, Handler handler)
+    : reactive_socket_send_op_base<ConstBufferSequence>(socket,
+        buffers, flags, &reactive_socket_send_op::do_complete),
+      handler_(handler)
+  {
+  }
+
+  static void do_complete(io_service_impl* owner, operation* base,
+      asio::error_code /*ec*/, std::size_t /*bytes_transferred*/)
+  {
+    // Take ownership of the handler object.
+    reactive_socket_send_op* o(static_cast<reactive_socket_send_op*>(base));
+    ptr p = { boost::addressof(o->handler_), o, o };
+
+    // Make a copy of the handler so that the memory can be deallocated before
+    // the upcall is made. Even if we're not about to make an upcall, a
+    // sub-object of the handler may be the true owner of the memory associated
+    // with the handler. Consequently, a local copy of the handler is required
+    // to ensure that any owning sub-object remains valid until after we have
+    // deallocated the memory here.
+    detail::binder2<Handler, asio::error_code, std::size_t>
+      handler(o->handler_, o->ec_, o->bytes_transferred_);
+    p.h = boost::addressof(handler.handler_);
+    p.reset();
+
+    // Make the upcall if required.
+    if (owner)
+    {
+      asio::detail::fenced_block b;
+      asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+    }
+  }
+
+private:
+  Handler handler_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_REACTIVE_SOCKET_SEND_OP_HPP
diff --git a/ext/asio/asio/detail/reactive_socket_sendto_op.hpp b/ext/asio/asio/detail/reactive_socket_sendto_op.hpp
new file mode 100644
index 0000000..e466a25
--- /dev/null
+++ b/ext/asio/asio/detail/reactive_socket_sendto_op.hpp
@@ -0,0 +1,118 @@
+//
+// detail/reactive_socket_sendto_op.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_REACTIVE_SOCKET_SENDTO_OP_HPP
+#define ASIO_DETAIL_REACTIVE_SOCKET_SENDTO_OP_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+#include <boost/utility/addressof.hpp>
+#include "asio/detail/bind_handler.hpp"
+#include "asio/detail/buffer_sequence_adapter.hpp"
+#include "asio/detail/fenced_block.hpp"
+#include "asio/detail/reactor_op.hpp"
+#include "asio/detail/socket_ops.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename ConstBufferSequence, typename Endpoint>
+class reactive_socket_sendto_op_base : public reactor_op
+{
+public:
+  reactive_socket_sendto_op_base(socket_type socket,
+      const ConstBufferSequence& buffers, const Endpoint& endpoint,
+      socket_base::message_flags flags, func_type complete_func)
+    : reactor_op(&reactive_socket_sendto_op_base::do_perform, complete_func),
+      socket_(socket),
+      buffers_(buffers),
+      destination_(endpoint),
+      flags_(flags)
+  {
+  }
+
+  static bool do_perform(reactor_op* base)
+  {
+    reactive_socket_sendto_op_base* o(
+        static_cast<reactive_socket_sendto_op_base*>(base));
+
+    buffer_sequence_adapter<asio::const_buffer,
+        ConstBufferSequence> bufs(o->buffers_);
+
+    return socket_ops::non_blocking_sendto(o->socket_,
+          bufs.buffers(), bufs.count(), o->flags_,
+          o->destination_.data(), o->destination_.size(),
+          o->ec_, o->bytes_transferred_);
+  }
+
+private:
+  socket_type socket_;
+  ConstBufferSequence buffers_;
+  Endpoint destination_;
+  socket_base::message_flags flags_;
+};
+
+template <typename ConstBufferSequence, typename Endpoint, typename Handler>
+class reactive_socket_sendto_op :
+  public reactive_socket_sendto_op_base<ConstBufferSequence, Endpoint>
+{
+public:
+  ASIO_DEFINE_HANDLER_PTR(reactive_socket_sendto_op);
+
+  reactive_socket_sendto_op(socket_type socket,
+      const ConstBufferSequence& buffers, const Endpoint& endpoint,
+      socket_base::message_flags flags, Handler handler)
+    : reactive_socket_sendto_op_base<ConstBufferSequence, Endpoint>(socket,
+        buffers, endpoint, flags, &reactive_socket_sendto_op::do_complete),
+      handler_(handler)
+  {
+  }
+
+  static void do_complete(io_service_impl* owner, operation* base,
+      asio::error_code /*ec*/, std::size_t /*bytes_transferred*/)
+  {
+    // Take ownership of the handler object.
+    reactive_socket_sendto_op* o(static_cast<reactive_socket_sendto_op*>(base));
+    ptr p = { boost::addressof(o->handler_), o, o };
+
+    // Make a copy of the handler so that the memory can be deallocated before
+    // the upcall is made. Even if we're not about to make an upcall, a
+    // sub-object of the handler may be the true owner of the memory associated
+    // with the handler. Consequently, a local copy of the handler is required
+    // to ensure that any owning sub-object remains valid until after we have
+    // deallocated the memory here.
+    detail::binder2<Handler, asio::error_code, std::size_t>
+      handler(o->handler_, o->ec_, o->bytes_transferred_);
+    p.h = boost::addressof(handler.handler_);
+    p.reset();
+
+    // Make the upcall if required.
+    if (owner)
+    {
+      asio::detail::fenced_block b;
+      asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+    }
+  }
+
+private:
+  Handler handler_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_REACTIVE_SOCKET_SENDTO_OP_HPP
diff --git a/ext/asio/asio/detail/reactive_socket_service.hpp b/ext/asio/asio/detail/reactive_socket_service.hpp
index 20bd512..daa9f60 100644
--- a/ext/asio/asio/detail/reactive_socket_service.hpp
+++ b/ext/asio/asio/detail/reactive_socket_service.hpp
@@ -1,8 +1,8 @@
 //
-// reactive_socket_service.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// detail/reactive_socket_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,28 +15,37 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
+
+#if !defined(ASIO_HAS_IOCP)
 
+#include <boost/utility/addressof.hpp>
 #include "asio/buffer.hpp"
 #include "asio/error.hpp"
 #include "asio/io_service.hpp"
 #include "asio/socket_base.hpp"
-#include "asio/detail/bind_handler.hpp"
 #include "asio/detail/buffer_sequence_adapter.hpp"
-#include "asio/detail/fenced_block.hpp"
 #include "asio/detail/noncopyable.hpp"
-#include "asio/detail/null_buffers_op.hpp"
+#include "asio/detail/reactive_null_buffers_op.hpp"
+#include "asio/detail/reactive_socket_accept_op.hpp"
+#include "asio/detail/reactive_socket_connect_op.hpp"
+#include "asio/detail/reactive_socket_recvfrom_op.hpp"
+#include "asio/detail/reactive_socket_sendto_op.hpp"
+#include "asio/detail/reactive_socket_service_base.hpp"
 #include "asio/detail/reactor.hpp"
 #include "asio/detail/reactor_op.hpp"
 #include "asio/detail/socket_holder.hpp"
 #include "asio/detail/socket_ops.hpp"
 #include "asio/detail/socket_types.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 namespace detail {
 
 template <typename Protocol>
-class reactive_socket_service
+class reactive_socket_service :
+  public reactive_socket_service_base
 {
 public:
   // The protocol type.
@@ -49,132 +58,32 @@ public:
   typedef socket_type native_type;
 
   // The implementation type of the socket.
-  class implementation_type
-    : private asio::detail::noncopyable
+  struct implementation_type :
+    reactive_socket_service_base::base_implementation_type
   {
-  public:
     // Default constructor.
     implementation_type()
-      : socket_(invalid_socket),
-        flags_(0),
-        protocol_(endpoint_type().protocol())
+      : protocol_(endpoint_type().protocol())
     {
     }
 
-  private:
-    // Only this service will have access to the internal values.
-    friend class reactive_socket_service<Protocol>;
-
-    // The native socket representation.
-    socket_type socket_;
-
-    enum
-    {
-      // The user wants a non-blocking socket.
-      user_set_non_blocking = 1,
-
-      // The implementation wants a non-blocking socket (in order to be able to
-      // perform asynchronous read and write operations).
-      internal_non_blocking = 2,
-
-      // Helper "flag" used to determine whether the socket is non-blocking.
-      non_blocking = user_set_non_blocking | internal_non_blocking,
-
-      // User wants connection_aborted errors, which are disabled by default.
-      enable_connection_aborted = 4,
-
-      // The user set the linger option. Needs to be checked when closing.
-      user_set_linger = 8
-    };
-
-    // Flags indicating the current state of the socket.
-    unsigned char flags_;
-
     // The protocol associated with the socket.
     protocol_type protocol_;
-
-    // Per-descriptor data used by the reactor.
-    reactor::per_descriptor_data reactor_data_;
   };
 
   // Constructor.
   reactive_socket_service(asio::io_service& io_service)
-    : io_service_impl_(use_service<io_service_impl>(io_service)),
-      reactor_(use_service<reactor>(io_service))
-  {
-    reactor_.init_task();
-  }
-
-  // Destroy all user-defined handler objects owned by the service.
-  void shutdown_service()
-  {
-  }
-
-  // Construct a new socket implementation.
-  void construct(implementation_type& impl)
+    : reactive_socket_service_base(io_service)
   {
-    impl.socket_ = invalid_socket;
-    impl.flags_ = 0;
-  }
-
-  // Destroy a socket implementation.
-  void destroy(implementation_type& impl)
-  {
-    if (impl.socket_ != invalid_socket)
-    {
-      reactor_.close_descriptor(impl.socket_, impl.reactor_data_);
-
-      if (impl.flags_ & implementation_type::non_blocking)
-      {
-        ioctl_arg_type non_blocking = 0;
-        asio::error_code ignored_ec;
-        socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ignored_ec);
-        impl.flags_ &= ~implementation_type::non_blocking;
-      }
-
-      if (impl.flags_ & implementation_type::user_set_linger)
-      {
-        ::linger opt;
-        opt.l_onoff = 0;
-        opt.l_linger = 0;
-        asio::error_code ignored_ec;
-        socket_ops::setsockopt(impl.socket_,
-            SOL_SOCKET, SO_LINGER, &opt, sizeof(opt), ignored_ec);
-      }
-
-      asio::error_code ignored_ec;
-      socket_ops::close(impl.socket_, ignored_ec);
-
-      impl.socket_ = invalid_socket;
-    }
   }
 
   // Open a new socket implementation.
   asio::error_code open(implementation_type& impl,
       const protocol_type& protocol, asio::error_code& ec)
   {
-    if (is_open(impl))
-    {
-      ec = asio::error::already_open;
-      return ec;
-    }
-
-    socket_holder sock(socket_ops::socket(protocol.family(),
-          protocol.type(), protocol.protocol(), ec));
-    if (sock.get() == invalid_socket)
-      return ec;
-
-    if (int err = reactor_.register_descriptor(sock.get(), impl.reactor_data_))
-    {
-      ec = asio::error_code(err,
-          asio::error::get_system_category());
-      return ec;
-    }
-
-    impl.socket_ = sock.release();
-    impl.flags_ = 0;
-    impl.protocol_ = protocol;
-    ec = asio::error_code();
+    if (!do_open(impl, protocol.family(),
+          protocol.type(), protocol.protocol(), ec))
+      impl.protocol_ = protocol;
     return ec;
   }
 
@@ -183,56 +92,8 @@ public:
       const protocol_type& protocol, const native_type& native_socket,
       asio::error_code& ec)
   {
-    if (is_open(impl))
-    {
-      ec = asio::error::already_open;
-      return ec;
-    }
-
-    if (int err = reactor_.register_descriptor(
-          native_socket, impl.reactor_data_))
-    {
-      ec = asio::error_code(err,
-          asio::error::get_system_category());
-      return ec;
-    }
-
-    impl.socket_ = native_socket;
-    impl.flags_ = 0;
-    impl.protocol_ = protocol;
-    ec = asio::error_code();
-    return ec;
-  }
-
-  // Determine whether the socket is open.
-  bool is_open(const implementation_type& impl) const
-  {
-    return impl.socket_ != invalid_socket;
-  }
-
-  // Destroy a socket implementation.
-  asio::error_code close(implementation_type& impl,
-      asio::error_code& ec)
-  {
-    if (is_open(impl))
-    {
-      reactor_.close_descriptor(impl.socket_, impl.reactor_data_);
-
-      if (impl.flags_ & implementation_type::non_blocking)
-      {
-        ioctl_arg_type non_blocking = 0;
-        asio::error_code ignored_ec;
-        socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ignored_ec);
-        impl.flags_ &= ~implementation_type::non_blocking;
-      }
-
-      if (socket_ops::close(impl.socket_, ec) == socket_error_retval)
-        return ec;
-
-      impl.socket_ = invalid_socket;
-    }
-
-    ec = asio::error_code();
+    if (!do_assign(impl, protocol.type(), native_socket, ec))
+      impl.protocol_ = protocol;
     return ec;
   }
 
@@ -242,153 +103,23 @@ public:
     return impl.socket_;
   }
 
-  // Cancel all operations associated with the socket.
-  asio::error_code cancel(implementation_type& impl,
-      asio::error_code& ec)
-  {
-    if (!is_open(impl))
-    {
-      ec = asio::error::bad_descriptor;
-      return ec;
-    }
-
-    reactor_.cancel_ops(impl.socket_, impl.reactor_data_);
-    ec = asio::error_code();
-    return ec;
-  }
-
-  // Determine whether the socket is at the out-of-band data mark.
-  bool at_mark(const implementation_type& impl,
-      asio::error_code& ec) const
-  {
-    if (!is_open(impl))
-    {
-      ec = asio::error::bad_descriptor;
-      return false;
-    }
-
-#if defined(SIOCATMARK)
-    asio::detail::ioctl_arg_type value = 0;
-    socket_ops::ioctl(impl.socket_, SIOCATMARK, &value, ec);
-# if defined(ENOTTY)
-    if (ec.value() == ENOTTY)
-      ec = asio::error::not_socket;
-# endif // defined(ENOTTY)
-#else // defined(SIOCATMARK)
-    int value = sockatmark(impl.socket_);
-    if (value == -1)
-      ec = asio::error_code(errno,
-          asio::error::get_system_category());
-    else
-      ec = asio::error_code();
-#endif // defined(SIOCATMARK)
-    return ec ? false : value != 0;
-  }
-
-  // Determine the number of bytes available for reading.
-  std::size_t available(const implementation_type& impl,
-      asio::error_code& ec) const
-  {
-    if (!is_open(impl))
-    {
-      ec = asio::error::bad_descriptor;
-      return 0;
-    }
-
-    asio::detail::ioctl_arg_type value = 0;
-    socket_ops::ioctl(impl.socket_, FIONREAD, &value, ec);
-#if defined(ENOTTY)
-    if (ec.value() == ENOTTY)
-      ec = asio::error::not_socket;
-#endif // defined(ENOTTY)
-    return ec ? static_cast<std::size_t>(0) : static_cast<std::size_t>(value);
-  }
-
   // Bind the socket to the specified local endpoint.
   asio::error_code bind(implementation_type& impl,
       const endpoint_type& endpoint, asio::error_code& ec)
   {
-    if (!is_open(impl))
-    {
-      ec = asio::error::bad_descriptor;
-      return ec;
-    }
-
     socket_ops::bind(impl.socket_, endpoint.data(), endpoint.size(), ec);
     return ec;
   }
 
-  // Place the socket into the state where it will listen for new connections.
-  asio::error_code listen(implementation_type& impl, int backlog,
-      asio::error_code& ec)
-  {
-    if (!is_open(impl))
-    {
-      ec = asio::error::bad_descriptor;
-      return ec;
-    }
-
-    socket_ops::listen(impl.socket_, backlog, ec);
-    return ec;
-  }
-
   // Set a socket option.
   template <typename Option>
   asio::error_code set_option(implementation_type& impl,
       const Option& option, asio::error_code& ec)
   {
-    if (!is_open(impl))
-    {
-      ec = asio::error::bad_descriptor;
-      return ec;
-    }
-
-    if (option.level(impl.protocol_) == custom_socket_option_level
-        && option.name(impl.protocol_) == enable_connection_aborted_option)
-    {
-      if (option.size(impl.protocol_) != sizeof(int))
-      {
-        ec = asio::error::invalid_argument;
-      }
-      else
-      {
-        if (*reinterpret_cast<const int*>(option.data(impl.protocol_)))
-          impl.flags_ |= implementation_type::enable_connection_aborted;
-        else
-          impl.flags_ &= ~implementation_type::enable_connection_aborted;
-        ec = asio::error_code();
-      }
-      return ec;
-    }
-    else
-    {
-      if (option.level(impl.protocol_) == SOL_SOCKET
-          && option.name(impl.protocol_) == SO_LINGER)
-      {
-        impl.flags_ |= implementation_type::user_set_linger;
-      }
-
-      socket_ops::setsockopt(impl.socket_,
-          option.level(impl.protocol_), option.name(impl.protocol_),
-          option.data(impl.protocol_), option.size(impl.protocol_), ec);
-
-#if defined(__MACH__) && defined(__APPLE__) \
-|| defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
-      // To implement portable behaviour for SO_REUSEADDR with UDP sockets we
-      // need to also set SO_REUSEPORT on BSD-based platforms.
-      if (!ec && impl.protocol_.type() == SOCK_DGRAM
-          && option.level(impl.protocol_) == SOL_SOCKET
-          && option.name(impl.protocol_) == SO_REUSEADDR)
-      {
-        asio::error_code ignored_ec;
-        socket_ops::setsockopt(impl.socket_, SOL_SOCKET, SO_REUSEPORT,
-            option.data(impl.protocol_), option.size(impl.protocol_),
-            ignored_ec);
-      }
-#endif
-
-      return ec;
-    }
+    socket_ops::setsockopt(impl.socket_, impl.state_,
+        option.level(impl.protocol_), option.name(impl.protocol_),
+        option.data(impl.protocol_), option.size(impl.protocol_), ec);
+    return ec;
   }
 
   // Set a socket option.
@@ -396,78 +127,12 @@ public:
   asio::error_code get_option(const implementation_type& impl,
       Option& option, asio::error_code& ec) const
   {
-    if (!is_open(impl))
-    {
-      ec = asio::error::bad_descriptor;
-      return ec;
-    }
-
-    if (option.level(impl.protocol_) == custom_socket_option_level
-        && option.name(impl.protocol_) == enable_connection_aborted_option)
-    {
-      if (option.size(impl.protocol_) != sizeof(int))
-      {
-        ec = asio::error::invalid_argument;
-      }
-      else
-      {
-        int* target = reinterpret_cast<int*>(option.data(impl.protocol_));
-        if (impl.flags_ & implementation_type::enable_connection_aborted)
-          *target = 1;
-        else
-          *target = 0;
-        option.resize(impl.protocol_, sizeof(int));
-        ec = asio::error_code();
-      }
-      return ec;
-    }
-    else
-    {
-      size_t size = option.size(impl.protocol_);
-      socket_ops::getsockopt(impl.socket_,
-          option.level(impl.protocol_), option.name(impl.protocol_),
-          option.data(impl.protocol_), &size, ec);
-      if (!ec)
-        option.resize(impl.protocol_, size);
-      return ec;
-    }
-  }
-
-  // Perform an IO control command on the socket.
-  template <typename IO_Control_Command>
-  asio::error_code io_control(implementation_type& impl,
-      IO_Control_Command& command, asio::error_code& ec)
-  {
-    if (!is_open(impl))
-    {
-      ec = asio::error::bad_descriptor;
-      return ec;
-    }
-
-    socket_ops::ioctl(impl.socket_, command.name(),
-        static_cast<ioctl_arg_type*>(command.data()), ec);
-
-    // When updating the non-blocking mode we always perform the ioctl
-    // syscall, even if the flags would otherwise indicate that the socket is
-    // already in the correct state. This ensures that the underlying socket
-    // is put into the state that has been requested by the user. If the ioctl
-    // syscall was successful then we need to update the flags to match.
-    if (!ec && command.name() == static_cast<int>(FIONBIO))
-    {
-      if (*static_cast<ioctl_arg_type*>(command.data()))
-      {
-        impl.flags_ |= implementation_type::user_set_non_blocking;
-      }
-      else
-      {
-        // Clearing the non-blocking mode always overrides any internally-set
-        // non-blocking flag. Any subsequent asynchronous operations will need
-        // to re-enable non-blocking I/O.
-        impl.flags_ &= ~(implementation_type::user_set_non_blocking
-            | implementation_type::internal_non_blocking);
-      }
-    }
-
+    std::size_t size = option.size(impl.protocol_);
+    socket_ops::getsockopt(impl.socket_, impl.state_,
+        option.level(impl.protocol_), option.name(impl.protocol_),
+        option.data(impl.protocol_), &size, ec);
+    if (!ec)
+      option.resize(impl.protocol_, size);
     return ec;
   }
 
@@ -475,12 +140,6 @@ public:
   endpoint_type local_endpoint(const implementation_type& impl,
       asio::error_code& ec) const
   {
-    if (!is_open(impl))
-    {
-      ec = asio::error::bad_descriptor;
-      return endpoint_type();
-    }
-
     endpoint_type endpoint;
     std::size_t addr_len = endpoint.capacity();
     if (socket_ops::getsockname(impl.socket_, endpoint.data(), &addr_len, ec))
@@ -493,218 +152,15 @@ public:
   endpoint_type remote_endpoint(const implementation_type& impl,
       asio::error_code& ec) const
   {
-    if (!is_open(impl))
-    {
-      ec = asio::error::bad_descriptor;
-      return endpoint_type();
-    }
-
     endpoint_type endpoint;
     std::size_t addr_len = endpoint.capacity();
-    if (socket_ops::getpeername(impl.socket_, endpoint.data(), &addr_len, ec))
+    if (socket_ops::getpeername(impl.socket_,
+          endpoint.data(), &addr_len, false, ec))
       return endpoint_type();
     endpoint.resize(addr_len);
     return endpoint;
   }
 
-  /// Disable sends or receives on the socket.
-  asio::error_code shutdown(implementation_type& impl,
-      socket_base::shutdown_type what, asio::error_code& ec)
-  {
-    if (!is_open(impl))
-    {
-      ec = asio::error::bad_descriptor;
-      return ec;
-    }
-
-    socket_ops::shutdown(impl.socket_, what, ec);
-    return ec;
-  }
-
-  // Send the given data to the peer.
-  template <typename ConstBufferSequence>
-  size_t send(implementation_type& impl, const ConstBufferSequence& buffers,
-      socket_base::message_flags flags, asio::error_code& ec)
-  {
-    if (!is_open(impl))
-    {
-      ec = asio::error::bad_descriptor;
-      return 0;
-    }
-
-    buffer_sequence_adapter<asio::const_buffer,
-        ConstBufferSequence> bufs(buffers);
-
-    // A request to receive 0 bytes on a stream socket is a no-op.
-    if (impl.protocol_.type() == SOCK_STREAM && bufs.all_empty())
-    {
-      ec = asio::error_code();
-      return 0;
-    }
-
-    // Send the data.
-    for (;;)
-    {
-      // Try to complete the operation without blocking.
-      int bytes_sent = socket_ops::send(impl.socket_,
-          bufs.buffers(), bufs.count(), flags, ec);
-
-      // Check if operation succeeded.
-      if (bytes_sent >= 0)
-        return bytes_sent;
-
-      // Operation failed.
-      if ((impl.flags_ & implementation_type::user_set_non_blocking)
-          || (ec != asio::error::would_block
-            && ec != asio::error::try_again))
-        return 0;
-
-      // Wait for socket to become ready.
-      if (socket_ops::poll_write(impl.socket_, ec) < 0)
-        return 0;
-    }
-  }
-
-  // Wait until data can be sent without blocking.
-  size_t send(implementation_type& impl, const null_buffers&,
-      socket_base::message_flags, asio::error_code& ec)
-  {
-    if (!is_open(impl))
-    {
-      ec = asio::error::bad_descriptor;
-      return 0;
-    }
-
-    // Wait for socket to become ready.
-    socket_ops::poll_write(impl.socket_, ec);
-
-    return 0;
-  }
-
-  template <typename ConstBufferSequence>
-  class send_op_base : public reactor_op
-  {
-  public:
-    send_op_base(socket_type socket, const ConstBufferSequence& buffers,
-        socket_base::message_flags flags, func_type complete_func)
-      : reactor_op(&send_op_base::do_perform, complete_func),
-        socket_(socket),
-        buffers_(buffers),
-        flags_(flags)
-    {
-    }
-
-    static bool do_perform(reactor_op* base)
-    {
-      send_op_base* o(static_cast<send_op_base*>(base));
-
-      buffer_sequence_adapter<asio::const_buffer,
-          ConstBufferSequence> bufs(o->buffers_);
-
-      for (;;)
-      {
-        // Send the data.
-        asio::error_code ec;
-        int bytes = socket_ops::send(o->socket_,
-            bufs.buffers(), bufs.count(), o->flags_, ec);
-
-        // Retry operation if interrupted by signal.
-        if (ec == asio::error::interrupted)
-          continue;
-
-        // Check if we need to run the operation again.
-        if (ec == asio::error::would_block
-            || ec == asio::error::try_again)
-          return false;
-
-        o->ec_ = ec;
-        o->bytes_transferred_ = (bytes < 0 ? 0 : bytes);
-        return true;
-      }
-    }
-
-  private:
-    socket_type socket_;
-    ConstBufferSequence buffers_;
-    socket_base::message_flags flags_;
-  };
-
-  template <typename ConstBufferSequence, typename Handler>
-  class send_op : public send_op_base<ConstBufferSequence>
-  {
-  public:
-    send_op(socket_type socket, const ConstBufferSequence& buffers,
-        socket_base::message_flags flags, Handler handler)
-      : send_op_base<ConstBufferSequence>(socket,
-          buffers, flags, &send_op::do_complete),
-        handler_(handler)
-    {
-    }
-
-    static void do_complete(io_service_impl* owner, operation* base,
-        asio::error_code /*ec*/, std::size_t /*bytes_transferred*/)
-    {
-      // Take ownership of the handler object.
-      send_op* o(static_cast<send_op*>(base));
-      typedef handler_alloc_traits<Handler, send_op> alloc_traits;
-      handler_ptr<alloc_traits> ptr(o->handler_, o);
-
-      // Make the upcall if required.
-      if (owner)
-      {
-        // Make a copy of the handler so that the memory can be deallocated
-        // before the upcall is made. Even if we're not about to make an
-        // upcall, a sub-object of the handler may be the true owner of the
-        // memory associated with the handler. Consequently, a local copy of
-        // the handler is required to ensure that any owning sub-object remains
-        // valid until after we have deallocated the memory here.
-        detail::binder2<Handler, asio::error_code, std::size_t>
-          handler(o->handler_, o->ec_, o->bytes_transferred_);
-        ptr.reset();
-        asio::detail::fenced_block b;
-        asio_handler_invoke_helpers::invoke(handler, handler);
-      }
-    }
-
-  private:
-    Handler handler_;
-  };
-
-  // Start an asynchronous send. The data being sent must be valid for the
-  // lifetime of the asynchronous operation.
-  template <typename ConstBufferSequence, typename Handler>
-  void async_send(implementation_type& impl, const ConstBufferSequence& buffers,
-      socket_base::message_flags flags, Handler handler)
-  {
-    // Allocate and construct an operation to wrap the handler.
-    typedef send_op<ConstBufferSequence, Handler> value_type;
-    typedef handler_alloc_traits<Handler, value_type> alloc_traits;
-    raw_handler_ptr<alloc_traits> raw_ptr(handler);
-    handler_ptr<alloc_traits> ptr(raw_ptr,
-        impl.socket_, buffers, flags, handler);
-
-    start_op(impl, reactor::write_op, ptr.get(), true,
-        (impl.protocol_.type() == SOCK_STREAM
-          && buffer_sequence_adapter<asio::const_buffer,
-            ConstBufferSequence>::all_empty(buffers)));
-    ptr.release();
-  }
-
-  // Start an asynchronous wait until data can be sent without blocking.
-  template <typename Handler>
-  void async_send(implementation_type& impl, const null_buffers&,
-      socket_base::message_flags, Handler handler)
-  {
-    // Allocate and construct an operation to wrap the handler.
-    typedef null_buffers_op<Handler> value_type;
-    typedef handler_alloc_traits<Handler, value_type> alloc_traits;
-    raw_handler_ptr<alloc_traits> raw_ptr(handler);
-    handler_ptr<alloc_traits> ptr(raw_ptr, handler);
-
-    start_op(impl, reactor::write_op, ptr.get(), false, false);
-    ptr.release();
-  }
-
   // Send a datagram to the specified endpoint. Returns the number of bytes
   // sent.
   template <typename ConstBufferSequence>
@@ -712,148 +168,25 @@ public:
       const endpoint_type& destination, socket_base::message_flags flags,
       asio::error_code& ec)
   {
-    if (!is_open(impl))
-    {
-      ec = asio::error::bad_descriptor;
-      return 0;
-    }
-
     buffer_sequence_adapter<asio::const_buffer,
         ConstBufferSequence> bufs(buffers);
 
-    // Send the data.
-    for (;;)
-    {
-      // Try to complete the operation without blocking.
-      int bytes_sent = socket_ops::sendto(impl.socket_, bufs.buffers(),
-          bufs.count(), flags, destination.data(), destination.size(), ec);
-
-      // Check if operation succeeded.
-      if (bytes_sent >= 0)
-        return bytes_sent;
-
-      // Operation failed.
-      if ((impl.flags_ & implementation_type::user_set_non_blocking)
-          || (ec != asio::error::would_block
-            && ec != asio::error::try_again))
-        return 0;
-
-      // Wait for socket to become ready.
-      if (socket_ops::poll_write(impl.socket_, ec) < 0)
-        return 0;
-    }
+    return socket_ops::sync_sendto(impl.socket_, impl.state_,
+        bufs.buffers(), bufs.count(), flags,
+        destination.data(), destination.size(), ec);
   }
 
   // Wait until data can be sent without blocking.
   size_t send_to(implementation_type& impl, const null_buffers&,
-      socket_base::message_flags, const endpoint_type&,
+      const endpoint_type&, socket_base::message_flags,
       asio::error_code& ec)
   {
-    if (!is_open(impl))
-    {
-      ec = asio::error::bad_descriptor;
-      return 0;
-    }
-
     // Wait for socket to become ready.
     socket_ops::poll_write(impl.socket_, ec);
 
     return 0;
   }
 
-  template <typename ConstBufferSequence>
-  class send_to_op_base : public reactor_op
-  {
-  public:
-    send_to_op_base(socket_type socket, const ConstBufferSequence& buffers,
-        const endpoint_type& endpoint, socket_base::message_flags flags,
-        func_type complete_func)
-      : reactor_op(&send_to_op_base::do_perform, complete_func),
-        socket_(socket),
-        buffers_(buffers),
-        destination_(endpoint),
-        flags_(flags)
-    {
-    }
-
-    static bool do_perform(reactor_op* base)
-    {
-      send_to_op_base* o(static_cast<send_to_op_base*>(base));
-
-      buffer_sequence_adapter<asio::const_buffer,
-          ConstBufferSequence> bufs(o->buffers_);
-
-      for (;;)
-      {
-        // Send the data.
-        asio::error_code ec;
-        int bytes = socket_ops::sendto(o->socket_, bufs.buffers(), bufs.count(),
-            o->flags_, o->destination_.data(), o->destination_.size(), ec);
-
-        // Retry operation if interrupted by signal.
-        if (ec == asio::error::interrupted)
-          continue;
-
-        // Check if we need to run the operation again.
-        if (ec == asio::error::would_block
-            || ec == asio::error::try_again)
-          return false;
-
-        o->ec_ = ec;
-        o->bytes_transferred_ = (bytes < 0 ? 0 : bytes);
-        return true;
-      }
-    }
-
-  private:
-    socket_type socket_;
-    ConstBufferSequence buffers_;
-    endpoint_type destination_;
-    socket_base::message_flags flags_;
-  };
-
-  template <typename ConstBufferSequence, typename Handler>
-  class send_to_op : public send_to_op_base<ConstBufferSequence>
-  {
-  public:
-    send_to_op(socket_type socket, const ConstBufferSequence& buffers,
-        const endpoint_type& endpoint, socket_base::message_flags flags,
-        Handler handler)
-      : send_to_op_base<ConstBufferSequence>(socket,
-          buffers, endpoint, flags, &send_to_op::do_complete),
-        handler_(handler)
-    {
-    }
-
-    static void do_complete(io_service_impl* owner, operation* base,
-        asio::error_code /*ec*/, std::size_t /*bytes_transferred*/)
-    {
-      // Take ownership of the handler object.
-      send_to_op* o(static_cast<send_to_op*>(base));
-      typedef handler_alloc_traits<Handler, send_to_op> alloc_traits;
-      handler_ptr<alloc_traits> ptr(o->handler_, o);
-
-      // Make the upcall if required.
-      if (owner)
-      {
-        // Make a copy of the handler so that the memory can be deallocated
-        // before the upcall is made. Even if we're not about to make an
-        // upcall, a sub-object of the handler may be the true owner of the
-        // memory associated with the handler. Consequently, a local copy of
-        // the handler is required to ensure that any owning sub-object remains
-        // valid until after we have deallocated the memory here.
-        detail::binder2<Handler, asio::error_code, std::size_t>
-          handler(o->handler_, o->ec_, o->bytes_transferred_);
-        ptr.reset();
-        asio::detail::fenced_block b;
-        asio_handler_invoke_helpers::invoke(handler, handler);
-      }
-    }
-
-  private:
-    Handler handler_;
-  };
-
   // Start an asynchronous send. The data being sent must be valid for the
   // lifetime of the asynchronous operation.
   template <typename ConstBufferSequence, typename Handler>
@@ -863,235 +196,31 @@ public:
       Handler handler)
   {
     // Allocate and construct an operation to wrap the handler.
-    typedef send_to_op<ConstBufferSequence, Handler> value_type;
-    typedef handler_alloc_traits<Handler, value_type> alloc_traits;
-    raw_handler_ptr<alloc_traits> raw_ptr(handler);
-    handler_ptr<alloc_traits> ptr(raw_ptr, impl.socket_,
-        buffers, destination, flags, handler);
+    typedef reactive_socket_sendto_op<ConstBufferSequence,
+        endpoint_type, Handler> op;
+    typename op::ptr p = { boost::addressof(handler),
+      asio_handler_alloc_helpers::allocate(
+        sizeof(op), handler), 0 };
+    p.p = new (p.v) op(impl.socket_, buffers, destination, flags, handler);
 
-    start_op(impl, reactor::write_op, ptr.get(), true, false);
-    ptr.release();
+    start_op(impl, reactor::write_op, p.p, true, false);
+    p.v = p.p = 0;
   }
 
   // Start an asynchronous wait until data can be sent without blocking.
   template <typename Handler>
   void async_send_to(implementation_type& impl, const null_buffers&,
-      socket_base::message_flags, const endpoint_type&, Handler handler)
+      const endpoint_type&, socket_base::message_flags, Handler handler)
   {
     // Allocate and construct an operation to wrap the handler.
-    typedef null_buffers_op<Handler> value_type;
-    typedef handler_alloc_traits<Handler, value_type> alloc_traits;
-    raw_handler_ptr<alloc_traits> raw_ptr(handler);
-    handler_ptr<alloc_traits> ptr(raw_ptr, handler);
-
-    start_op(impl, reactor::write_op, ptr.get(), false, false);
-    ptr.release();
-  }
-
-  // Receive some data from the peer. Returns the number of bytes received.
-  template <typename MutableBufferSequence>
-  size_t receive(implementation_type& impl,
-      const MutableBufferSequence& buffers,
-      socket_base::message_flags flags, asio::error_code& ec)
-  {
-    if (!is_open(impl))
-    {
-      ec = asio::error::bad_descriptor;
-      return 0;
-    }
-
-    buffer_sequence_adapter<asio::mutable_buffer,
-        MutableBufferSequence> bufs(buffers);
-
-    // A request to receive 0 bytes on a stream socket is a no-op.
-    if (impl.protocol_.type() == SOCK_STREAM && bufs.all_empty())
-    {
-      ec = asio::error_code();
-      return 0;
-    }
-
-    // Receive some data.
-    for (;;)
-    {
-      // Try to complete the operation without blocking.
-      int bytes_recvd = socket_ops::recv(impl.socket_,
-          bufs.buffers(), bufs.count(), flags, ec);
-
-      // Check if operation succeeded.
-      if (bytes_recvd > 0)
-        return bytes_recvd;
-
-      // Check for EOF.
-      if (bytes_recvd == 0 && impl.protocol_.type() == SOCK_STREAM)
-      {
-        ec = asio::error::eof;
-        return 0;
-      }
-
-      // Operation failed.
-      if ((impl.flags_ & implementation_type::user_set_non_blocking)
-          || (ec != asio::error::would_block
-            && ec != asio::error::try_again))
-        return 0;
-
-      // Wait for socket to become ready.
-      if (socket_ops::poll_read(impl.socket_, ec) < 0)
-        return 0;
-    }
-  }
-
-  // Wait until data can be received without blocking.
-  size_t receive(implementation_type& impl, const null_buffers&,
-      socket_base::message_flags, asio::error_code& ec)
-  {
-    if (!is_open(impl))
-    {
-      ec = asio::error::bad_descriptor;
-      return 0;
-    }
-
-    // Wait for socket to become ready.
-    socket_ops::poll_read(impl.socket_, ec);
+    typedef reactive_null_buffers_op<Handler> op;
+    typename op::ptr p = { boost::addressof(handler),
+      asio_handler_alloc_helpers::allocate(
+        sizeof(op), handler), 0 };
+    p.p = new (p.v) op(handler);
 
-    return 0;
-  }
-
-  template <typename MutableBufferSequence>
-  class receive_op_base : public reactor_op
-  {
-  public:
-    receive_op_base(socket_type socket, int protocol_type,
-        const MutableBufferSequence& buffers,
-        socket_base::message_flags flags, func_type complete_func)
-      : reactor_op(&receive_op_base::do_perform, complete_func),
-        socket_(socket),
-        protocol_type_(protocol_type),
-        buffers_(buffers),
-        flags_(flags)
-    {
-    }
-
-    static bool do_perform(reactor_op* base)
-    {
-      receive_op_base* o(static_cast<receive_op_base*>(base));
-
-      buffer_sequence_adapter<asio::mutable_buffer,
-          MutableBufferSequence> bufs(o->buffers_);
-
-      for (;;)
-      {
-        // Receive some data.
-        asio::error_code ec;
-        int bytes = socket_ops::recv(o->socket_,
-            bufs.buffers(), bufs.count(), o->flags_, ec);
-        if (bytes == 0 && o->protocol_type_ == SOCK_STREAM)
-          ec = asio::error::eof;
-
-        // Retry operation if interrupted by signal.
-        if (ec == asio::error::interrupted)
-          continue;
-
-        // Check if we need to run the operation again.
-        if (ec == asio::error::would_block
-            || ec == asio::error::try_again)
-          return false;
-
-        o->ec_ = ec;
-        o->bytes_transferred_ = (bytes < 0 ? 0 : bytes);
-        return true;
-      }
-    }
-
-  private:
-    socket_type socket_;
-    int protocol_type_;
-    MutableBufferSequence buffers_;
-    socket_base::message_flags flags_;
-  };
-
-  template <typename MutableBufferSequence, typename Handler>
-  class receive_op : public receive_op_base<MutableBufferSequence>
-  {
-  public:
-    receive_op(socket_type socket, int protocol_type,
-        const MutableBufferSequence& buffers,
-        socket_base::message_flags flags, Handler handler)
-      : receive_op_base<MutableBufferSequence>(socket,
-          protocol_type, buffers, flags, &receive_op::do_complete),
-        handler_(handler)
-    {
-    }
-
-    static void do_complete(io_service_impl* owner, operation* base,
-        asio::error_code /*ec*/, std::size_t /*bytes_transferred*/)
-    {
-      // Take ownership of the handler object.
-      receive_op* o(static_cast<receive_op*>(base));
-      typedef handler_alloc_traits<Handler, receive_op> alloc_traits;
-      handler_ptr<alloc_traits> ptr(o->handler_, o);
-
-      // Make the upcall if required.
-      if (owner)
-      {
-        // Make a copy of the handler so that the memory can be deallocated
-        // before the upcall is made. Even if we're not about to make an
-        // upcall, a sub-object of the handler may be the true owner of the
-        // memory associated with the handler. Consequently, a local copy of
-        // the handler is required to ensure that any owning sub-object remains
-        // valid until after we have deallocated the memory here.
-        detail::binder2<Handler, asio::error_code, std::size_t>
-          handler(o->handler_, o->ec_, o->bytes_transferred_);
-        ptr.reset();
-        asio::detail::fenced_block b;
-        asio_handler_invoke_helpers::invoke(handler, handler);
-      }
-    }
-
-  private:
-    Handler handler_;
-  };
-
-  // Start an asynchronous receive. The buffer for the data being received
-  // must be valid for the lifetime of the asynchronous operation.
-  template <typename MutableBufferSequence, typename Handler>
-  void async_receive(implementation_type& impl,
-      const MutableBufferSequence& buffers,
-      socket_base::message_flags flags, Handler handler)
-  {
-    // Allocate and construct an operation to wrap the handler.
-    typedef receive_op<MutableBufferSequence, Handler> value_type;
-    typedef handler_alloc_traits<Handler, value_type> alloc_traits;
-    raw_handler_ptr<alloc_traits> raw_ptr(handler);
-    int protocol_type = impl.protocol_.type();
-    handler_ptr<alloc_traits> ptr(raw_ptr, impl.socket_,
-        protocol_type, buffers, flags, handler);
-
-    start_op(impl,
-        (flags & socket_base::message_out_of_band)
-          ? reactor::except_op : reactor::read_op,
-        ptr.get(), (flags & socket_base::message_out_of_band) == 0,
-        (impl.protocol_.type() == SOCK_STREAM
-          && buffer_sequence_adapter<asio::mutable_buffer,
-            MutableBufferSequence>::all_empty(buffers)));
-    ptr.release();
-  }
-
-  // Wait until data can be received without blocking.
-  template <typename Handler>
-  void async_receive(implementation_type& impl, const null_buffers&,
-      socket_base::message_flags flags, Handler handler)
-  {
-    // Allocate and construct an operation to wrap the handler.
-    typedef null_buffers_op<Handler> value_type;
-    typedef handler_alloc_traits<Handler, value_type> alloc_traits;
-    raw_handler_ptr<alloc_traits> raw_ptr(handler);
-    handler_ptr<alloc_traits> ptr(raw_ptr, handler);
-
-    start_op(impl,
-        (flags & socket_base::message_out_of_band)
-          ? reactor::except_op : reactor::read_op,
-        ptr.get(), false, false);
-    ptr.release();
+    start_op(impl, reactor::write_op, p.p, false, false);
+    p.v = p.p = 0;
   }
 
   // Receive a datagram with the endpoint of the sender. Returns the number of
@@ -1102,47 +231,18 @@ public:
       endpoint_type& sender_endpoint, socket_base::message_flags flags,
       asio::error_code& ec)
   {
-    if (!is_open(impl))
-    {
-      ec = asio::error::bad_descriptor;
-      return 0;
-    }
-
     buffer_sequence_adapter<asio::mutable_buffer,
         MutableBufferSequence> bufs(buffers);
 
-    // Receive some data.
-    for (;;)
-    {
-      // Try to complete the operation without blocking.
-      std::size_t addr_len = sender_endpoint.capacity();
-      int bytes_recvd = socket_ops::recvfrom(impl.socket_, bufs.buffers(),
-          bufs.count(), flags, sender_endpoint.data(), &addr_len, ec);
+    std::size_t addr_len = sender_endpoint.capacity();
+    std::size_t bytes_recvd = socket_ops::sync_recvfrom(
+        impl.socket_, impl.state_, bufs.buffers(), bufs.count(),
+        flags, sender_endpoint.data(), &addr_len, ec);
 
-      // Check if operation succeeded.
-      if (bytes_recvd > 0)
-      {
-        sender_endpoint.resize(addr_len);
-        return bytes_recvd;
-      }
+    if (!ec)
+      sender_endpoint.resize(addr_len);
 
-      // Check for EOF.
-      if (bytes_recvd == 0 && impl.protocol_.type() == SOCK_STREAM)
-      {
-        ec = asio::error::eof;
-        return 0;
-      }
-
-      // Operation failed.
-      if ((impl.flags_ & implementation_type::user_set_non_blocking)
-          || (ec != asio::error::would_block
-            && ec != asio::error::try_again))
-        return 0;
-
-      // Wait for socket to become ready.
-      if (socket_ops::poll_read(impl.socket_, ec) < 0)
-        return 0;
-    }
+    return bytes_recvd;
   }
 
   // Wait until data can be received without blocking.
@@ -1150,12 +250,6 @@ public:
       endpoint_type& sender_endpoint, socket_base::message_flags,
       asio::error_code& ec)
   {
-    if (!is_open(impl))
-    {
-      ec = asio::error::bad_descriptor;
-      return 0;
-    }
-
     // Wait for socket to become ready.
     socket_ops::poll_read(impl.socket_, ec);
 
@@ -1165,105 +259,6 @@ public:
     return 0;
   }
 
-  template <typename MutableBufferSequence>
-  class receive_from_op_base : public reactor_op
-  {
-  public:
-    receive_from_op_base(socket_type socket, int protocol_type,
-        const MutableBufferSequence& buffers, endpoint_type& endpoint,
-        socket_base::message_flags flags, func_type complete_func)
-      : reactor_op(&receive_from_op_base::do_perform, complete_func),
-        socket_(socket),
-        protocol_type_(protocol_type),
-        buffers_(buffers),
-        sender_endpoint_(endpoint),
-        flags_(flags)
-    {
-    }
-
-    static bool do_perform(reactor_op* base)
-    {
-      receive_from_op_base* o(static_cast<receive_from_op_base*>(base));
-
-      buffer_sequence_adapter<asio::mutable_buffer,
-          MutableBufferSequence> bufs(o->buffers_);
-
-      for (;;)
-      {
-        // Receive some data.
-        asio::error_code ec;
-        std::size_t addr_len = o->sender_endpoint_.capacity();
-        int bytes = socket_ops::recvfrom(o->socket_, bufs.buffers(),
-            bufs.count(), o->flags_, o->sender_endpoint_.data(), &addr_len, ec);
-        if (bytes == 0 && o->protocol_type_ == SOCK_STREAM)
-          ec = asio::error::eof;
-
-        // Retry operation if interrupted by signal.
-        if (ec == asio::error::interrupted)
-          continue;
-
-        // Check if we need to run the operation again.
-        if (ec == asio::error::would_block
-            || ec == asio::error::try_again)
-          return false;
-
-        o->sender_endpoint_.resize(addr_len);
-        o->ec_ = ec;
-        o->bytes_transferred_ = (bytes < 0 ? 0 : bytes);
-        return true;
-      }
-    }
-
-  private:
-    socket_type socket_;
-    int protocol_type_;
-    MutableBufferSequence buffers_;
-    endpoint_type& sender_endpoint_;
-    socket_base::message_flags flags_;
-  };
-
-  template <typename MutableBufferSequence, typename Handler>
-  class receive_from_op : public receive_from_op_base<MutableBufferSequence>
-  {
-  public:
-    receive_from_op(socket_type socket, int protocol_type,
-        const MutableBufferSequence& buffers, endpoint_type& endpoint,
-        socket_base::message_flags flags, Handler handler)
-      : receive_from_op_base<MutableBufferSequence>(socket, protocol_type,
-          buffers, endpoint, flags, &receive_from_op::do_complete),
-        handler_(handler)
-    {
-    }
-
-    static void do_complete(io_service_impl* owner, operation* base,
-        asio::error_code /*ec*/, std::size_t /*bytes_transferred*/)
-    {
-      // Take ownership of the handler object.
-      receive_from_op* o(static_cast<receive_from_op*>(base));
-      typedef handler_alloc_traits<Handler, receive_from_op> alloc_traits;
-      handler_ptr<alloc_traits> ptr(o->handler_, o);
-
-      // Make the upcall if required.
-      if (owner)
-      {
-        // Make a copy of the handler so that the memory can be deallocated
-        // before the upcall is made. Even if we're not about to make an
-        // upcall, a sub-object of the handler may be the true owner of the
-        // memory associated with the handler. Consequently, a local copy of
-        // the handler is required to ensure that any owning sub-object remains
-        // valid until after we have deallocated the memory here.
-        detail::binder2<Handler, asio::error_code, std::size_t>
-          handler(o->handler_, o->ec_, o->bytes_transferred_);
-        ptr.reset();
-        asio::detail::fenced_block b;
-        asio_handler_invoke_helpers::invoke(handler, handler);
-      }
-    }
-
-  private:
-    Handler handler_;
-  };
-
   // Start an asynchronous receive. The buffer for the data being received and
   // the sender_endpoint object must both be valid for the lifetime of the
   // asynchronous operation.
@@ -1273,18 +268,20 @@ public:
       socket_base::message_flags flags, Handler handler)
   {
     // Allocate and construct an operation to wrap the handler.
-    typedef receive_from_op<MutableBufferSequence, Handler> value_type;
-    typedef handler_alloc_traits<Handler, value_type> alloc_traits;
-    raw_handler_ptr<alloc_traits> raw_ptr(handler);
+    typedef reactive_socket_recvfrom_op<MutableBufferSequence,
+        endpoint_type, Handler> op;
+    typename op::ptr p = { boost::addressof(handler),
+      asio_handler_alloc_helpers::allocate(
+        sizeof(op), handler), 0 };
     int protocol_type = impl.protocol_.type();
-    handler_ptr<alloc_traits> ptr(raw_ptr, impl.socket_,
-        protocol_type, buffers, sender_endpoint, flags, handler);
+    p.p = new (p.v) op(impl.socket_, protocol_type,
+        buffers, sender_endpoint, flags, handler);
 
     start_op(impl,
         (flags & socket_base::message_out_of_band)
           ? reactor::except_op : reactor::read_op,
-        ptr.get(), true, false);
-    ptr.release();
+        p.p, true, false);
+    p.v = p.p = 0;
   }
 
   // Wait until data can be received without blocking.
@@ -1294,10 +291,11 @@ public:
       socket_base::message_flags flags, Handler handler)
   {
     // Allocate and construct an operation to wrap the handler.
-    typedef null_buffers_op<Handler> value_type;
-    typedef handler_alloc_traits<Handler, value_type> alloc_traits;
-    raw_handler_ptr<alloc_traits> raw_ptr(handler);
-    handler_ptr<alloc_traits> ptr(raw_ptr, handler);
+    typedef reactive_null_buffers_op<Handler> op;
+    typename op::ptr p = { boost::addressof(handler),
+      asio_handler_alloc_helpers::allocate(
+        sizeof(op), handler), 0 };
+    p.p = new (p.v) op(handler);
 
     // Reset endpoint since it can be given no sensible value at this time.
     sender_endpoint = endpoint_type();
@@ -1305,8 +303,8 @@ public:
     start_op(impl,
         (flags & socket_base::message_out_of_band)
           ? reactor::except_op : reactor::read_op,
-        ptr.get(), false, false);
-    ptr.release();
+        p.p, false, false);
+    p.v = p.p = 0;
   }
 
   // Accept a new connection.
@@ -1314,12 +312,6 @@ public:
   asio::error_code accept(implementation_type& impl,
       Socket& peer, endpoint_type* peer_endpoint, asio::error_code& ec)
   {
-    if (!is_open(impl))
-    {
-      ec = asio::error::bad_descriptor;
-      return ec;
-    }
-
     // We cannot accept a socket that is already open.
     if (peer.is_open())
     {
@@ -1327,181 +319,22 @@ public:
       return ec;
     }
 
-    // Accept a socket.
-    for (;;)
-    {
-      // Try to complete the operation without blocking.
-      socket_holder new_socket;
-      std::size_t addr_len = 0;
-      if (peer_endpoint)
-      {
-        addr_len = peer_endpoint->capacity();
-        new_socket.reset(socket_ops::accept(impl.socket_,
-              peer_endpoint->data(), &addr_len, ec));
-      }
-      else
-      {
-        new_socket.reset(socket_ops::accept(impl.socket_, 0, 0, ec));
-      }
-
-      // Check if operation succeeded.
-      if (new_socket.get() >= 0)
-      {
-        if (peer_endpoint)
-          peer_endpoint->resize(addr_len);
-        peer.assign(impl.protocol_, new_socket.get(), ec);
-        if (!ec)
-          new_socket.release();
-        return ec;
-      }
+    std::size_t addr_len = peer_endpoint ? peer_endpoint->capacity() : 0;
+    socket_holder new_socket(socket_ops::sync_accept(impl.socket_,
+          impl.state_, peer_endpoint ? peer_endpoint->data() : 0,
+          peer_endpoint ? &addr_len : 0, ec));
 
-      // Operation failed.
-      if (ec == asio::error::would_block
-          || ec == asio::error::try_again)
-      {
-        if (impl.flags_ & implementation_type::user_set_non_blocking)
-          return ec;
-        // Fall through to retry operation.
-      }
-      else if (ec == asio::error::connection_aborted)
-      {
-        if (impl.flags_ & implementation_type::enable_connection_aborted)
-          return ec;
-        // Fall through to retry operation.
-      }
-#if defined(EPROTO)
-      else if (ec.value() == EPROTO)
-      {
-        if (impl.flags_ & implementation_type::enable_connection_aborted)
-          return ec;
-        // Fall through to retry operation.
-      }
-#endif // defined(EPROTO)
-      else
-        return ec;
-
-      // Wait for socket to become ready.
-      if (socket_ops::poll_read(impl.socket_, ec) < 0)
-        return ec;
-    }
-  }
-
-  template <typename Socket>
-  class accept_op_base : public reactor_op
-  {
-  public:
-    accept_op_base(socket_type socket, Socket& peer,
-        const protocol_type& protocol, endpoint_type* peer_endpoint,
-        bool enable_connection_aborted, func_type complete_func)
-      : reactor_op(&accept_op_base::do_perform, complete_func),
-        socket_(socket),
-        peer_(peer),
-        protocol_(protocol),
-        peer_endpoint_(peer_endpoint),
-        enable_connection_aborted_(enable_connection_aborted)
-    {
-    }
-
-    static bool do_perform(reactor_op* base)
+    // On success, assign new connection to peer socket object.
+    if (new_socket.get() != invalid_socket)
     {
-      accept_op_base* o(static_cast<accept_op_base*>(base));
-
-      for (;;)
-      {
-        // Accept the waiting connection.
-        asio::error_code ec;
-        socket_holder new_socket;
-        std::size_t addr_len = 0;
-        std::size_t* addr_len_p = 0;
-        socket_addr_type* addr = 0;
-        if (o->peer_endpoint_)
-        {
-          addr_len = o->peer_endpoint_->capacity();
-          addr_len_p = &addr_len;
-          addr = o->peer_endpoint_->data();
-        }
-        new_socket.reset(socket_ops::accept(o->socket_, addr, addr_len_p, ec));
-
-        // Retry operation if interrupted by signal.
-        if (ec == asio::error::interrupted)
-          continue;
-
-        // Check if we need to run the operation again.
-        if (ec == asio::error::would_block
-            || ec == asio::error::try_again)
-          return false;
-        if (ec == asio::error::connection_aborted
-            && !o->enable_connection_aborted_)
-          return false;
-#if defined(EPROTO)
-        if (ec.value() == EPROTO && !o->enable_connection_aborted_)
-          return false;
-#endif // defined(EPROTO)
-
-        // Transfer ownership of the new socket to the peer object.
-        if (!ec)
-        {
-          if (o->peer_endpoint_)
-            o->peer_endpoint_->resize(addr_len);
-          o->peer_.assign(o->protocol_, new_socket.get(), ec);
-          if (!ec)
-            new_socket.release();
-        }
-
-        o->ec_ = ec;
-        return true;
-      }
-    }
-
-  private:
-    socket_type socket_;
-    Socket& peer_;
-    protocol_type protocol_;
-    endpoint_type* peer_endpoint_;
-    bool enable_connection_aborted_;
-  };
-
-  template <typename Socket, typename Handler>
-  class accept_op : public accept_op_base<Socket>
-  {
-  public:
-    accept_op(socket_type socket, Socket& peer, const protocol_type& protocol,
-        endpoint_type* peer_endpoint, bool enable_connection_aborted,
-        Handler handler)
-      : accept_op_base<Socket>(socket, peer, protocol, peer_endpoint,
-          enable_connection_aborted, &accept_op::do_complete),
-        handler_(handler)
-    {
-    }
-
-    static void do_complete(io_service_impl* owner, operation* base,
-        asio::error_code /*ec*/, std::size_t /*bytes_transferred*/)
-    {
-      // Take ownership of the handler object.
-      accept_op* o(static_cast<accept_op*>(base));
-      typedef handler_alloc_traits<Handler, accept_op> alloc_traits;
-      handler_ptr<alloc_traits> ptr(o->handler_, o);
-
-      // Make the upcall if required.
-      if (owner)
-      {
-        // Make a copy of the handler so that the memory can be deallocated
-        // before the upcall is made. Even if we're not about to make an
-        // upcall, a sub-object of the handler may be the true owner of the
-        // memory associated with the handler. Consequently, a local copy of
-        // the handler is required to ensure that any owning sub-object remains
-        // valid until after we have deallocated the memory here.
-        detail::binder1<Handler, asio::error_code>
-          handler(o->handler_, o->ec_);
-        ptr.reset();
-        asio::detail::fenced_block b;
-        asio_handler_invoke_helpers::invoke(handler, handler);
-      }
+      if (peer_endpoint)
+        peer_endpoint->resize(addr_len);
+      if (!peer.assign(impl.protocol_, new_socket.get(), ec))
+        new_socket.release();
     }
 
-  private:
-    Handler handler_;
-  };
+    return ec;
+  }
 
   // Start an asynchronous accept. The peer and peer_endpoint objects
   // must be valid until the accept's handler is invoked.
@@ -1510,230 +343,41 @@ public:
       endpoint_type* peer_endpoint, Handler handler)
   {
     // Allocate and construct an operation to wrap the handler.
-    typedef accept_op<Socket, Handler> value_type;
-    typedef handler_alloc_traits<Handler, value_type> alloc_traits;
-    raw_handler_ptr<alloc_traits> raw_ptr(handler);
-    bool enable_connection_aborted =
-      (impl.flags_ & implementation_type::enable_connection_aborted) != 0;
-    handler_ptr<alloc_traits> ptr(raw_ptr, impl.socket_, peer,
-        impl.protocol_, peer_endpoint, enable_connection_aborted, handler);
+    typedef reactive_socket_accept_op<Socket, Protocol, Handler> op;
+    typename op::ptr p = { boost::addressof(handler),
+      asio_handler_alloc_helpers::allocate(
+        sizeof(op), handler), 0 };
+    p.p = new (p.v) op(impl.socket_, impl.state_, peer,
+        impl.protocol_, peer_endpoint, handler);
 
-    start_accept_op(impl, ptr.get(), peer.is_open());
-    ptr.release();
+    start_accept_op(impl, p.p, peer.is_open());
+    p.v = p.p = 0;
   }
 
   // Connect the socket to the specified endpoint.
   asio::error_code connect(implementation_type& impl,
       const endpoint_type& peer_endpoint, asio::error_code& ec)
   {
-    if (!is_open(impl))
-    {
-      ec = asio::error::bad_descriptor;
-      return ec;
-    }
-
-    // Perform the connect operation.
-    socket_ops::connect(impl.socket_,
+    socket_ops::sync_connect(impl.socket_,
         peer_endpoint.data(), peer_endpoint.size(), ec);
-    if (ec != asio::error::in_progress
-        && ec != asio::error::would_block)
-    {
-      // The connect operation finished immediately.
-      return ec;
-    }
-
-    // Wait for socket to become ready.
-    if (socket_ops::poll_connect(impl.socket_, ec) < 0)
-      return ec;
-
-    // Get the error code from the connect operation.
-    int connect_error = 0;
-    size_t connect_error_len = sizeof(connect_error);
-    if (socket_ops::getsockopt(impl.socket_, SOL_SOCKET, SO_ERROR,
-          &connect_error, &connect_error_len, ec) == socket_error_retval)
-      return ec;
-
-    // Return the result of the connect operation.
-    ec = asio::error_code(connect_error,
-        asio::error::get_system_category());
     return ec;
   }
 
-  class connect_op_base : public reactor_op
-  {
-  public:
-    connect_op_base(socket_type socket, func_type complete_func)
-      : reactor_op(&connect_op_base::do_perform, complete_func),
-        socket_(socket)
-    {
-    }
-
-    static bool do_perform(reactor_op* base)
-    {
-      connect_op_base* o(static_cast<connect_op_base*>(base));
-
-      // Get the error code from the connect operation.
-      int connect_error = 0;
-      size_t connect_error_len = sizeof(connect_error);
-      if (socket_ops::getsockopt(o->socket_, SOL_SOCKET, SO_ERROR,
-            &connect_error, &connect_error_len, o->ec_) == socket_error_retval)
-        return true;
-
-      // The connection failed so the handler will be posted with an error code.
-      if (connect_error)
-      {
-        o->ec_ = asio::error_code(connect_error,
-            asio::error::get_system_category());
-      }
-
-      return true;
-    }
-
-  private:
-    socket_type socket_;
-  };
-
-  template <typename Handler>
-  class connect_op : public connect_op_base
-  {
-  public:
-    connect_op(socket_type socket, Handler handler)
-      : connect_op_base(socket, &connect_op::do_complete),
-        handler_(handler)
-    {
-    }
-
-    static void do_complete(io_service_impl* owner, operation* base,
-        asio::error_code /*ec*/, std::size_t /*bytes_transferred*/)
-    {
-      // Take ownership of the handler object.
-      connect_op* o(static_cast<connect_op*>(base));
-      typedef handler_alloc_traits<Handler, connect_op> alloc_traits;
-      handler_ptr<alloc_traits> ptr(o->handler_, o);
-
-      // Make the upcall if required.
-      if (owner)
-      {
-        // Make a copy of the handler so that the memory can be deallocated
-        // before the upcall is made. Even if we're not about to make an
-        // upcall, a sub-object of the handler may be the true owner of the
-        // memory associated with the handler. Consequently, a local copy of
-        // the handler is required to ensure that any owning sub-object remains
-        // valid until after we have deallocated the memory here.
-        detail::binder1<Handler, asio::error_code>
-          handler(o->handler_, o->ec_);
-        ptr.reset();
-        asio::detail::fenced_block b;
-        asio_handler_invoke_helpers::invoke(handler, handler);
-      }
-    }
-
-  private:
-    Handler handler_;
-  };
-
   // Start an asynchronous connect.
   template <typename Handler>
   void async_connect(implementation_type& impl,
       const endpoint_type& peer_endpoint, Handler handler)
   {
     // Allocate and construct an operation to wrap the handler.
-    typedef connect_op<Handler> value_type;
-    typedef handler_alloc_traits<Handler, value_type> alloc_traits;
-    raw_handler_ptr<alloc_traits> raw_ptr(handler);
-    handler_ptr<alloc_traits> ptr(raw_ptr, impl.socket_, handler);
-
-    start_connect_op(impl, ptr.get(), peer_endpoint);
-    ptr.release();
-  }
-
-private:
-  // Start the asynchronous read or write operation.
-  void start_op(implementation_type& impl, int op_type,
-      reactor_op* op, bool non_blocking, bool noop)
-  {
-    if (!noop)
-    {
-      if (is_open(impl))
-      {
-        if (!non_blocking || is_non_blocking(impl)
-            || set_non_blocking(impl, op->ec_))
-        {
-          reactor_.start_op(op_type, impl.socket_,
-              impl.reactor_data_, op, non_blocking);
-          return;
-        }
-      }
-      else
-        op->ec_ = asio::error::bad_descriptor;
-    }
+    typedef reactive_socket_connect_op<Handler> op;
+    typename op::ptr p = { boost::addressof(handler),
+      asio_handler_alloc_helpers::allocate(
+        sizeof(op), handler), 0 };
+    p.p = new (p.v) op(impl.socket_, handler);
 
-    io_service_impl_.post_immediate_completion(op);
+    start_connect_op(impl, p.p, peer_endpoint.data(), peer_endpoint.size());
+    p.v = p.p = 0;
   }
-
-  // Start the asynchronous accept operation.
-  void start_accept_op(implementation_type& impl,
-      reactor_op* op, bool peer_is_open)
-  {
-    if (!peer_is_open)
-      start_op(impl, reactor::read_op, op, true, false);
-    else
-    {
-      op->ec_ = asio::error::already_open;
-      io_service_impl_.post_immediate_completion(op);
-    }
-  }
-
-  // Start the asynchronous connect operation.
-  void start_connect_op(implementation_type& impl,
-      reactor_op* op, const endpoint_type& peer_endpoint)
-  {
-    if (is_open(impl))
-    {
-      if (is_non_blocking(impl) || set_non_blocking(impl, op->ec_))
-      {
-        if (socket_ops::connect(impl.socket_, peer_endpoint.data(),
-              peer_endpoint.size(), op->ec_) != 0)
-        {
-          if (op->ec_ == asio::error::in_progress
-              || op->ec_ == asio::error::would_block)
-          {
-            op->ec_ = asio::error_code();
-            reactor_.start_op(reactor::connect_op,
-                impl.socket_, impl.reactor_data_, op, false);
-            return;
-          }
-        }
-      }
-    }
-    else
-      op->ec_ = asio::error::bad_descriptor;
-
-    io_service_impl_.post_immediate_completion(op);
-  }
-
-  // Determine whether the socket has been set non-blocking.
-  bool is_non_blocking(implementation_type& impl) const
-  {
-    return (impl.flags_ & implementation_type::non_blocking);
-  }
-
-  // Set the internal non-blocking flag.
-  bool set_non_blocking(implementation_type& impl,
-      asio::error_code& ec)
-  {
-    ioctl_arg_type non_blocking = 1;
-    if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
-      return false;
-    impl.flags_ |= implementation_type::internal_non_blocking;
-    return true;
-  }
-
-  // The io_service implementation used to post completions.
-  io_service_impl& io_service_impl_;
-
-  // The selector that performs event demultiplexing for the service.
-  reactor& reactor_;
 };
 
 } // namespace detail
@@ -1741,4 +385,6 @@ private:
 
 #include "asio/detail/pop_options.hpp"
 
+#endif // !defined(ASIO_HAS_IOCP)
+
 #endif // ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_HPP
diff --git a/ext/asio/asio/detail/reactive_socket_service_base.hpp b/ext/asio/asio/detail/reactive_socket_service_base.hpp
new file mode 100644
index 0000000..b26d73e
--- /dev/null
+++ b/ext/asio/asio/detail/reactive_socket_service_base.hpp
@@ -0,0 +1,298 @@
+//
+// detail/reactive_socket_service_base.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_BASE_HPP
+#define ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_BASE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if !defined(ASIO_HAS_IOCP)
+
+#include <boost/utility/addressof.hpp>
+#include "asio/buffer.hpp"
+#include "asio/error.hpp"
+#include "asio/io_service.hpp"
+#include "asio/socket_base.hpp"
+#include "asio/detail/buffer_sequence_adapter.hpp"
+#include "asio/detail/reactive_null_buffers_op.hpp"
+#include "asio/detail/reactive_socket_recv_op.hpp"
+#include "asio/detail/reactive_socket_send_op.hpp"
+#include "asio/detail/reactor.hpp"
+#include "asio/detail/reactor_op.hpp"
+#include "asio/detail/socket_holder.hpp"
+#include "asio/detail/socket_ops.hpp"
+#include "asio/detail/socket_types.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+class reactive_socket_service_base
+{
+public:
+  // The native type of a socket.
+  typedef socket_type native_type;
+
+  // The implementation type of the socket.
+  struct base_implementation_type
+  {
+    // The native socket representation.
+    socket_type socket_;
+
+    // The current state of the socket.
+    socket_ops::state_type state_;
+
+    // Per-descriptor data used by the reactor.
+    reactor::per_descriptor_data reactor_data_;
+  };
+
+  // Constructor.
+  ASIO_DECL reactive_socket_service_base(
+      asio::io_service& io_service);
+
+  // Destroy all user-defined handler objects owned by the service.
+  ASIO_DECL void shutdown_service();
+
+  // Construct a new socket implementation.
+  ASIO_DECL void construct(base_implementation_type& impl);
+
+  // Destroy a socket implementation.
+  ASIO_DECL void destroy(base_implementation_type& impl);
+
+  // Determine whether the socket is open.
+  bool is_open(const base_implementation_type& impl) const
+  {
+    return impl.socket_ != invalid_socket;
+  }
+
+  // Destroy a socket implementation.
+  ASIO_DECL asio::error_code close(
+      base_implementation_type& impl, asio::error_code& ec);
+
+  // Get the native socket representation.
+  native_type native(base_implementation_type& impl)
+  {
+    return impl.socket_;
+  }
+
+  // Cancel all operations associated with the socket.
+  ASIO_DECL asio::error_code cancel(
+      base_implementation_type& impl, asio::error_code& ec);
+
+  // Determine whether the socket is at the out-of-band data mark.
+  bool at_mark(const base_implementation_type& impl,
+      asio::error_code& ec) const
+  {
+    return socket_ops::sockatmark(impl.socket_, ec);
+  }
+
+  // Determine the number of bytes available for reading.
+  std::size_t available(const base_implementation_type& impl,
+      asio::error_code& ec) const
+  {
+    return socket_ops::available(impl.socket_, ec);
+  }
+
+  // Place the socket into the state where it will listen for new connections.
+  asio::error_code listen(base_implementation_type& impl,
+      int backlog, asio::error_code& ec)
+  {
+    socket_ops::listen(impl.socket_, backlog, ec);
+    return ec;
+  }
+
+  // Perform an IO control command on the socket.
+  template <typename IO_Control_Command>
+  asio::error_code io_control(base_implementation_type& impl,
+      IO_Control_Command& command, asio::error_code& ec)
+  {
+    socket_ops::ioctl(impl.socket_, impl.state_, command.name(),
+        static_cast<ioctl_arg_type*>(command.data()), ec);
+    return ec;
+  }
+
+  /// Disable sends or receives on the socket.
+  asio::error_code shutdown(base_implementation_type& impl,
+      socket_base::shutdown_type what, asio::error_code& ec)
+  {
+    socket_ops::shutdown(impl.socket_, what, ec);
+    return ec;
+  }
+
+  // Send the given data to the peer.
+  template <typename ConstBufferSequence>
+  size_t send(base_implementation_type& impl,
+      const ConstBufferSequence& buffers,
+      socket_base::message_flags flags, asio::error_code& ec)
+  {
+    buffer_sequence_adapter<asio::const_buffer,
+        ConstBufferSequence> bufs(buffers);
+
+    return socket_ops::sync_send(impl.socket_, impl.state_,
+        bufs.buffers(), bufs.count(), flags, bufs.all_empty(), ec);
+  }
+
+  // Wait until data can be sent without blocking.
+  size_t send(base_implementation_type& impl, const null_buffers&,
+      socket_base::message_flags, asio::error_code& ec)
+  {
+    // Wait for socket to become ready.
+    socket_ops::poll_write(impl.socket_, ec);
+
+    return 0;
+  }
+
+  // Start an asynchronous send. The data being sent must be valid for the
+  // lifetime of the asynchronous operation.
+  template <typename ConstBufferSequence, typename Handler>
+  void async_send(base_implementation_type& impl,
+      const ConstBufferSequence& buffers,
+      socket_base::message_flags flags, Handler handler)
+  {
+    // Allocate and construct an operation to wrap the handler.
+    typedef reactive_socket_send_op<ConstBufferSequence, Handler> op;
+    typename op::ptr p = { boost::addressof(handler),
+      asio_handler_alloc_helpers::allocate(
+        sizeof(op), handler), 0 };
+    p.p = new (p.v) op(impl.socket_, buffers, flags, handler);
+
+    start_op(impl, reactor::write_op, p.p, true,
+        ((impl.state_ & socket_ops::stream_oriented)
+          && buffer_sequence_adapter<asio::const_buffer,
+            ConstBufferSequence>::all_empty(buffers)));
+    p.v = p.p = 0;
+  }
+
+  // Start an asynchronous wait until data can be sent without blocking.
+  template <typename Handler>
+  void async_send(base_implementation_type& impl, const null_buffers&,
+      socket_base::message_flags, Handler handler)
+  {
+    // Allocate and construct an operation to wrap the handler.
+    typedef reactive_null_buffers_op<Handler> op;
+    typename op::ptr p = { boost::addressof(handler),
+      asio_handler_alloc_helpers::allocate(
+        sizeof(op), handler), 0 };
+    p.p = new (p.v) op(handler);
+
+    start_op(impl, reactor::write_op, p.p, false, false);
+    p.v = p.p = 0;
+  }
+
+  // Receive some data from the peer. Returns the number of bytes received.
+  template <typename MutableBufferSequence>
+  size_t receive(base_implementation_type& impl,
+      const MutableBufferSequence& buffers,
+      socket_base::message_flags flags, asio::error_code& ec)
+  {
+    buffer_sequence_adapter<asio::mutable_buffer,
+        MutableBufferSequence> bufs(buffers);
+
+    return socket_ops::sync_recv(impl.socket_, impl.state_,
+        bufs.buffers(), bufs.count(), flags, bufs.all_empty(), ec);
+  }
+
+  // Wait until data can be received without blocking.
+  size_t receive(base_implementation_type& impl, const null_buffers&,
+      socket_base::message_flags, asio::error_code& ec)
+  {
+    // Wait for socket to become ready.
+    socket_ops::poll_read(impl.socket_, ec);
+
+    return 0;
+  }
+
+  // Start an asynchronous receive. The buffer for the data being received
+  // must be valid for the lifetime of the asynchronous operation.
+  template <typename MutableBufferSequence, typename Handler>
+  void async_receive(base_implementation_type& impl,
+      const MutableBufferSequence& buffers,
+      socket_base::message_flags flags, Handler handler)
+  {
+    // Allocate and construct an operation to wrap the handler.
+    typedef reactive_socket_recv_op<MutableBufferSequence, Handler> op;
+    typename op::ptr p = { boost::addressof(handler),
+      asio_handler_alloc_helpers::allocate(
+        sizeof(op), handler), 0 };
+    p.p = new (p.v) op(impl.socket_, impl.state_, buffers, flags, handler);
+
+    start_op(impl,
+        (flags & socket_base::message_out_of_band)
+          ? reactor::except_op : reactor::read_op,
+        p.p, (flags & socket_base::message_out_of_band) == 0,
+        ((impl.state_ & socket_ops::stream_oriented)
+          && buffer_sequence_adapter<asio::mutable_buffer,
+            MutableBufferSequence>::all_empty(buffers)));
+    p.v = p.p = 0;
+  }
+
+  // Wait until data can be received without blocking.
+  template <typename Handler>
+  void async_receive(base_implementation_type& impl, const null_buffers&,
+      socket_base::message_flags flags, Handler handler)
+  {
+    // Allocate and construct an operation to wrap the handler.
+    typedef reactive_null_buffers_op<Handler> op;
+    typename op::ptr p = { boost::addressof(handler),
+      asio_handler_alloc_helpers::allocate(
+        sizeof(op), handler), 0 };
+    p.p = new (p.v) op(handler);
+
+    start_op(impl,
+        (flags & socket_base::message_out_of_band)
+          ? reactor::except_op : reactor::read_op,
+        p.p, false, false);
+    p.v = p.p = 0;
+  }
+
+protected:
+  // Open a new socket implementation.
+  ASIO_DECL asio::error_code do_open(
+      base_implementation_type& impl, int af,
+      int type, int protocol, asio::error_code& ec);
+
+  // Assign a native socket to a socket implementation.
+  ASIO_DECL asio::error_code do_assign(
+      base_implementation_type& impl, int type,
+      const native_type& native_socket, asio::error_code& ec);
+
+  // Start the asynchronous read or write operation.
+  ASIO_DECL void start_op(base_implementation_type& impl, int op_type,
+      reactor_op* op, bool non_blocking, bool noop);
+
+  // Start the asynchronous accept operation.
+  ASIO_DECL void start_accept_op(base_implementation_type& impl,
+      reactor_op* op, bool peer_is_open);
+
+  // Start the asynchronous connect operation.
+  ASIO_DECL void start_connect_op(base_implementation_type& impl,
+      reactor_op* op, const socket_addr_type* addr, size_t addrlen);
+
+  // The selector that performs event demultiplexing for the service.
+  reactor& reactor_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/detail/impl/reactive_socket_service_base.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
+#endif // !defined(ASIO_HAS_IOCP)
+
+#endif // ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_BASE_HPP
diff --git a/ext/asio/asio/detail/reactor.hpp b/ext/asio/asio/detail/reactor.hpp
index 98ac360..0e938c9 100644
--- a/ext/asio/asio/detail/reactor.hpp
+++ b/ext/asio/asio/detail/reactor.hpp
@@ -1,8 +1,8 @@
 //
-// reactor.hpp
-// ~~~~~~~~~~~
+// detail/reactor.hpp
+// ~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,8 +15,6 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
 #include "asio/detail/reactor_fwd.hpp"
 
 #if defined(ASIO_HAS_EPOLL)
@@ -29,6 +27,4 @@
 # include "asio/detail/select_reactor.hpp"
 #endif
 
-#include "asio/detail/pop_options.hpp"
-
 #endif // ASIO_DETAIL_REACTOR_HPP
diff --git a/ext/asio/asio/detail/reactor_fwd.hpp b/ext/asio/asio/detail/reactor_fwd.hpp
index 9c33be5..d45d768 100644
--- a/ext/asio/asio/detail/reactor_fwd.hpp
+++ b/ext/asio/asio/detail/reactor_fwd.hpp
@@ -1,8 +1,8 @@
 //
-// reactor_fwd.hpp
-// ~~~~~~~~~~~~~~~
+// detail/reactor_fwd.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,19 +15,25 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 
-#include "asio/detail/dev_poll_reactor_fwd.hpp"
-#include "asio/detail/epoll_reactor_fwd.hpp"
-#include "asio/detail/kqueue_reactor_fwd.hpp"
-#include "asio/detail/select_reactor_fwd.hpp"
-#include "asio/detail/win_iocp_io_service_fwd.hpp"
+#if defined(ASIO_HAS_IOCP)
+# include "asio/detail/select_reactor_fwd.hpp"
+#elif defined(ASIO_HAS_EPOLL)
+# include "asio/detail/epoll_reactor_fwd.hpp"
+#elif defined(ASIO_HAS_KQUEUE)
+# include "asio/detail/kqueue_reactor_fwd.hpp"
+#elif defined(ASIO_HAS_DEV_POLL)
+# include "asio/detail/dev_poll_reactor_fwd.hpp"
+#else
+# include "asio/detail/select_reactor_fwd.hpp"
+#endif
 
 namespace asio {
 namespace detail {
 
 #if defined(ASIO_HAS_IOCP)
-typedef select_reactor<true> reactor;
+typedef select_reactor reactor;
 #elif defined(ASIO_HAS_EPOLL)
 typedef epoll_reactor reactor;
 #elif defined(ASIO_HAS_KQUEUE)
@@ -35,12 +41,10 @@ typedef kqueue_reactor reactor;
 #elif defined(ASIO_HAS_DEV_POLL)
 typedef dev_poll_reactor reactor;
 #else
-typedef select_reactor<false> reactor;
+typedef select_reactor reactor;
 #endif
 
 } // namespace detail
 } // namespace asio
 
-#include "asio/detail/pop_options.hpp"
-
 #endif // ASIO_DETAIL_REACTOR_FWD_HPP
diff --git a/ext/asio/asio/detail/reactor_op.hpp b/ext/asio/asio/detail/reactor_op.hpp
index cd557fa..3009cf9 100644
--- a/ext/asio/asio/detail/reactor_op.hpp
+++ b/ext/asio/asio/detail/reactor_op.hpp
@@ -1,8 +1,8 @@
 //
-// reactor_op.hpp
-// ~~~~~~~~~~~~
+// detail/reactor_op.hpp
+// ~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,10 +15,11 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
+#include "asio/detail/config.hpp"
 #include "asio/detail/operation.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 namespace detail {
 
diff --git a/ext/asio/asio/detail/reactor_op_queue.hpp b/ext/asio/asio/detail/reactor_op_queue.hpp
index 233c0ae..6eed398 100644
--- a/ext/asio/asio/detail/reactor_op_queue.hpp
+++ b/ext/asio/asio/detail/reactor_op_queue.hpp
@@ -1,8 +1,8 @@
 //
-// reactor_op_queue.hpp
-// ~~~~~~~~~~~~~~~~~~~~
+// detail/reactor_op_queue.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,13 +15,14 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/error.hpp"
+#include "asio/detail/config.hpp"
 #include "asio/detail/hash_map.hpp"
 #include "asio/detail/noncopyable.hpp"
 #include "asio/detail/op_queue.hpp"
 #include "asio/detail/reactor_op.hpp"
+#include "asio/error.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 namespace detail {
diff --git a/ext/asio/asio/detail/regex_fwd.hpp b/ext/asio/asio/detail/regex_fwd.hpp
new file mode 100644
index 0000000..9da295b
--- /dev/null
+++ b/ext/asio/asio/detail/regex_fwd.hpp
@@ -0,0 +1,31 @@
+//
+// detail/regex_fwd.hpp
+// ~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_REGEX_FWD_HPP
+#define ASIO_DETAIL_REGEX_FWD_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/regex_fwd.hpp>
+#include <boost/regex/v4/match_flags.hpp>
+
+namespace boost {
+
+template <class BidiIterator>
+struct sub_match;
+
+template <class BidiIterator, class Allocator>
+class match_results;
+
+} // namespace boost
+
+#endif // ASIO_DETAIL_REGEX_FWD_HPP
diff --git a/ext/asio/asio/detail/resolve_endpoint_op.hpp b/ext/asio/asio/detail/resolve_endpoint_op.hpp
new file mode 100644
index 0000000..0931fd0
--- /dev/null
+++ b/ext/asio/asio/detail/resolve_endpoint_op.hpp
@@ -0,0 +1,116 @@
+//
+// detail/resolve_endpoint_op.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_RESOLVER_ENDPOINT_OP_HPP
+#define ASIO_DETAIL_RESOLVER_ENDPOINT_OP_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+#include <boost/utility/addressof.hpp>
+#include "asio/error.hpp"
+#include "asio/io_service.hpp"
+#include "asio/ip/basic_resolver_iterator.hpp"
+#include "asio/detail/bind_handler.hpp"
+#include "asio/detail/fenced_block.hpp"
+#include "asio/detail/handler_alloc_helpers.hpp"
+#include "asio/detail/handler_invoke_helpers.hpp"
+#include "asio/detail/operation.hpp"
+#include "asio/detail/socket_ops.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename Protocol, typename Handler>
+class resolve_endpoint_op : public operation
+{
+public:
+  ASIO_DEFINE_HANDLER_PTR(resolve_endpoint_op);
+
+  typedef typename Protocol::endpoint endpoint_type;
+  typedef asio::ip::basic_resolver_iterator<Protocol> iterator_type;
+
+  resolve_endpoint_op(socket_ops::weak_cancel_token_type cancel_token,
+      const endpoint_type& endpoint, io_service_impl& ios, Handler handler)
+    : operation(&resolve_endpoint_op::do_complete),
+      cancel_token_(cancel_token),
+      endpoint_(endpoint),
+      io_service_impl_(ios),
+      handler_(handler)
+  {
+  }
+
+  static void do_complete(io_service_impl* owner, operation* base,
+      asio::error_code /*ec*/, std::size_t /*bytes_transferred*/)
+  {
+    // Take ownership of the operation object.
+    resolve_endpoint_op* o(static_cast<resolve_endpoint_op*>(base));
+    ptr p = { boost::addressof(o->handler_), o, o };
+
+    if (owner && owner != &o->io_service_impl_)
+    {
+      // The operation is being run on the worker io_service. Time to perform
+      // the resolver operation.
+    
+      // Perform the blocking endpoint resolution operation.
+      char host_name[NI_MAXHOST];
+      char service_name[NI_MAXSERV];
+      socket_ops::background_getnameinfo(o->cancel_token_, o->endpoint_.data(),
+          o->endpoint_.size(), host_name, NI_MAXHOST, service_name, NI_MAXSERV,
+          o->endpoint_.protocol().type(), o->ec_);
+      o->iter_ = iterator_type::create(o->endpoint_, host_name, service_name);
+
+      // Pass operation back to main io_service for completion.
+      o->io_service_impl_.post_deferred_completion(o);
+      p.v = p.p = 0;
+    }
+    else
+    {
+      // The operation has been returned to the main io_service. The completion
+      // handler is ready to be delivered.
+
+      // Make a copy of the handler so that the memory can be deallocated
+      // before the upcall is made. Even if we're not about to make an upcall,
+      // a sub-object of the handler may be the true owner of the memory
+      // associated with the handler. Consequently, a local copy of the handler
+      // is required to ensure that any owning sub-object remains valid until
+      // after we have deallocated the memory here.
+      detail::binder2<Handler, asio::error_code, iterator_type>
+        handler(o->handler_, o->ec_, o->iter_);
+      p.h = boost::addressof(handler.handler_);
+      p.reset();
+
+      if (owner)
+      {
+        asio::detail::fenced_block b;
+        asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+      }
+    }
+  }
+
+private:
+  socket_ops::weak_cancel_token_type cancel_token_;
+  endpoint_type endpoint_;
+  io_service_impl& io_service_impl_;
+  Handler handler_;
+  asio::error_code ec_;
+  iterator_type iter_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_RESOLVER_ENDPOINT_OP_HPP
diff --git a/ext/asio/asio/detail/resolve_op.hpp b/ext/asio/asio/detail/resolve_op.hpp
new file mode 100644
index 0000000..a04fbc3
--- /dev/null
+++ b/ext/asio/asio/detail/resolve_op.hpp
@@ -0,0 +1,126 @@
+//
+// detail/resolve_op.hpp
+// ~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_RESOLVE_OP_HPP
+#define ASIO_DETAIL_RESOLVE_OP_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+#include <boost/utility/addressof.hpp>
+#include "asio/error.hpp"
+#include "asio/io_service.hpp"
+#include "asio/ip/basic_resolver_iterator.hpp"
+#include "asio/ip/basic_resolver_query.hpp"
+#include "asio/detail/bind_handler.hpp"
+#include "asio/detail/fenced_block.hpp"
+#include "asio/detail/handler_alloc_helpers.hpp"
+#include "asio/detail/handler_invoke_helpers.hpp"
+#include "asio/detail/operation.hpp"
+#include "asio/detail/socket_ops.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename Protocol, typename Handler>
+class resolve_op : public operation
+{
+public:
+  ASIO_DEFINE_HANDLER_PTR(resolve_op);
+
+  typedef asio::ip::basic_resolver_query<Protocol> query_type;
+  typedef asio::ip::basic_resolver_iterator<Protocol> iterator_type;
+
+  resolve_op(socket_ops::weak_cancel_token_type cancel_token,
+      const query_type& query, io_service_impl& ios, Handler handler)
+    : operation(&resolve_op::do_complete),
+      cancel_token_(cancel_token),
+      query_(query),
+      io_service_impl_(ios),
+      handler_(handler),
+      addrinfo_(0)
+  {
+  }
+
+  ~resolve_op()
+  {
+    if (addrinfo_)
+      socket_ops::freeaddrinfo(addrinfo_);
+  }
+
+  static void do_complete(io_service_impl* owner, operation* base,
+      asio::error_code /*ec*/, std::size_t /*bytes_transferred*/)
+  {
+    // Take ownership of the operation object.
+    resolve_op* o(static_cast<resolve_op*>(base));
+    ptr p = { boost::addressof(o->handler_), o, o };
+
+    if (owner && owner != &o->io_service_impl_)
+    {
+      // The operation is being run on the worker io_service. Time to perform
+      // the resolver operation.
+    
+      // Perform the blocking host resolution operation.
+      socket_ops::background_getaddrinfo(o->cancel_token_,
+          o->query_.host_name().c_str(), o->query_.service_name().c_str(),
+          o->query_.hints(), &o->addrinfo_, o->ec_);
+
+      // Pass operation back to main io_service for completion.
+      o->io_service_impl_.post_deferred_completion(o);
+      p.v = p.p = 0;
+    }
+    else
+    {
+      // The operation has been returned to the main io_service. The completion
+      // handler is ready to be delivered.
+
+      // Make a copy of the handler so that the memory can be deallocated
+      // before the upcall is made. Even if we're not about to make an upcall,
+      // a sub-object of the handler may be the true owner of the memory
+      // associated with the handler. Consequently, a local copy of the handler
+      // is required to ensure that any owning sub-object remains valid until
+      // after we have deallocated the memory here.
+      detail::binder2<Handler, asio::error_code, iterator_type>
+        handler(o->handler_, o->ec_, iterator_type());
+      p.h = boost::addressof(handler.handler_);
+      if (o->addrinfo_)
+      {
+        handler.arg2_ = iterator_type::create(o->addrinfo_,
+            o->query_.host_name(), o->query_.service_name());
+      }
+      p.reset();
+
+      if (owner)
+      {
+        asio::detail::fenced_block b;
+        asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+      }
+    }
+  }
+
+private:
+  socket_ops::weak_cancel_token_type cancel_token_;
+  query_type query_;
+  io_service_impl& io_service_impl_;
+  Handler handler_;
+  asio::error_code ec_;
+  asio::detail::addrinfo_type* addrinfo_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_RESOLVE_OP_HPP
diff --git a/ext/asio/asio/detail/resolver_service.hpp b/ext/asio/asio/detail/resolver_service.hpp
index 562dc10..c2c3b0c 100644
--- a/ext/asio/asio/detail/resolver_service.hpp
+++ b/ext/asio/asio/detail/resolver_service.hpp
@@ -1,8 +1,8 @@
 //
-// resolver_service.hpp
-// ~~~~~~~~~~~~~~~~~~~~
+// detail/resolver_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,68 +15,25 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <cstring>
-#include <boost/scoped_ptr.hpp>
-#include <boost/shared_ptr.hpp>
-#include <boost/weak_ptr.hpp>
-#include "asio/detail/pop_options.hpp"
-
-#include "asio/error.hpp"
-#include "asio/io_service.hpp"
+#include "asio/detail/config.hpp"
 #include "asio/ip/basic_resolver_iterator.hpp"
 #include "asio/ip/basic_resolver_query.hpp"
-#include "asio/detail/bind_handler.hpp"
-#include "asio/detail/fenced_block.hpp"
-#include "asio/detail/mutex.hpp"
-#include "asio/detail/noncopyable.hpp"
-#include "asio/detail/operation.hpp"
-#include "asio/detail/service_base.hpp"
-#include "asio/detail/socket_ops.hpp"
-#include "asio/detail/socket_types.hpp"
-#include "asio/detail/thread.hpp"
+#include "asio/detail/resolve_endpoint_op.hpp"
+#include "asio/detail/resolve_op.hpp"
+#include "asio/detail/resolver_service_base.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 namespace detail {
 
 template <typename Protocol>
-class resolver_service
-  : public asio::detail::service_base<resolver_service<Protocol> >
+class resolver_service : public resolver_service_base
 {
-private:
-  // Helper class to perform exception-safe cleanup of addrinfo objects.
-  class auto_addrinfo
-    : private asio::detail::noncopyable
-  {
-  public:
-    explicit auto_addrinfo(asio::detail::addrinfo_type* ai)
-      : ai_(ai)
-    {
-    }
-
-    ~auto_addrinfo()
-    {
-      if (ai_)
-        socket_ops::freeaddrinfo(ai_);
-    }
-
-    operator asio::detail::addrinfo_type*()
-    {
-      return ai_;
-    }
-
-  private:
-    asio::detail::addrinfo_type* ai_;
-  };
-
 public:
-  // The implementation type of the resolver. The shared pointer is used as a
-  // cancellation token to indicate to the background thread that the operation
-  // has been cancelled.
-  typedef boost::shared_ptr<void> implementation_type;
-  struct noop_deleter { void operator()(void*) {} };
+  // The implementation type of the resolver. A cancellation token is used to
+  // indicate to the background thread that the operation has been cancelled.
+  typedef socket_ops::shared_cancel_token_type implementation_type;
 
   // The endpoint type.
   typedef typename Protocol::endpoint endpoint_type;
@@ -89,55 +46,8 @@ public:
 
   // Constructor.
   resolver_service(asio::io_service& io_service)
-    : asio::detail::service_base<
-        resolver_service<Protocol> >(io_service),
-      mutex_(),
-      io_service_impl_(asio::use_service<io_service_impl>(io_service)),
-      work_io_service_(new asio::io_service),
-      work_io_service_impl_(asio::use_service<
-          io_service_impl>(*work_io_service_)),
-      work_(new asio::io_service::work(*work_io_service_)),
-      work_thread_(0)
-  {
-  }
-
-  // Destructor.
-  ~resolver_service()
+    : resolver_service_base(io_service)
   {
-    shutdown_service();
-  }
-
-  // Destroy all user-defined handler objects owned by the service.
-  void shutdown_service()
-  {
-    work_.reset();
-    if (work_io_service_)
-    {
-      work_io_service_->stop();
-      if (work_thread_)
-      {
-        work_thread_->join();
-        work_thread_.reset();
-      }
-      work_io_service_.reset();
-    }
-  }
-
-  // Construct a new resolver implementation.
-  void construct(implementation_type& impl)
-  {
-    impl.reset(static_cast<void*>(0), noop_deleter());
-  }
-
-  // Destroy a resolver implementation.
-  void destroy(implementation_type&)
-  {
-  }
-
-  // Cancel pending asynchronous operations.
-  void cancel(implementation_type& impl)
-  {
-    impl.reset(static_cast<void*>(0), noop_deleter());
   }
 
   // Resolve a query to a list of entries.
@@ -145,293 +55,60 @@ public:
       asio::error_code& ec)
   {
     asio::detail::addrinfo_type* address_info = 0;
-    std::string host_name = query.host_name();
-    std::string service_name = query.service_name();
-    asio::detail::addrinfo_type hints = query.hints();
 
-    socket_ops::getaddrinfo(!host_name.empty() ? host_name.c_str() : 0,
-        service_name.c_str(), &hints, &address_info, ec);
+    socket_ops::getaddrinfo(query.host_name().c_str(),
+        query.service_name().c_str(), query.hints(), &address_info, ec);
     auto_addrinfo auto_address_info(address_info);
 
-    if (ec)
-      return iterator_type();
-
-    return iterator_type::create(address_info, host_name, service_name);
+    return ec ? iterator_type() : iterator_type::create(
+        address_info, query.host_name(), query.service_name());
   }
 
-  template <typename Handler>
-  class resolve_op
-    : public operation
-  {
-  public:
-    resolve_op(implementation_type impl, const query_type& query,
-        io_service_impl& io_service_impl, Handler handler)
-      : operation(&resolve_op::do_complete),
-        impl_(impl),
-        query_(query),
-        io_service_impl_(io_service_impl),
-        handler_(handler)
-    {
-    }
-
-    static void do_complete(io_service_impl* owner, operation* base,
-        asio::error_code /*ec*/, std::size_t /*bytes_transferred*/)
-    {
-      // Take ownership of the operation object.
-      resolve_op* o(static_cast<resolve_op*>(base));
-      typedef handler_alloc_traits<Handler, resolve_op> alloc_traits;
-      handler_ptr<alloc_traits> ptr(o->handler_, o);
-
-      if (owner)
-      {
-        if (owner != &o->io_service_impl_)
-        {
-          // The operation is being run on the worker io_service. Time to
-          // perform the resolver operation.
-        
-          if (o->impl_.expired())
-          {
-            // THe operation has been cancelled.
-            o->ec_ = asio::error::operation_aborted;
-          }
-          else
-          {
-            // Perform the blocking host resolution operation.
-            asio::detail::addrinfo_type* address_info = 0;
-            std::string host_name = o->query_.host_name();
-            std::string service_name = o->query_.service_name();
-            asio::detail::addrinfo_type hints = o->query_.hints();
-            socket_ops::getaddrinfo(!host_name.empty() ? host_name.c_str() : 0,
-                service_name.c_str(), &hints, &address_info, o->ec_);
-            auto_addrinfo auto_address_info(address_info);
-            o->iter_ = iterator_type::create(
-              address_info, host_name, service_name);
-          }
-
-          o->io_service_impl_.post_deferred_completion(o);
-          ptr.release();
-        }
-        else
-        {
-          // The operation has been returned to the main io_serice. The
-          // completion handler is ready to be delivered.
-
-          // Make a copy of the handler so that the memory can be deallocated
-          // before the upcall is made. Even if we're not about to make an
-          // upcall, a sub-object of the handler may be the true owner of the
-          // memory associated with the handler. Consequently, a local copy of
-          // the handler is required to ensure that any owning sub-object
-          // remains valid until after we have deallocated the memory here.
-          detail::binder2<Handler, asio::error_code, iterator_type>
-            handler(o->handler_, o->ec_, o->iter_);
-          ptr.reset();
-          asio::detail::fenced_block b;
-          asio_handler_invoke_helpers::invoke(handler, handler);
-        }
-      }
-    }
-
-  private:
-    boost::weak_ptr<void> impl_;
-    query_type query_;
-    io_service_impl& io_service_impl_;
-    Handler handler_;
-    asio::error_code ec_;
-    iterator_type iter_;
-  };
-
   // Asynchronously resolve a query to a list of entries.
   template <typename Handler>
   void async_resolve(implementation_type& impl, const query_type& query,
       Handler handler)
   {
     // Allocate and construct an operation to wrap the handler.
-    typedef resolve_op<Handler> value_type;
-    typedef handler_alloc_traits<Handler, value_type> alloc_traits;
-    raw_handler_ptr<alloc_traits> raw_ptr(handler);
-    handler_ptr<alloc_traits> ptr(raw_ptr,
-        impl, query, io_service_impl_, handler);
-
-    if (work_io_service_)
-    {
-      start_work_thread();
-      io_service_impl_.work_started();
-      work_io_service_impl_.post_immediate_completion(ptr.get());
-      ptr.release();
-    }
+    typedef resolve_op<Protocol, Handler> op;
+    typename op::ptr p = { boost::addressof(handler),
+      asio_handler_alloc_helpers::allocate(
+        sizeof(op), handler), 0 };
+    p.p = new (p.v) op(impl, query, io_service_impl_, handler);
+
+    start_resolve_op(p.p);
+    p.v = p.p = 0;
   }
 
   // Resolve an endpoint to a list of entries.
   iterator_type resolve(implementation_type&,
       const endpoint_type& endpoint, asio::error_code& ec)
   {
-    // First try resolving with the service name. If that fails try resolving
-    // but allow the service to be returned as a number.
     char host_name[NI_MAXHOST];
     char service_name[NI_MAXSERV];
-    int flags = endpoint.protocol().type() == SOCK_DGRAM ? NI_DGRAM : 0;
-    socket_ops::getnameinfo(endpoint.data(), endpoint.size(),
-        host_name, NI_MAXHOST, service_name, NI_MAXSERV, flags, ec);
-    if (ec)
-    {
-      flags |= NI_NUMERICSERV;
-      socket_ops::getnameinfo(endpoint.data(), endpoint.size(),
-          host_name, NI_MAXHOST, service_name, NI_MAXSERV, flags, ec);
-    }
+    socket_ops::sync_getnameinfo(endpoint.data(), endpoint.size(),
+        host_name, NI_MAXHOST, service_name, NI_MAXSERV,
+        endpoint.protocol().type(), ec);
 
-    if (ec)
-      return iterator_type();
-
-    return iterator_type::create(endpoint, host_name, service_name);
+    return ec ? iterator_type() : iterator_type::create(
+        endpoint, host_name, service_name);
   }
 
-  template <typename Handler>
-  class resolve_endpoint_op
-    : public operation
-  {
-  public:
-    resolve_endpoint_op(implementation_type impl, const endpoint_type& ep,
-        io_service_impl& io_service_impl, Handler handler)
-      : operation(&resolve_endpoint_op::do_complete),
-        impl_(impl),
-        ep_(ep),
-        io_service_impl_(io_service_impl),
-        handler_(handler)
-    {
-    }
-
-    static void do_complete(io_service_impl* owner, operation* base,
-        asio::error_code /*ec*/, std::size_t /*bytes_transferred*/)
-    {
-      // Take ownership of the operation object.
-      resolve_endpoint_op* o(static_cast<resolve_endpoint_op*>(base));
-      typedef handler_alloc_traits<Handler, resolve_endpoint_op> alloc_traits;
-      handler_ptr<alloc_traits> ptr(o->handler_, o);
-
-      if (owner)
-      {
-        if (owner != &o->io_service_impl_)
-        {
-          // The operation is being run on the worker io_service. Time to
-          // perform the resolver operation.
-        
-          if (o->impl_.expired())
-          {
-            // THe operation has been cancelled.
-            o->ec_ = asio::error::operation_aborted;
-          }
-          else
-          {
-            // Perform the blocking endoint resolution operation.
-            char host_name[NI_MAXHOST];
-            char service_name[NI_MAXSERV];
-            int flags = o->ep_.protocol().type() == SOCK_DGRAM ? NI_DGRAM : 0;
-            socket_ops::getnameinfo(o->ep_.data(), o->ep_.size(),
-                host_name, NI_MAXHOST, service_name,
-                NI_MAXSERV, flags, o->ec_);
-            if (o->ec_)
-            {
-              flags |= NI_NUMERICSERV;
-              socket_ops::getnameinfo(o->ep_.data(), o->ep_.size(),
-                  host_name, NI_MAXHOST, service_name,
-                  NI_MAXSERV, flags, o->ec_);
-            }
-            o->iter_ = iterator_type::create(o->ep_, host_name, service_name);
-          }
-
-          o->io_service_impl_.post_deferred_completion(o);
-          ptr.release();
-        }
-        else
-        {
-          // The operation has been returned to the main io_serice. The
-          // completion handler is ready to be delivered.
-
-          // Make a copy of the handler so that the memory can be deallocated
-          // before the upcall is made. Even if we're not about to make an
-          // upcall, a sub-object of the handler may be the true owner of the
-          // memory associated with the handler. Consequently, a local copy of
-          // the handler is required to ensure that any owning sub-object
-          // remains valid until after we have deallocated the memory here.
-          detail::binder2<Handler, asio::error_code, iterator_type>
-            handler(o->handler_, o->ec_, o->iter_);
-          ptr.reset();
-          asio::detail::fenced_block b;
-          asio_handler_invoke_helpers::invoke(handler, handler);
-        }
-      }
-    }
-
-  private:
-    boost::weak_ptr<void> impl_;
-    endpoint_type ep_;
-    io_service_impl& io_service_impl_;
-    Handler handler_;
-    asio::error_code ec_;
-    iterator_type iter_;
-  };
-
   // Asynchronously resolve an endpoint to a list of entries.
   template <typename Handler>
   void async_resolve(implementation_type& impl, const endpoint_type& endpoint,
       Handler handler)
   {
     // Allocate and construct an operation to wrap the handler.
-    typedef resolve_endpoint_op<Handler> value_type;
-    typedef handler_alloc_traits<Handler, value_type> alloc_traits;
-    raw_handler_ptr<alloc_traits> raw_ptr(handler);
-    handler_ptr<alloc_traits> ptr(raw_ptr,
-        impl, endpoint, io_service_impl_, handler);
-
-    if (work_io_service_)
-    {
-      start_work_thread();
-      io_service_impl_.work_started();
-      work_io_service_impl_.post_immediate_completion(ptr.get());
-      ptr.release();
-    }
-  }
-
-private:
-  // Helper class to run the work io_service in a thread.
-  class work_io_service_runner
-  {
-  public:
-    work_io_service_runner(asio::io_service& io_service)
-      : io_service_(io_service) {}
-    void operator()() { io_service_.run(); }
-  private:
-    asio::io_service& io_service_;
-  };
-
-  // Start the work thread if it's not already running.
-  void start_work_thread()
-  {
-    asio::detail::mutex::scoped_lock lock(mutex_);
-    if (!work_thread_)
-    {
-      work_thread_.reset(new asio::detail::thread(
-            work_io_service_runner(*work_io_service_)));
-    }
+    typedef resolve_endpoint_op<Protocol, Handler> op;
+    typename op::ptr p = { boost::addressof(handler),
+      asio_handler_alloc_helpers::allocate(
+        sizeof(op), handler), 0 };
+    p.p = new (p.v) op(impl, endpoint, io_service_impl_, handler);
+
+    start_resolve_op(p.p);
+    p.v = p.p = 0;
   }
-
-  // Mutex to protect access to internal data.
-  asio::detail::mutex mutex_;
-
-  // The io_service implementation used to post completions.
-  io_service_impl& io_service_impl_;
-
-  // Private io_service used for performing asynchronous host resolution.
-  boost::scoped_ptr<asio::io_service> work_io_service_;
-
-  // The work io_service implementation used to post completions.
-  io_service_impl& work_io_service_impl_;
-
-  // Work for the private io_service to perform.
-  boost::scoped_ptr<asio::io_service::work> work_;
-
-  // Thread used for running the work io_service's run loop.
-  boost::scoped_ptr<asio::detail::thread> work_thread_;
 };
 
 } // namespace detail
diff --git a/ext/asio/asio/detail/resolver_service_base.hpp b/ext/asio/asio/detail/resolver_service_base.hpp
new file mode 100644
index 0000000..d6f20bd
--- /dev/null
+++ b/ext/asio/asio/detail/resolver_service_base.hpp
@@ -0,0 +1,123 @@
+//
+// detail/resolver_service_base.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_RESOLVER_SERVICE_BASE_HPP
+#define ASIO_DETAIL_RESOLVER_SERVICE_BASE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+#include <boost/scoped_ptr.hpp>
+#include "asio/error.hpp"
+#include "asio/io_service.hpp"
+#include "asio/detail/mutex.hpp"
+#include "asio/detail/noncopyable.hpp"
+#include "asio/detail/operation.hpp"
+#include "asio/detail/socket_ops.hpp"
+#include "asio/detail/socket_types.hpp"
+#include "asio/detail/thread.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+class resolver_service_base
+{
+public:
+  // The implementation type of the resolver. A cancellation token is used to
+  // indicate to the background thread that the operation has been cancelled.
+  typedef socket_ops::shared_cancel_token_type implementation_type;
+
+  // Constructor.
+  ASIO_DECL resolver_service_base(asio::io_service& io_service);
+
+  // Destructor.
+  ASIO_DECL ~resolver_service_base();
+
+  // Destroy all user-defined handler objects owned by the service.
+  ASIO_DECL void shutdown_service();
+
+  // Construct a new resolver implementation.
+  ASIO_DECL void construct(implementation_type& impl);
+
+  // Destroy a resolver implementation.
+  ASIO_DECL void destroy(implementation_type&);
+
+  // Cancel pending asynchronous operations.
+  ASIO_DECL void cancel(implementation_type& impl);
+
+protected:
+  // Helper function to start an asynchronous resolve operation.
+  ASIO_DECL void start_resolve_op(operation* op);
+
+  // Helper class to perform exception-safe cleanup of addrinfo objects.
+  class auto_addrinfo
+    : private asio::detail::noncopyable
+  {
+  public:
+    explicit auto_addrinfo(asio::detail::addrinfo_type* ai)
+      : ai_(ai)
+    {
+    }
+
+    ~auto_addrinfo()
+    {
+      if (ai_)
+        socket_ops::freeaddrinfo(ai_);
+    }
+
+    operator asio::detail::addrinfo_type*()
+    {
+      return ai_;
+    }
+
+  private:
+    asio::detail::addrinfo_type* ai_;
+  };
+
+  // Helper class to run the work io_service in a thread.
+  class work_io_service_runner;
+
+  // Start the work thread if it's not already running.
+  ASIO_DECL void start_work_thread();
+
+  // The io_service implementation used to post completions.
+  io_service_impl& io_service_impl_;
+
+private:
+  // Mutex to protect access to internal data.
+  asio::detail::mutex mutex_;
+
+  // Private io_service used for performing asynchronous host resolution.
+  boost::scoped_ptr<asio::io_service> work_io_service_;
+
+  // The work io_service implementation used to post completions.
+  io_service_impl& work_io_service_impl_;
+
+  // Work for the private io_service to perform.
+  boost::scoped_ptr<asio::io_service::work> work_;
+
+  // Thread used for running the work io_service's run loop.
+  boost::scoped_ptr<asio::detail::thread> work_thread_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/detail/impl/resolver_service_base.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
+#endif // ASIO_DETAIL_RESOLVER_SERVICE_BASE_HPP
diff --git a/ext/asio/asio/detail/scoped_lock.hpp b/ext/asio/asio/detail/scoped_lock.hpp
index e6f6ba5..69b5725 100644
--- a/ext/asio/asio/detail/scoped_lock.hpp
+++ b/ext/asio/asio/detail/scoped_lock.hpp
@@ -1,8 +1,8 @@
 //
-// scoped_lock.hpp
-// ~~~~~~~~~~~~~~~
+// detail/scoped_lock.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,10 +15,10 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
 #include "asio/detail/noncopyable.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 namespace detail {
 
diff --git a/ext/asio/asio/detail/select_interrupter.hpp b/ext/asio/asio/detail/select_interrupter.hpp
index ff5505b..e975ddc 100644
--- a/ext/asio/asio/detail/select_interrupter.hpp
+++ b/ext/asio/asio/detail/select_interrupter.hpp
@@ -1,8 +1,8 @@
 //
-// select_interrupter.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~
+// detail/select_interrupter.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,23 +15,20 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
-
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) || defined(__SYMBIAN32__)
 # include "asio/detail/socket_select_interrupter.hpp"
-#else
+#elif defined(ASIO_HAS_EVENTFD)
 # include "asio/detail/eventfd_select_interrupter.hpp"
+#else
 # include "asio/detail/pipe_select_interrupter.hpp"
 #endif
 
 namespace asio {
 namespace detail {
 
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) || defined(__SYMBIAN32__)
 typedef socket_select_interrupter select_interrupter;
 #elif defined(ASIO_HAS_EVENTFD)
 typedef eventfd_select_interrupter select_interrupter;
@@ -42,6 +39,4 @@ typedef pipe_select_interrupter select_interrupter;
 } // namespace detail
 } // namespace asio
 
-#include "asio/detail/pop_options.hpp"
-
 #endif // ASIO_DETAIL_SELECT_INTERRUPTER_HPP
diff --git a/ext/asio/asio/detail/select_reactor.hpp b/ext/asio/asio/detail/select_reactor.hpp
index 798611b..161305f 100644
--- a/ext/asio/asio/detail/select_reactor.hpp
+++ b/ext/asio/asio/detail/select_reactor.hpp
@@ -1,8 +1,8 @@
 //
-// select_reactor.hpp
-// ~~~~~~~~~~~~~~~~~~
+// detail/select_reactor.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,41 +15,38 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 
-#include "asio/detail/socket_types.hpp" // Must come before posix_time.
+#if defined(ASIO_HAS_IOCP) \
+  || (!defined(ASIO_HAS_DEV_POLL) \
+      && !defined(ASIO_HAS_EPOLL) \
+      && !defined(ASIO_HAS_KQUEUE))
 
-#include "asio/detail/push_options.hpp"
 #include <cstddef>
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
-
-#include "asio/io_service.hpp"
-#include "asio/detail/bind_handler.hpp"
-#include "asio/detail/fd_set_adapter.hpp"
 #include "asio/detail/mutex.hpp"
-#include "asio/detail/noncopyable.hpp"
 #include "asio/detail/op_queue.hpp"
 #include "asio/detail/reactor_op.hpp"
 #include "asio/detail/reactor_op_queue.hpp"
 #include "asio/detail/select_interrupter.hpp"
 #include "asio/detail/select_reactor_fwd.hpp"
-#include "asio/detail/service_base.hpp"
-#include "asio/detail/signal_blocker.hpp"
-#include "asio/detail/socket_ops.hpp"
 #include "asio/detail/socket_types.hpp"
-#include "asio/detail/thread.hpp"
 #include "asio/detail/timer_op.hpp"
 #include "asio/detail/timer_queue_base.hpp"
 #include "asio/detail/timer_queue_fwd.hpp"
 #include "asio/detail/timer_queue_set.hpp"
+#include "asio/io_service.hpp"
+
+#if defined(ASIO_HAS_IOCP)
+# include "asio/detail/thread.hpp"
+#endif // defined(ASIO_HAS_IOCP)
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 namespace detail {
 
-template <bool Own_Thread>
 class select_reactor
-  : public asio::detail::service_base<select_reactor<Own_Thread> >
+  : public asio::detail::service_base<select_reactor>
 {
 public:
 #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
@@ -66,280 +63,91 @@ public:
   };
 
   // Constructor.
-  select_reactor(asio::io_service& io_service)
-    : asio::detail::service_base<
-        select_reactor<Own_Thread> >(io_service),
-      io_service_(use_service<io_service_impl>(io_service)),
-      mutex_(),
-      interrupter_(),
-      stop_thread_(false),
-      thread_(0),
-      shutdown_(false)
-  {
-    if (Own_Thread)
-    {
-      asio::detail::signal_blocker sb;
-      thread_ = new asio::detail::thread(
-          bind_handler(&select_reactor::call_run_thread, this));
-    }
-  }
+  ASIO_DECL select_reactor(asio::io_service& io_service);
 
   // Destructor.
-  ~select_reactor()
-  {
-    shutdown_service();
-  }
+  ASIO_DECL ~select_reactor();
 
   // Destroy all user-defined handler objects owned by the service.
-  void shutdown_service()
-  {
-    asio::detail::mutex::scoped_lock lock(mutex_);
-    shutdown_ = true;
-    stop_thread_ = true;
-    lock.unlock();
-
-    if (Own_Thread)
-    {
-      if (thread_)
-      {
-        interrupter_.interrupt();
-        thread_->join();
-        delete thread_;
-        thread_ = 0;
-      }
-    }
-
-    op_queue<operation> ops;
-
-    for (int i = 0; i < max_ops; ++i)
-      op_queue_[i].get_all_operations(ops);
-
-    timer_queues_.get_all_timers(ops);
-  }
+  ASIO_DECL void shutdown_service();
 
   // Initialise the task, but only if the reactor is not in its own thread.
-  void init_task()
-  {
-    io_service_.init_task();
-  }
+  ASIO_DECL void init_task();
 
   // Register a socket with the reactor. Returns 0 on success, system error
   // code on failure.
-  int register_descriptor(socket_type, per_descriptor_data&)
+  ASIO_DECL int register_descriptor(socket_type, per_descriptor_data&);
+
+  // Post a reactor operation for immediate completion.
+  void post_immediate_completion(reactor_op* op)
   {
-    return 0;
+    io_service_.post_immediate_completion(op);
   }
 
   // Start a new operation. The reactor operation will be performed when the
   // given descriptor is flagged as ready, or an error has occurred.
-  void start_op(int op_type, socket_type descriptor,
-      per_descriptor_data&, reactor_op* op, bool)
-  {
-    asio::detail::mutex::scoped_lock lock(mutex_);
-    if (!shutdown_)
-    {
-      bool first = op_queue_[op_type].enqueue_operation(descriptor, op);
-      io_service_.work_started();
-      if (first)
-        interrupter_.interrupt();
-    }
-  }
+  ASIO_DECL void start_op(int op_type, socket_type descriptor,
+      per_descriptor_data&, reactor_op* op, bool);
 
   // Cancel all operations associated with the given descriptor. The
   // handlers associated with the descriptor will be invoked with the
   // operation_aborted error.
-  void cancel_ops(socket_type descriptor, per_descriptor_data&)
-  {
-    asio::detail::mutex::scoped_lock lock(mutex_);
-    cancel_ops_unlocked(descriptor, asio::error::operation_aborted);
-  }
+  ASIO_DECL void cancel_ops(socket_type descriptor, per_descriptor_data&);
 
   // Cancel any operations that are running against the descriptor and remove
   // its registration from the reactor.
-  void close_descriptor(socket_type descriptor, per_descriptor_data&)
-  {
-    asio::detail::mutex::scoped_lock lock(mutex_);
-    cancel_ops_unlocked(descriptor, asio::error::operation_aborted);
-  }
+  ASIO_DECL void close_descriptor(socket_type descriptor,
+      per_descriptor_data&);
 
   // Add a new timer queue to the reactor.
   template <typename Time_Traits>
-  void add_timer_queue(timer_queue<Time_Traits>& timer_queue)
-  {
-    asio::detail::mutex::scoped_lock lock(mutex_);
-    timer_queues_.insert(&timer_queue);
-  }
+  void add_timer_queue(timer_queue<Time_Traits>& queue);
 
   // Remove a timer queue from the reactor.
   template <typename Time_Traits>
-  void remove_timer_queue(timer_queue<Time_Traits>& timer_queue)
-  {
-    asio::detail::mutex::scoped_lock lock(mutex_);
-    timer_queues_.erase(&timer_queue);
-  }
+  void remove_timer_queue(timer_queue<Time_Traits>& queue);
 
   // Schedule a new operation in the given timer queue to expire at the
   // specified absolute time.
   template <typename Time_Traits>
-  void schedule_timer(timer_queue<Time_Traits>& timer_queue,
-      const typename Time_Traits::time_type& time, timer_op* op, void* token)
-  {
-    asio::detail::mutex::scoped_lock lock(mutex_);
-    if (!shutdown_)
-    {
-      bool earliest = timer_queue.enqueue_timer(time, op, token);
-      io_service_.work_started();
-      if (earliest)
-        interrupter_.interrupt();
-    }
-  }
+  void schedule_timer(timer_queue<Time_Traits>& queue,
+      const typename Time_Traits::time_type& time,
+      typename timer_queue<Time_Traits>::per_timer_data& timer, timer_op* op);
 
   // Cancel the timer operations associated with the given token. Returns the
   // number of operations that have been posted or dispatched.
   template <typename Time_Traits>
-  std::size_t cancel_timer(timer_queue<Time_Traits>& timer_queue, void* token)
-  {
-    asio::detail::mutex::scoped_lock lock(mutex_);
-    op_queue<operation> ops;
-    std::size_t n = timer_queue.cancel_timer(token, ops);
-    lock.unlock();
-    io_service_.post_deferred_completions(ops);
-    return n;
-  }
+  std::size_t cancel_timer(timer_queue<Time_Traits>& queue,
+      typename timer_queue<Time_Traits>::per_timer_data& timer);
 
   // Run select once until interrupted or events are ready to be dispatched.
-  void run(bool block, op_queue<operation>& ops)
-  {
-    asio::detail::mutex::scoped_lock lock(mutex_);
-
-    // Check if the thread is supposed to stop.
-    if (Own_Thread)
-      if (stop_thread_)
-        return;
-
-    // Set up the descriptor sets.
-    fd_set_adapter fds[max_select_ops];
-    fds[read_op].set(interrupter_.read_descriptor());
-    socket_type max_fd = 0;
-    bool have_work_to_do = !timer_queues_.all_empty();
-    for (int i = 0; i < max_select_ops; ++i)
-    {
-      have_work_to_do = have_work_to_do || !op_queue_[i].empty();
-      op_queue_[i].get_descriptors(fds[i], ops);
-      if (fds[i].max_descriptor() > max_fd)
-        max_fd = fds[i].max_descriptor();
-    }
-
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-    // Connection operations on Windows use both except and write fd_sets.
-    have_work_to_do = have_work_to_do || !op_queue_[connect_op].empty();
-    op_queue_[connect_op].get_descriptors(fds[write_op], ops);
-    if (fds[write_op].max_descriptor() > max_fd)
-      max_fd = fds[write_op].max_descriptor();
-    op_queue_[connect_op].get_descriptors(fds[except_op], ops);
-    if (fds[except_op].max_descriptor() > max_fd)
-      max_fd = fds[except_op].max_descriptor();
-#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-
-    // We can return immediately if there's no work to do and the reactor is
-    // not supposed to block.
-    if (!block && !have_work_to_do)
-      return;
-
-    // Determine how long to block while waiting for events.
-    timeval tv_buf = { 0, 0 };
-    timeval* tv = block ? get_timeout(tv_buf) : &tv_buf;
-
-    lock.unlock();
-
-    // Block on the select call until descriptors become ready.
-    asio::error_code ec;
-    int retval = socket_ops::select(static_cast<int>(max_fd + 1),
-        fds[read_op], fds[write_op], fds[except_op], tv, ec);
-
-    // Reset the interrupter.
-    if (retval > 0 && fds[read_op].is_set(interrupter_.read_descriptor()))
-      interrupter_.reset();
-
-    lock.lock();
-
-    // Dispatch all ready operations.
-    if (retval > 0)
-    {
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-      // Connection operations on Windows use both except and write fd_sets.
-      op_queue_[connect_op].perform_operations_for_descriptors(
-          fds[except_op], ops);
-      op_queue_[connect_op].perform_operations_for_descriptors(
-          fds[write_op], ops);
-#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-
-      // Exception operations must be processed first to ensure that any
-      // out-of-band data is read before normal data.
-      for (int i = max_select_ops - 1; i >= 0; --i)
-        op_queue_[i].perform_operations_for_descriptors(fds[i], ops);
-    }
-    timer_queues_.get_ready_timers(ops);
-  }
+  ASIO_DECL void run(bool block, op_queue<operation>& ops);
 
   // Interrupt the select loop.
-  void interrupt()
-  {
-    interrupter_.interrupt();
-  }
+  ASIO_DECL void interrupt();
 
 private:
+#if defined(ASIO_HAS_IOCP)
   // Run the select loop in the thread.
-  void run_thread()
-  {
-    if (Own_Thread)
-    {
-      asio::detail::mutex::scoped_lock lock(mutex_);
-      while (!stop_thread_)
-      {
-        lock.unlock();
-        op_queue<operation> ops;
-        run(true, ops);
-        io_service_.post_deferred_completions(ops);
-        lock.lock();
-      }
-    }
-  }
+  ASIO_DECL void run_thread();
 
   // Entry point for the select loop thread.
-  static void call_run_thread(select_reactor* reactor)
-  {
-    if (Own_Thread)
-    {
-      reactor->run_thread();
-    }
-  }
+  ASIO_DECL static void call_run_thread(select_reactor* reactor);
+#endif // defined(ASIO_HAS_IOCP)
+
+  // Helper function to add a new timer queue.
+  ASIO_DECL void do_add_timer_queue(timer_queue_base& queue);
+
+  // Helper function to remove a timer queue.
+  ASIO_DECL void do_remove_timer_queue(timer_queue_base& queue);
 
   // Get the timeout value for the select call.
-  timeval* get_timeout(timeval& tv)
-  {
-    // By default we will wait no longer than 5 minutes. This will ensure that
-    // any changes to the system clock are detected after no longer than this.
-    long usec = timer_queues_.wait_duration_usec(5 * 60 * 1000 * 1000);
-    tv.tv_sec = usec / 1000000;
-    tv.tv_usec = usec % 1000000;
-    return &tv;
-  }
+  ASIO_DECL timeval* get_timeout(timeval& tv);
 
   // Cancel all operations associated with the given descriptor. This function
   // does not acquire the select_reactor's mutex.
-  void cancel_ops_unlocked(socket_type descriptor,
-      const asio::error_code& ec)
-  {
-    bool need_interrupt = false;
-    op_queue<operation> ops;
-    for (int i = 0; i < max_ops; ++i)
-      need_interrupt = op_queue_[i].cancel_operations(
-          descriptor, ops, ec) || need_interrupt;
-    io_service_.post_deferred_completions(ops);
-    if (need_interrupt)
-      interrupter_.interrupt();
-  }
+  ASIO_DECL void cancel_ops_unlocked(socket_type descriptor,
+      const asio::error_code& ec);
 
   // The io_service implementation used to post completions.
   io_service_impl& io_service_;
@@ -356,11 +164,13 @@ private:
   // The timer queues.
   timer_queue_set timer_queues_;
 
+#if defined(ASIO_HAS_IOCP)
   // Does the reactor loop thread need to stop.
   bool stop_thread_;
 
   // The thread that is running the reactor loop.
   asio::detail::thread* thread_;
+#endif // defined(ASIO_HAS_IOCP)
 
   // Whether the service has been shut down.
   bool shutdown_;
@@ -371,4 +181,14 @@ private:
 
 #include "asio/detail/pop_options.hpp"
 
+#include "asio/detail/impl/select_reactor.hpp"
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/detail/impl/select_reactor.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
+#endif // defined(ASIO_HAS_IOCP)
+       //   || (!defined(ASIO_HAS_DEV_POLL)
+       //       && !defined(ASIO_HAS_EPOLL)
+       //       && !defined(ASIO_HAS_KQUEUE))
+
 #endif // ASIO_DETAIL_SELECT_REACTOR_HPP
diff --git a/ext/asio/asio/detail/select_reactor_fwd.hpp b/ext/asio/asio/detail/select_reactor_fwd.hpp
index 0b72e7e..04e5ecd 100644
--- a/ext/asio/asio/detail/select_reactor_fwd.hpp
+++ b/ext/asio/asio/detail/select_reactor_fwd.hpp
@@ -1,8 +1,8 @@
 //
-// select_reactor_fwd.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~
+// detail/select_reactor_fwd.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,17 +15,12 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
 namespace asio {
 namespace detail {
 
-template <bool Own_Thread>
 class select_reactor;
 
 } // namespace detail
 } // namespace asio
 
-#include "asio/detail/pop_options.hpp"
-
 #endif // ASIO_DETAIL_SELECT_REACTOR_FWD_HPP
diff --git a/ext/asio/asio/detail/service_registry.hpp b/ext/asio/asio/detail/service_registry.hpp
index f80b4b6..34b946d 100644
--- a/ext/asio/asio/detail/service_registry.hpp
+++ b/ext/asio/asio/detail/service_registry.hpp
@@ -1,8 +1,8 @@
 //
-// service_registry.hpp
-// ~~~~~~~~~~~~~~~~~~~~
+// detail/service_registry.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,16 +15,11 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 #include <typeinfo>
-#include "asio/detail/pop_options.hpp"
-
-#include "asio/io_service.hpp"
 #include "asio/detail/mutex.hpp"
 #include "asio/detail/noncopyable.hpp"
-#include "asio/detail/service_id.hpp"
+#include "asio/io_service.hpp"
 
 #if defined(BOOST_NO_TYPEID)
 # if !defined(ASIO_NO_TYPEID)
@@ -32,6 +27,8 @@
 # endif // !defined(ASIO_NO_TYPEID)
 #endif // defined(BOOST_NO_TYPEID)
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 namespace detail {
 
@@ -55,98 +52,43 @@ class service_registry
 {
 public:
   // Constructor.
-  service_registry(asio::io_service& o)
-    : owner_(o),
-      first_service_(0)
-  {
-  }
+  ASIO_DECL service_registry(asio::io_service& o);
 
   // Destructor.
-  ~service_registry()
-  {
-    // Shutdown all services. This must be done in a separate loop before the
-    // services are destroyed since the destructors of user-defined handler
-    // objects may try to access other service objects.
-    asio::io_service::service* service = first_service_;
-    while (service)
-    {
-      service->shutdown_service();
-      service = service->next_;
-    }
-
-    // Destroy all services.
-    while (first_service_)
-    {
-      asio::io_service::service* next_service = first_service_->next_;
-      destroy(first_service_);
-      first_service_ = next_service;
-    }
-  }
+  ASIO_DECL ~service_registry();
 
   // Get the service object corresponding to the specified service type. Will
   // create a new service object automatically if no such object already
   // exists. Ownership of the service object is not transferred to the caller.
   template <typename Service>
-  Service& use_service()
-  {
-    asio::io_service::service::key key;
-    init_key(key, Service::id);
-    factory_type factory = &service_registry::create<Service>;
-    return *static_cast<Service*>(do_use_service(key, factory));
-  }
+  Service& use_service();
 
-  // Add a service object. Returns false on error, in which case ownership of
-  // the object is retained by the caller.
+  // Add a service object. Throws on error, in which case ownership of the
+  // object is retained by the caller.
   template <typename Service>
-  bool add_service(Service* new_service)
-  {
-    asio::io_service::service::key key;
-    init_key(key, Service::id);
-    return do_add_service(key, new_service);
-  }
+  void add_service(Service* new_service);
 
   // Check whether a service object of the specified type already exists.
   template <typename Service>
-  bool has_service() const
-  {
-    asio::io_service::service::key key;
-    init_key(key, Service::id);
-    return do_has_service(key);
-  }
+  bool has_service() const;
 
 private:
   // Initialise a service's key based on its id.
-  void init_key(asio::io_service::service::key& key,
-      const asio::io_service::id& id)
-  {
-    key.type_info_ = 0;
-    key.id_ = &id;
-  }
+  ASIO_DECL static void init_key(
+      asio::io_service::service::key& key,
+      const asio::io_service::id& id);
 
 #if !defined(ASIO_NO_TYPEID)
   // Initialise a service's key based on its id.
   template <typename Service>
-  void init_key(asio::io_service::service::key& key,
-      const asio::detail::service_id<Service>& /*id*/)
-  {
-    key.type_info_ = &typeid(typeid_wrapper<Service>);
-    key.id_ = 0;
-  }
+  static void init_key(asio::io_service::service::key& key,
+      const asio::detail::service_id<Service>& /*id*/);
 #endif // !defined(ASIO_NO_TYPEID)
 
   // Check if a service matches the given id.
-  static bool keys_match(
+  ASIO_DECL static bool keys_match(
       const asio::io_service::service::key& key1,
-      const asio::io_service::service::key& key2)
-  {
-    if (key1.id_ && key2.id_)
-      if (key1.id_ == key2.id_)
-        return true;
-    if (key1.type_info_ && key2.type_info_)
-      if (*key1.type_info_ == *key2.type_info_)
-        return true;
-    return false;
-  }
+      const asio::io_service::service::key& key2);
 
   // The type of a factory function used for creating a service instance.
   typedef asio::io_service::service*
@@ -155,18 +97,15 @@ private:
   // Factory function for creating a service instance.
   template <typename Service>
   static asio::io_service::service* create(
-      asio::io_service& owner)
-  {
-    return new Service(owner);
-  }
+      asio::io_service& owner);
 
   // Destroy a service instance.
-  static void destroy(asio::io_service::service* service)
-  {
-    delete service;
-  }
+  ASIO_DECL static void destroy(
+      asio::io_service::service* service);
 
   // Helper class to manage service pointers.
+  struct auto_service_ptr;
+  friend struct auto_service_ptr;
   struct auto_service_ptr
   {
     asio::io_service::service* ptr_;
@@ -176,86 +115,19 @@ private:
   // Get the service object corresponding to the specified service key. Will
   // create a new service object automatically if no such object already
   // exists. Ownership of the service object is not transferred to the caller.
-  asio::io_service::service* do_use_service(
+  ASIO_DECL asio::io_service::service* do_use_service(
       const asio::io_service::service::key& key,
-      factory_type factory)
-  {
-    asio::detail::mutex::scoped_lock lock(mutex_);
-
-    // First see if there is an existing service object with the given key.
-    asio::io_service::service* service = first_service_;
-    while (service)
-    {
-      if (keys_match(service->key_, key))
-        return service;
-      service = service->next_;
-    }
-
-    // Create a new service object. The service registry's mutex is not locked
-    // at this time to allow for nested calls into this function from the new
-    // service's constructor.
-    lock.unlock();
-    auto_service_ptr new_service = { factory(owner_) };
-    new_service.ptr_->key_ = key;
-    lock.lock();
-
-    // Check that nobody else created another service object of the same type
-    // while the lock was released.
-    service = first_service_;
-    while (service)
-    {
-      if (keys_match(service->key_, key))
-        return service;
-      service = service->next_;
-    }
-
-    // Service was successfully initialised, pass ownership to registry.
-    new_service.ptr_->next_ = first_service_;
-    first_service_ = new_service.ptr_;
-    new_service.ptr_ = 0;
-    return first_service_;
-  }
+      factory_type factory);
 
   // Add a service object. Returns false on error, in which case ownership of
   // the object is retained by the caller.
-  bool do_add_service(
+  ASIO_DECL void do_add_service(
       const asio::io_service::service::key& key,
-      asio::io_service::service* new_service)
-  {
-    asio::detail::mutex::scoped_lock lock(mutex_);
-
-    // Check if there is an existing service object with the given key.
-    asio::io_service::service* service = first_service_;
-    while (service)
-    {
-      if (keys_match(service->key_, key))
-        return false;
-      service = service->next_;
-    }
-
-    // Take ownership of the service object.
-    new_service->key_ = key;
-    new_service->next_ = first_service_;
-    first_service_ = new_service;
-
-    return true;
-  }
+      asio::io_service::service* new_service);
 
   // Check whether a service object with the specified key already exists.
-  bool do_has_service(const asio::io_service::service::key& key) const
-  {
-    asio::detail::mutex::scoped_lock lock(mutex_);
-
-    asio::io_service::service* service = first_service_;
-    while (service)
-    {
-      if (keys_match(service->key_, key))
-        return true;
-      service = service->next_;
-    }
-
-    return false;
-  }
+  ASIO_DECL bool do_has_service(
+      const asio::io_service::service::key& key) const;
 
   // Mutex to protect access to internal data.
   mutable asio::detail::mutex mutex_;
@@ -272,4 +144,9 @@ private:
 
 #include "asio/detail/pop_options.hpp"
 
+#include "asio/detail/impl/service_registry.hpp"
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/detail/impl/service_registry.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
 #endif // ASIO_DETAIL_SERVICE_REGISTRY_HPP
diff --git a/ext/asio/asio/detail/service_registry_fwd.hpp b/ext/asio/asio/detail/service_registry_fwd.hpp
index 423bb4b..4108c1a 100644
--- a/ext/asio/asio/detail/service_registry_fwd.hpp
+++ b/ext/asio/asio/detail/service_registry_fwd.hpp
@@ -1,8 +1,8 @@
 //
-// service_registry_fwd.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~
+// detail/service_registry_fwd.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,8 +15,6 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
 namespace asio {
 namespace detail {
 
@@ -25,6 +23,4 @@ class service_registry;
 } // namespace detail
 } // namespace asio
 
-#include "asio/detail/pop_options.hpp"
-
 #endif // ASIO_DETAIL_SERVICE_REGISTRY_FWD_HPP
diff --git a/ext/asio/asio/detail/shared_ptr.hpp b/ext/asio/asio/detail/shared_ptr.hpp
new file mode 100644
index 0000000..cd496f5
--- /dev/null
+++ b/ext/asio/asio/detail/shared_ptr.hpp
@@ -0,0 +1,38 @@
+//
+// detail/shared_ptr.hpp
+// ~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_SHARED_PTR_HPP
+#define ASIO_DETAIL_SHARED_PTR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1600)
+# include <memory>
+#else
+# include <boost/shared_ptr.hpp>
+#endif
+
+namespace asio {
+namespace detail {
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1600)
+using std::shared_ptr;
+#else
+using boost::shared_ptr;
+#endif
+
+} // namespace detail
+} // namespace asio
+
+#endif // ASIO_DETAIL_SHARED_PTR_HPP
diff --git a/ext/asio/asio/detail/signal_blocker.hpp b/ext/asio/asio/detail/signal_blocker.hpp
index 52f70c8..89f45ca 100644
--- a/ext/asio/asio/detail/signal_blocker.hpp
+++ b/ext/asio/asio/detail/signal_blocker.hpp
@@ -1,8 +1,8 @@
 //
-// signal_blocker.hpp
-// ~~~~~~~~~~~~~~~~~~
+// detail/signal_blocker.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,16 +15,11 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
-
-#if !defined(BOOST_HAS_THREADS) || defined(ASIO_DISABLE_THREADS)
+#if !defined(BOOST_HAS_THREADS) || defined(ASIO_DISABLE_THREADS) \
+  || defined(BOOST_WINDOWS) || defined(__CYGWIN__) || defined(__SYMBIAN32__)
 # include "asio/detail/null_signal_blocker.hpp"
-#elif defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-# include "asio/detail/win_signal_blocker.hpp"
 #elif defined(BOOST_HAS_PTHREADS)
 # include "asio/detail/posix_signal_blocker.hpp"
 #else
@@ -34,10 +29,9 @@
 namespace asio {
 namespace detail {
 
-#if !defined(BOOST_HAS_THREADS) || defined(ASIO_DISABLE_THREADS)
+#if !defined(BOOST_HAS_THREADS) || defined(ASIO_DISABLE_THREADS) \
+  || defined(BOOST_WINDOWS) || defined(__CYGWIN__) || defined(__SYMBIAN32__)
 typedef null_signal_blocker signal_blocker;
-#elif defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-typedef win_signal_blocker signal_blocker;
 #elif defined(BOOST_HAS_PTHREADS)
 typedef posix_signal_blocker signal_blocker;
 #endif
@@ -45,6 +39,4 @@ typedef posix_signal_blocker signal_blocker;
 } // namespace detail
 } // namespace asio
 
-#include "asio/detail/pop_options.hpp"
-
 #endif // ASIO_DETAIL_SIGNAL_BLOCKER_HPP
diff --git a/ext/asio/asio/detail/signal_init.hpp b/ext/asio/asio/detail/signal_init.hpp
index 12f17d3..80925f6 100644
--- a/ext/asio/asio/detail/signal_init.hpp
+++ b/ext/asio/asio/detail/signal_init.hpp
@@ -1,8 +1,8 @@
 //
-// signal_init.hpp
-// ~~~~~~~~~~~~~~~
+// detail/signal_init.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,17 +15,13 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
+#include "asio/detail/config.hpp"
 
 #if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
 
-#include "asio/detail/push_options.hpp"
 #include <csignal>
-#include "asio/detail/pop_options.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 namespace detail {
@@ -44,8 +40,8 @@ public:
 } // namespace detail
 } // namespace asio
 
-#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
-
 #include "asio/detail/pop_options.hpp"
 
+#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
 #endif // ASIO_DETAIL_SIGNAL_INIT_HPP
diff --git a/ext/asio/asio/detail/socket_holder.hpp b/ext/asio/asio/detail/socket_holder.hpp
index 82a3884..cb40175 100644
--- a/ext/asio/asio/detail/socket_holder.hpp
+++ b/ext/asio/asio/detail/socket_holder.hpp
@@ -1,8 +1,8 @@
 //
-// socket_holder.hpp
-// ~~~~~~~~~~~~~~~~~
+// detail/socket_holder.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,11 +15,12 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
+#include "asio/detail/config.hpp"
 #include "asio/detail/noncopyable.hpp"
 #include "asio/detail/socket_ops.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 namespace detail {
 
@@ -46,7 +47,8 @@ public:
     if (socket_ != invalid_socket)
     {
       asio::error_code ec;
-      socket_ops::close(socket_, ec);
+      socket_ops::state_type state = 0;
+      socket_ops::close(socket_, state, true, ec);
     }
   }
 
@@ -62,7 +64,8 @@ public:
     if (socket_ != invalid_socket)
     {
       asio::error_code ec;
-      socket_ops::close(socket_, ec);
+      socket_ops::state_type state = 0;
+      socket_ops::close(socket_, state, true, ec);
       socket_ = invalid_socket;
     }
   }
diff --git a/ext/asio/asio/detail/socket_ops.hpp b/ext/asio/asio/detail/socket_ops.hpp
index 1a863a9..8ad464c 100644
--- a/ext/asio/asio/detail/socket_ops.hpp
+++ b/ext/asio/asio/detail/socket_ops.hpp
@@ -1,8 +1,8 @@
 //
-// socket_ops.hpp
-// ~~~~~~~~~~~~~~
+// detail/socket_ops.hpp
+// ~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,193 +15,102 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include <boost/assert.hpp>
-#include <cstdio>
-#include <cstdlib>
-#include <cstring>
-#include <cerrno>
-#include <boost/detail/workaround.hpp>
-#include <new>
-#include "asio/detail/pop_options.hpp"
+#include "asio/detail/config.hpp"
 
-#include "asio/error.hpp"
+#include "asio/error_code.hpp"
+#include "asio/detail/shared_ptr.hpp"
 #include "asio/detail/socket_types.hpp"
+#include "asio/detail/weak_ptr.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 namespace detail {
 namespace socket_ops {
 
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-struct msghdr { int msg_namelen; };
-#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+// Socket state bits.
+enum
+{
+  // The user wants a non-blocking socket.
+  user_set_non_blocking = 1,
 
-#if defined(__hpux)
-// HP-UX doesn't declare these functions extern "C", so they are declared again
-// here to avoid linker errors about undefined symbols.
-extern "C" char* if_indextoname(unsigned int, char*);
-extern "C" unsigned int if_nametoindex(const char*);
-#endif // defined(__hpux)
+  // The socket has been set non-blocking.
+  internal_non_blocking = 2,
 
-inline void clear_error(asio::error_code& ec)
-{
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-  WSASetLastError(0);
-#else
-  errno = 0;
-#endif
-  ec = asio::error_code();
-}
-
-template <typename ReturnType>
-inline ReturnType error_wrapper(ReturnType return_value,
-    asio::error_code& ec)
-{
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-  ec = asio::error_code(WSAGetLastError(),
-      asio::error::get_system_category());
-#else
-  ec = asio::error_code(errno,
-      asio::error::get_system_category());
-#endif
-  return return_value;
-}
-
-template <typename SockLenType>
-inline socket_type call_accept(SockLenType msghdr::*,
-    socket_type s, socket_addr_type* addr, std::size_t* addrlen)
-{
-  SockLenType tmp_addrlen = addrlen ? (SockLenType)*addrlen : 0;
-  socket_type result = ::accept(s, addr, addrlen ? &tmp_addrlen : 0);
-  if (addrlen)
-    *addrlen = (std::size_t)tmp_addrlen;
-  return result;
-}
-
-inline socket_type accept(socket_type s, socket_addr_type* addr,
-    std::size_t* addrlen, asio::error_code& ec)
-{
-  clear_error(ec);
-
-  socket_type new_s = error_wrapper(call_accept(
-        &msghdr::msg_namelen, s, addr, addrlen), ec);
-  if (new_s == invalid_socket)
-    return new_s;
-
-#if defined(__MACH__) && defined(__APPLE__) || defined(__FreeBSD__)
-  int optval = 1;
-  int result = error_wrapper(::setsockopt(new_s,
-        SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval)), ec);
-  if (result != 0)
-  {
-    ::close(new_s);
-    return invalid_socket;
-  }
-#endif
-
-  clear_error(ec);
-  return new_s;
-}
-
-template <typename SockLenType>
-inline int call_bind(SockLenType msghdr::*,
-    socket_type s, const socket_addr_type* addr, std::size_t addrlen)
-{
-  return ::bind(s, addr, (SockLenType)addrlen);
-}
+  // Helper "state" used to determine whether the socket is non-blocking.
+  non_blocking = user_set_non_blocking | internal_non_blocking,
 
-inline int bind(socket_type s, const socket_addr_type* addr,
-    std::size_t addrlen, asio::error_code& ec)
-{
-  clear_error(ec);
-  int result = error_wrapper(call_bind(
-        &msghdr::msg_namelen, s, addr, addrlen), ec);
-  if (result == 0)
-    clear_error(ec);
-  return result;
-}
-
-inline int close(socket_type s, asio::error_code& ec)
-{
-  clear_error(ec);
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-  int result = error_wrapper(::closesocket(s), ec);
-#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-  int result = error_wrapper(::close(s), ec);
-#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-  if (result == 0)
-    clear_error(ec);
-  return result;
-}
+  // User wants connection_aborted errors, which are disabled by default.
+  enable_connection_aborted = 4,
 
-inline int shutdown(socket_type s, int what, asio::error_code& ec)
-{
-  clear_error(ec);
-  int result = error_wrapper(::shutdown(s, what), ec);
-  if (result == 0)
-    clear_error(ec);
-  return result;
-}
-
-template <typename SockLenType>
-inline int call_connect(SockLenType msghdr::*,
-    socket_type s, const socket_addr_type* addr, std::size_t addrlen)
-{
-  return ::connect(s, addr, (SockLenType)addrlen);
-}
+  // The user set the linger option. Needs to be checked when closing.
+  user_set_linger = 8,
 
-inline int connect(socket_type s, const socket_addr_type* addr,
-    std::size_t addrlen, asio::error_code& ec)
-{
-  clear_error(ec);
-  int result = error_wrapper(call_connect(
-        &msghdr::msg_namelen, s, addr, addrlen), ec);
-  if (result == 0)
-    clear_error(ec);
-  return result;
-}
-
-inline int socketpair(int af, int type, int protocol,
-    socket_type sv[2], asio::error_code& ec)
-{
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-  (void)(af);
-  (void)(type);
-  (void)(protocol);
-  (void)(sv);
-  ec = asio::error::operation_not_supported;
-  return -1;
-#else
-  clear_error(ec);
-  int result = error_wrapper(::socketpair(af, type, protocol, sv), ec);
-  if (result == 0)
-    clear_error(ec);
-  return result;
-#endif
-}
-
-inline int listen(socket_type s, int backlog, asio::error_code& ec)
-{
-  clear_error(ec);
-  int result = error_wrapper(::listen(s, backlog), ec);
-  if (result == 0)
-    clear_error(ec);
-  return result;
-}
-
-inline void init_buf_iov_base(void*& base, void* addr)
-{
-  base = addr;
-}
+  // The socket is stream-oriented.
+  stream_oriented = 16,
 
-template <typename T>
-inline void init_buf_iov_base(T& base, void* addr)
-{
-  base = static_cast<T>(addr);
-}
+  // The socket is datagram-oriented.
+  datagram_oriented = 32
+};
+
+typedef unsigned char state_type;
+
+struct noop_deleter { void operator()(void*) {} };
+typedef shared_ptr<void> shared_cancel_token_type;
+typedef weak_ptr<void> weak_cancel_token_type;
+
+ASIO_DECL socket_type accept(socket_type s, socket_addr_type* addr,
+    std::size_t* addrlen, asio::error_code& ec);
+
+ASIO_DECL socket_type sync_accept(socket_type s,
+    state_type state, socket_addr_type* addr,
+    std::size_t* addrlen, asio::error_code& ec);
+
+#if defined(ASIO_HAS_IOCP)
+
+ASIO_DECL void complete_iocp_accept(socket_type s,
+    void* output_buffer, DWORD address_length,
+    socket_addr_type* addr, std::size_t* addrlen,
+    socket_type new_socket, asio::error_code& ec);
+
+#else // defined(ASIO_HAS_IOCP)
+
+ASIO_DECL bool non_blocking_accept(socket_type s,
+    state_type state, socket_addr_type* addr, std::size_t* addrlen,
+    asio::error_code& ec, socket_type& new_socket);
+
+#endif // defined(ASIO_HAS_IOCP)
+
+ASIO_DECL int bind(socket_type s, const socket_addr_type* addr,
+    std::size_t addrlen, asio::error_code& ec);
+
+ASIO_DECL int close(socket_type s, state_type& state,
+    bool destruction, asio::error_code& ec);
+
+ASIO_DECL bool set_internal_non_blocking(socket_type s,
+    state_type& state, asio::error_code& ec);
+
+ASIO_DECL int shutdown(socket_type s,
+    int what, asio::error_code& ec);
+
+ASIO_DECL int connect(socket_type s, const socket_addr_type* addr,
+    std::size_t addrlen, asio::error_code& ec);
+
+ASIO_DECL void sync_connect(socket_type s, const socket_addr_type* addr,
+    std::size_t addrlen, asio::error_code& ec);
+
+ASIO_DECL bool non_blocking_connect(
+    socket_type s, asio::error_code& ec);
+
+ASIO_DECL int socketpair(int af, int type, int protocol,
+    socket_type sv[2], asio::error_code& ec);
+
+ASIO_DECL bool sockatmark(socket_type s, asio::error_code& ec);
+
+ASIO_DECL size_t available(socket_type s, asio::error_code& ec);
+
+ASIO_DECL int listen(socket_type s,
+    int backlog, asio::error_code& ec);
 
 #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
 typedef WSABUF buf;
@@ -209,1699 +118,163 @@ typedef WSABUF buf;
 typedef iovec buf;
 #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
 
-inline void init_buf(buf& b, void* data, size_t size)
-{
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-  b.buf = static_cast<char*>(data);
-  b.len = static_cast<u_long>(size);
-#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-  init_buf_iov_base(b.iov_base, data);
-  b.iov_len = size;
-#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-}
+ASIO_DECL void init_buf(buf& b, void* data, size_t size);
 
-inline void init_buf(buf& b, const void* data, size_t size)
-{
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-  b.buf = static_cast<char*>(const_cast<void*>(data));
-  b.len = static_cast<u_long>(size);
-#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-  init_buf_iov_base(b.iov_base, const_cast<void*>(data));
-  b.iov_len = size;
-#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-}
+ASIO_DECL void init_buf(buf& b, const void* data, size_t size);
 
-inline void init_msghdr_msg_name(void*& name, socket_addr_type* addr)
-{
-  name = addr;
-}
+ASIO_DECL int recv(socket_type s, buf* bufs, size_t count, int flags,
+    asio::error_code& ec);
 
-inline void init_msghdr_msg_name(void*& name, const socket_addr_type* addr)
-{
-  name = const_cast<socket_addr_type*>(addr);
-}
+ASIO_DECL size_t sync_recv(socket_type s, state_type state, buf* bufs,
+    size_t count, int flags, bool all_empty, asio::error_code& ec);
 
-template <typename T>
-inline void init_msghdr_msg_name(T& name, socket_addr_type* addr)
-{
-  name = reinterpret_cast<T>(addr);
-}
+#if defined(ASIO_HAS_IOCP)
 
-template <typename T>
-inline void init_msghdr_msg_name(T& name, const socket_addr_type* addr)
-{
-  name = reinterpret_cast<T>(const_cast<socket_addr_type*>(addr));
-}
+ASIO_DECL void complete_iocp_recv(state_type state,
+    const weak_cancel_token_type& cancel_token, bool all_empty,
+    asio::error_code& ec, size_t bytes_transferred);
 
-inline int recv(socket_type s, buf* bufs, size_t count, int flags,
-    asio::error_code& ec)
-{
-  clear_error(ec);
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-  // Receive some data.
-  DWORD recv_buf_count = static_cast<DWORD>(count);
-  DWORD bytes_transferred = 0;
-  DWORD recv_flags = flags;
-  int result = error_wrapper(::WSARecv(s, bufs,
-        recv_buf_count, &bytes_transferred, &recv_flags, 0, 0), ec);
-  if (result != 0)
-    return -1;
-  clear_error(ec);
-  return bytes_transferred;
-#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-  msghdr msg = msghdr();
-  msg.msg_iov = bufs;
-  msg.msg_iovlen = count;
-  int result = error_wrapper(::recvmsg(s, &msg, flags), ec);
-  if (result >= 0)
-    clear_error(ec);
-  return result;
-#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-}
+#else // defined(ASIO_HAS_IOCP)
+
+ASIO_DECL bool non_blocking_recv(socket_type s,
+    buf* bufs, size_t count, int flags, bool is_stream,
+    asio::error_code& ec, size_t& bytes_transferred);
+
+#endif // defined(ASIO_HAS_IOCP)
 
-inline int recvfrom(socket_type s, buf* bufs, size_t count, int flags,
+ASIO_DECL int recvfrom(socket_type s, buf* bufs, size_t count, int flags,
     socket_addr_type* addr, std::size_t* addrlen,
-    asio::error_code& ec)
-{
-  clear_error(ec);
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-  // Receive some data.
-  DWORD recv_buf_count = static_cast<DWORD>(count);
-  DWORD bytes_transferred = 0;
-  DWORD recv_flags = flags;
-  int tmp_addrlen = (int)*addrlen;
-  int result = error_wrapper(::WSARecvFrom(s, bufs, recv_buf_count,
-        &bytes_transferred, &recv_flags, addr, &tmp_addrlen, 0, 0), ec);
-  *addrlen = (std::size_t)tmp_addrlen;
-  if (result != 0)
-    return -1;
-  clear_error(ec);
-  return bytes_transferred;
-#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-  msghdr msg = msghdr();
-  init_msghdr_msg_name(msg.msg_name, addr);
-  msg.msg_namelen = *addrlen;
-  msg.msg_iov = bufs;
-  msg.msg_iovlen = count;
-  int result = error_wrapper(::recvmsg(s, &msg, flags), ec);
-  *addrlen = msg.msg_namelen;
-  if (result >= 0)
-    clear_error(ec);
-  return result;
-#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-}
+    asio::error_code& ec);
 
-inline int send(socket_type s, const buf* bufs, size_t count, int flags,
-    asio::error_code& ec)
-{
-  clear_error(ec);
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-  // Send the data.
-  DWORD send_buf_count = static_cast<DWORD>(count);
-  DWORD bytes_transferred = 0;
-  DWORD send_flags = flags;
-  int result = error_wrapper(::WSASend(s, const_cast<buf*>(bufs),
-        send_buf_count, &bytes_transferred, send_flags, 0, 0), ec);
-  if (result != 0)
-    return -1;
-  clear_error(ec);
-  return bytes_transferred;
-#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-  msghdr msg = msghdr();
-  msg.msg_iov = const_cast<buf*>(bufs);
-  msg.msg_iovlen = count;
-#if defined(__linux__)
-  flags |= MSG_NOSIGNAL;
-#endif // defined(__linux__)
-  int result = error_wrapper(::sendmsg(s, &msg, flags), ec);
-  if (result >= 0)
-    clear_error(ec);
-  return result;
-#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-}
+ASIO_DECL size_t sync_recvfrom(socket_type s, state_type state,
+    buf* bufs, size_t count, int flags, socket_addr_type* addr,
+    std::size_t* addrlen, asio::error_code& ec);
+
+#if defined(ASIO_HAS_IOCP)
+
+ASIO_DECL void complete_iocp_recvfrom(
+    const weak_cancel_token_type& cancel_token,
+    asio::error_code& ec);
+
+#else // defined(ASIO_HAS_IOCP)
+
+ASIO_DECL bool non_blocking_recvfrom(socket_type s,
+    buf* bufs, size_t count, int flags,
+    socket_addr_type* addr, std::size_t* addrlen,
+    asio::error_code& ec, size_t& bytes_transferred);
+
+#endif // defined(ASIO_HAS_IOCP)
+
+ASIO_DECL int send(socket_type s, const buf* bufs,
+    size_t count, int flags, asio::error_code& ec);
+
+ASIO_DECL size_t sync_send(socket_type s, state_type state,
+    const buf* bufs, size_t count, int flags,
+    bool all_empty, asio::error_code& ec);
+
+#if defined(ASIO_HAS_IOCP)
+
+ASIO_DECL void complete_iocp_send(
+    const weak_cancel_token_type& cancel_token,
+    asio::error_code& ec);
+
+#else // defined(ASIO_HAS_IOCP)
 
-inline int sendto(socket_type s, const buf* bufs, size_t count, int flags,
+ASIO_DECL bool non_blocking_send(socket_type s,
+    const buf* bufs, size_t count, int flags,
+    asio::error_code& ec, size_t& bytes_transferred);
+
+#endif // defined(ASIO_HAS_IOCP)
+
+ASIO_DECL int sendto(socket_type s, const buf* bufs, size_t count,
+    int flags, const socket_addr_type* addr, std::size_t addrlen,
+    asio::error_code& ec);
+
+ASIO_DECL size_t sync_sendto(socket_type s, state_type state,
+    const buf* bufs, size_t count, int flags, const socket_addr_type* addr,
+    std::size_t addrlen, asio::error_code& ec);
+
+#if !defined(ASIO_HAS_IOCP)
+
+ASIO_DECL bool non_blocking_sendto(socket_type s,
+    const buf* bufs, size_t count, int flags,
     const socket_addr_type* addr, std::size_t addrlen,
-    asio::error_code& ec)
-{
-  clear_error(ec);
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-  // Send the data.
-  DWORD send_buf_count = static_cast<DWORD>(count);
-  DWORD bytes_transferred = 0;
-  int result = error_wrapper(::WSASendTo(s, const_cast<buf*>(bufs),
-        send_buf_count, &bytes_transferred, flags, addr,
-        static_cast<int>(addrlen), 0, 0), ec);
-  if (result != 0)
-    return -1;
-  clear_error(ec);
-  return bytes_transferred;
-#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-  msghdr msg = msghdr();
-  init_msghdr_msg_name(msg.msg_name, addr);
-  msg.msg_namelen = addrlen;
-  msg.msg_iov = const_cast<buf*>(bufs);
-  msg.msg_iovlen = count;
-#if defined(__linux__)
-  flags |= MSG_NOSIGNAL;
-#endif // defined(__linux__)
-  int result = error_wrapper(::sendmsg(s, &msg, flags), ec);
-  if (result >= 0)
-    clear_error(ec);
-  return result;
-#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-}
+    asio::error_code& ec, size_t& bytes_transferred);
 
-inline socket_type socket(int af, int type, int protocol,
-    asio::error_code& ec)
-{
-  clear_error(ec);
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-  socket_type s = error_wrapper(::WSASocket(af, type, protocol, 0, 0,
-        WSA_FLAG_OVERLAPPED), ec);
-  if (s == invalid_socket)
-    return s;
-
-  if (af == AF_INET6)
-  {
-    // Try to enable the POSIX default behaviour of having IPV6_V6ONLY set to
-    // false. This will only succeed on Windows Vista and later versions of
-    // Windows, where a dual-stack IPv4/v6 implementation is available.
-    DWORD optval = 0;
-    ::setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
-        reinterpret_cast<const char*>(&optval), sizeof(optval));
-  }
-
-  clear_error(ec);
-
-  return s;
-#elif defined(__MACH__) && defined(__APPLE__) || defined(__FreeBSD__)
-  socket_type s = error_wrapper(::socket(af, type, protocol), ec);
-  if (s == invalid_socket)
-    return s;
-
-  int optval = 1;
-  int result = error_wrapper(::setsockopt(s,
-        SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval)), ec);
-  if (result != 0)
-  {
-    ::close(s);
-    return invalid_socket;
-  }
-
-  return s;
-#else
-  int s = error_wrapper(::socket(af, type, protocol), ec);
-  if (s >= 0)
-    clear_error(ec);
-  return s;
-#endif
-}
-
-template <typename SockLenType>
-inline int call_setsockopt(SockLenType msghdr::*,
-    socket_type s, int level, int optname,
-    const void* optval, std::size_t optlen)
-{
-  return ::setsockopt(s, level, optname,
-      (const char*)optval, (SockLenType)optlen);
-}
+#endif // !defined(ASIO_HAS_IOCP)
 
-inline int setsockopt(socket_type s, int level, int optname,
-    const void* optval, std::size_t optlen, asio::error_code& ec)
-{
-  if (level == custom_socket_option_level && optname == always_fail_option)
-  {
-    ec = asio::error::invalid_argument;
-    return -1;
-  }
-
-#if defined(__BORLANDC__)
-  // Mysteriously, using the getsockopt and setsockopt functions directly with
-  // Borland C++ results in incorrect values being set and read. The bug can be
-  // worked around by using function addresses resolved with GetProcAddress.
-  if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32"))
-  {
-    typedef int (WSAAPI *sso_t)(SOCKET, int, int, const char*, int);
-    if (sso_t sso = (sso_t)::GetProcAddress(winsock_module, "setsockopt"))
-    {
-      clear_error(ec);
-      return error_wrapper(sso(s, level, optname,
-            reinterpret_cast<const char*>(optval),
-            static_cast<int>(optlen)), ec);
-    }
-  }
-  ec = asio::error::fault;
-  return -1;
-#else // defined(__BORLANDC__)
-  clear_error(ec);
-  int result = error_wrapper(call_setsockopt(&msghdr::msg_namelen,
-        s, level, optname, optval, optlen), ec);
-  if (result == 0)
-    clear_error(ec);
-  return result;
-#endif // defined(__BORLANDC__)
-}
-
-template <typename SockLenType>
-inline int call_getsockopt(SockLenType msghdr::*,
-    socket_type s, int level, int optname,
-    void* optval, std::size_t* optlen)
-{
-  SockLenType tmp_optlen = (SockLenType)*optlen;
-  int result = ::getsockopt(s, level, optname, (char*)optval, &tmp_optlen);
-  *optlen = (std::size_t)tmp_optlen;
-  return result;
-}
-
-inline int getsockopt(socket_type s, int level, int optname, void* optval,
-    size_t* optlen, asio::error_code& ec)
-{
-  if (level == custom_socket_option_level && optname == always_fail_option)
-  {
-    ec = asio::error::invalid_argument;
-    return -1;
-  }
-
-#if defined(__BORLANDC__)
-  // Mysteriously, using the getsockopt and setsockopt functions directly with
-  // Borland C++ results in incorrect values being set and read. The bug can be
-  // worked around by using function addresses resolved with GetProcAddress.
-  if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32"))
-  {
-    typedef int (WSAAPI *gso_t)(SOCKET, int, int, char*, int*);
-    if (gso_t gso = (gso_t)::GetProcAddress(winsock_module, "getsockopt"))
-    {
-      clear_error(ec);
-      int tmp_optlen = static_cast<int>(*optlen);
-      int result = error_wrapper(gso(s, level, optname,
-            reinterpret_cast<char*>(optval), &tmp_optlen), ec);
-      *optlen = static_cast<size_t>(tmp_optlen);
-      if (result != 0 && level == IPPROTO_IPV6 && optname == IPV6_V6ONLY
-          && ec.value() == WSAENOPROTOOPT && *optlen == sizeof(DWORD))
-      {
-        // Dual-stack IPv4/v6 sockets, and the IPV6_V6ONLY socket option, are
-        // only supported on Windows Vista and later. To simplify program logic
-        // we will fake success of getting this option and specify that the
-        // value is non-zero (i.e. true). This corresponds to the behavior of
-        // IPv6 sockets on Windows platforms pre-Vista.
-        *static_cast<DWORD*>(optval) = 1;
-        clear_error(ec);
-      }
-      return result;
-    }
-  }
-  ec = asio::error::fault;
-  return -1;
-#elif defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-  clear_error(ec);
-  int result = error_wrapper(call_getsockopt(&msghdr::msg_namelen,
-        s, level, optname, optval, optlen), ec);
-  if (result != 0 && level == IPPROTO_IPV6 && optname == IPV6_V6ONLY
-      && ec.value() == WSAENOPROTOOPT && *optlen == sizeof(DWORD))
-  {
-    // Dual-stack IPv4/v6 sockets, and the IPV6_V6ONLY socket option, are only
-    // supported on Windows Vista and later. To simplify program logic we will
-    // fake success of getting this option and specify that the value is
-    // non-zero (i.e. true). This corresponds to the behavior of IPv6 sockets
-    // on Windows platforms pre-Vista.
-    *static_cast<DWORD*>(optval) = 1;
-    clear_error(ec);
-  }
-  if (result == 0)
-    clear_error(ec);
-  return result;
-#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-  clear_error(ec);
-  int result = error_wrapper(call_getsockopt(&msghdr::msg_namelen,
-        s, level, optname, optval, optlen), ec);
-#if defined(__linux__)
-  if (result == 0 && level == SOL_SOCKET && *optlen == sizeof(int)
-      && (optname == SO_SNDBUF || optname == SO_RCVBUF))
-  {
-    // On Linux, setting SO_SNDBUF or SO_RCVBUF to N actually causes the kernel
-    // to set the buffer size to N*2. Linux puts additional stuff into the
-    // buffers so that only about half is actually available to the application.
-    // The retrieved value is divided by 2 here to make it appear as though the
-    // correct value has been set.
-    *static_cast<int*>(optval) /= 2;
-  }
-#endif // defined(__linux__)
-  if (result == 0)
-    clear_error(ec);
-  return result;
-#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-}
+ASIO_DECL socket_type socket(int af, int type, int protocol,
+    asio::error_code& ec);
 
-template <typename SockLenType>
-inline int call_getpeername(SockLenType msghdr::*,
-    socket_type s, socket_addr_type* addr, std::size_t* addrlen)
-{
-  SockLenType tmp_addrlen = (SockLenType)*addrlen;
-  int result = ::getpeername(s, addr, &tmp_addrlen);
-  *addrlen = (std::size_t)tmp_addrlen;
-  return result;
-}
-
-inline int getpeername(socket_type s, socket_addr_type* addr,
-    std::size_t* addrlen, asio::error_code& ec)
-{
-  clear_error(ec);
-  int result = error_wrapper(call_getpeername(
-        &msghdr::msg_namelen, s, addr, addrlen), ec);
-  if (result == 0)
-    clear_error(ec);
-  return result;
-}
-
-template <typename SockLenType>
-inline int call_getsockname(SockLenType msghdr::*,
-    socket_type s, socket_addr_type* addr, std::size_t* addrlen)
-{
-  SockLenType tmp_addrlen = (SockLenType)*addrlen;
-  int result = ::getsockname(s, addr, &tmp_addrlen);
-  *addrlen = (std::size_t)tmp_addrlen;
-  return result;
-}
-
-inline int getsockname(socket_type s, socket_addr_type* addr,
-    std::size_t* addrlen, asio::error_code& ec)
-{
-  clear_error(ec);
-  int result = error_wrapper(call_getsockname(
-        &msghdr::msg_namelen, s, addr, addrlen), ec);
-  if (result == 0)
-    clear_error(ec);
-  return result;
-}
-
-inline int ioctl(socket_type s, long cmd, ioctl_arg_type* arg,
-    asio::error_code& ec)
-{
-  clear_error(ec);
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-  int result = error_wrapper(::ioctlsocket(s, cmd, arg), ec);
-#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-  int result = error_wrapper(::ioctl(s, cmd, arg), ec);
-#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-  if (result >= 0)
-    clear_error(ec);
-  return result;
-}
+ASIO_DECL int setsockopt(socket_type s, state_type& state,
+    int level, int optname, const void* optval,
+    std::size_t optlen, asio::error_code& ec);
 
-inline int select(int nfds, fd_set* readfds, fd_set* writefds,
-    fd_set* exceptfds, timeval* timeout, asio::error_code& ec)
-{
-  clear_error(ec);
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-  if (!readfds && !writefds && !exceptfds && timeout)
-  {
-    DWORD milliseconds = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
-    if (milliseconds == 0)
-      milliseconds = 1; // Force context switch.
-    ::Sleep(milliseconds);
-    ec = asio::error_code();
-    return 0;
-  }
-
-  // The select() call allows timeout values measured in microseconds, but the
-  // system clock (as wrapped by boost::posix_time::microsec_clock) typically
-  // has a resolution of 10 milliseconds. This can lead to a spinning select
-  // reactor, meaning increased CPU usage, when waiting for the earliest
-  // scheduled timeout if it's less than 10 milliseconds away. To avoid a tight
-  // spin we'll use a minimum timeout of 1 millisecond.
-  if (timeout && timeout->tv_sec == 0
-      && timeout->tv_usec > 0 && timeout->tv_usec < 1000)
-    timeout->tv_usec = 1000;
-#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ASIO_DECL int getsockopt(socket_type s, state_type state,
+    int level, int optname, void* optval,
+    size_t* optlen, asio::error_code& ec);
 
-#if defined(__hpux) && defined(__HP_aCC)
-  timespec ts;
-  ts.tv_sec = timeout ? timeout->tv_sec : 0;
-  ts.tv_nsec = timeout ? timeout->tv_usec * 1000 : 0;
-  return error_wrapper(::pselect(nfds, readfds,
-        writefds, exceptfds, timeout ? &ts : 0, 0), ec);
-#else
-  int result = error_wrapper(::select(nfds, readfds,
-        writefds, exceptfds, timeout), ec);
-  if (result >= 0)
-    clear_error(ec);
-  return result;
-#endif
-}
-
-inline int poll_read(socket_type s, asio::error_code& ec)
-{
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-  FD_SET fds;
-  FD_ZERO(&fds);
-  FD_SET(s, &fds);
-  clear_error(ec);
-  int result = error_wrapper(::select(s, &fds, 0, 0, 0), ec);
-  if (result >= 0)
-    clear_error(ec);
-  return result;
-#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-  pollfd fds;
-  fds.fd = s;
-  fds.events = POLLIN;
-  fds.revents = 0;
-  clear_error(ec);
-  int result = error_wrapper(::poll(&fds, 1, -1), ec);
-  if (result >= 0)
-    clear_error(ec);
-  return result;
-#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-}
+ASIO_DECL int getpeername(socket_type s, socket_addr_type* addr,
+    std::size_t* addrlen, bool cached, asio::error_code& ec);
 
-inline int poll_write(socket_type s, asio::error_code& ec)
-{
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-  FD_SET fds;
-  FD_ZERO(&fds);
-  FD_SET(s, &fds);
-  clear_error(ec);
-  int result = error_wrapper(::select(s, 0, &fds, 0, 0), ec);
-  if (result >= 0)
-    clear_error(ec);
-  return result;
-#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-  pollfd fds;
-  fds.fd = s;
-  fds.events = POLLOUT;
-  fds.revents = 0;
-  clear_error(ec);
-  int result = error_wrapper(::poll(&fds, 1, -1), ec);
-  if (result >= 0)
-    clear_error(ec);
-  return result;
-#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-}
+ASIO_DECL int getsockname(socket_type s, socket_addr_type* addr,
+    std::size_t* addrlen, asio::error_code& ec);
 
-inline int poll_connect(socket_type s, asio::error_code& ec)
-{
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-  FD_SET write_fds;
-  FD_ZERO(&write_fds);
-  FD_SET(s, &write_fds);
-  FD_SET except_fds;
-  FD_ZERO(&except_fds);
-  FD_SET(s, &except_fds);
-  clear_error(ec);
-  int result = error_wrapper(::select(s, 0, &write_fds, &except_fds, 0), ec);
-  if (result >= 0)
-    clear_error(ec);
-  return result;
-#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-  pollfd fds;
-  fds.fd = s;
-  fds.events = POLLOUT;
-  fds.revents = 0;
-  clear_error(ec);
-  int result = error_wrapper(::poll(&fds, 1, -1), ec);
-  if (result >= 0)
-    clear_error(ec);
-  return result;
-#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-}
+ASIO_DECL int ioctl(socket_type s, state_type& state,
+    int cmd, ioctl_arg_type* arg, asio::error_code& ec);
 
-inline const char* inet_ntop(int af, const void* src, char* dest, size_t length,
-    unsigned long scope_id, asio::error_code& ec)
-{
-  clear_error(ec);
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-  using namespace std; // For memcpy.
-
-  if (af != AF_INET && af != AF_INET6)
-  {
-    ec = asio::error::address_family_not_supported;
-    return 0;
-  }
-
-  union
-  {
-    socket_addr_type base;
-    sockaddr_storage_type storage;
-    sockaddr_in4_type v4;
-    sockaddr_in6_type v6;
-  } address;
-  DWORD address_length;
-  if (af == AF_INET)
-  {
-    address_length = sizeof(sockaddr_in4_type);
-    address.v4.sin_family = AF_INET;
-    address.v4.sin_port = 0;
-    memcpy(&address.v4.sin_addr, src, sizeof(in4_addr_type));
-  }
-  else // AF_INET6
-  {
-    address_length = sizeof(sockaddr_in6_type);
-    address.v6.sin6_family = AF_INET6;
-    address.v6.sin6_port = 0;
-    address.v6.sin6_flowinfo = 0;
-    address.v6.sin6_scope_id = scope_id;
-    memcpy(&address.v6.sin6_addr, src, sizeof(in6_addr_type));
-  }
-
-  DWORD string_length = static_cast<DWORD>(length);
-#if defined(BOOST_NO_ANSI_APIS)
-  LPWSTR string_buffer = (LPWSTR)_alloca(length * sizeof(WCHAR));
-  int result = error_wrapper(::WSAAddressToStringW(&address.base,
-        address_length, 0, string_buffer, &string_length), ec);
-  ::WideCharToMultiByte(CP_ACP, 0, string_buffer, -1, dest, length, 0, 0);
-#else
-  int result = error_wrapper(::WSAAddressToStringA(
-        &address.base, address_length, 0, dest, &string_length), ec);
-#endif
-
-  // Windows may set error code on success.
-  if (result != socket_error_retval)
-    clear_error(ec);
-
-  // Windows may not set an error code on failure.
-  else if (result == socket_error_retval && !ec)
-    ec = asio::error::invalid_argument;
-
-  return result == socket_error_retval ? 0 : dest;
-#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-  const char* result = error_wrapper(::inet_ntop(af, src, dest, length), ec);
-  if (result == 0 && !ec)
-    ec = asio::error::invalid_argument;
-  if (result != 0 && af == AF_INET6 && scope_id != 0)
-  {
-    using namespace std; // For strcat and sprintf.
-    char if_name[IF_NAMESIZE + 1] = "%";
-    const in6_addr_type* ipv6_address = static_cast<const in6_addr_type*>(src);
-    bool is_link_local = IN6_IS_ADDR_LINKLOCAL(ipv6_address);
-    if (!is_link_local || if_indextoname(scope_id, if_name + 1) == 0)
-      sprintf(if_name + 1, "%lu", scope_id);
-    strcat(dest, if_name);
-  }
-  return result;
-#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-}
+ASIO_DECL int select(int nfds, fd_set* readfds, fd_set* writefds,
+    fd_set* exceptfds, timeval* timeout, asio::error_code& ec);
 
-inline int inet_pton(int af, const char* src, void* dest,
-    unsigned long* scope_id, asio::error_code& ec)
-{
-  clear_error(ec);
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-  using namespace std; // For memcpy and strcmp.
-
-  if (af != AF_INET && af != AF_INET6)
-  {
-    ec = asio::error::address_family_not_supported;
-    return -1;
-  }
-
-  union
-  {
-    socket_addr_type base;
-    sockaddr_storage_type storage;
-    sockaddr_in4_type v4;
-    sockaddr_in6_type v6;
-  } address;
-  int address_length = sizeof(sockaddr_storage_type);
-#if defined(BOOST_NO_ANSI_APIS)
-  int num_wide_chars = strlen(src) + 1;
-  LPWSTR wide_buffer = (LPWSTR)_alloca(num_wide_chars * sizeof(WCHAR));
-  ::MultiByteToWideChar(CP_ACP, 0, src, -1, wide_buffer, num_wide_chars);
-  int result = error_wrapper(::WSAStringToAddressW(
-        wide_buffer, af, 0, &address.base, &address_length), ec);
-#else
-  int result = error_wrapper(::WSAStringToAddressA(
-        const_cast<char*>(src), af, 0, &address.base, &address_length), ec);
-#endif
-
-  if (af == AF_INET)
-  {
-    if (result != socket_error_retval)
-    {
-      memcpy(dest, &address.v4.sin_addr, sizeof(in4_addr_type));
-      clear_error(ec);
-    }
-    else if (strcmp(src, "255.255.255.255") == 0)
-    {
-      static_cast<in4_addr_type*>(dest)->s_addr = INADDR_NONE;
-      clear_error(ec);
-    }
-  }
-  else // AF_INET6
-  {
-    if (result != socket_error_retval)
-    {
-      memcpy(dest, &address.v6.sin6_addr, sizeof(in6_addr_type));
-      if (scope_id)
-        *scope_id = address.v6.sin6_scope_id;
-      clear_error(ec);
-    }
-  }
-
-  // Windows may not set an error code on failure.
-  if (result == socket_error_retval && !ec)
-    ec = asio::error::invalid_argument;
-
-  if (result != socket_error_retval)
-    clear_error(ec);
-
-  return result == socket_error_retval ? -1 : 1;
-#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-  int result = error_wrapper(::inet_pton(af, src, dest), ec);
-  if (result <= 0 && !ec)
-    ec = asio::error::invalid_argument;
-  if (result > 0 && af == AF_INET6 && scope_id)
-  {
-    using namespace std; // For strchr and atoi.
-    *scope_id = 0;
-    if (const char* if_name = strchr(src, '%'))
-    {
-      in6_addr_type* ipv6_address = static_cast<in6_addr_type*>(dest);
-      bool is_link_local = IN6_IS_ADDR_LINKLOCAL(ipv6_address);
-      if (is_link_local)
-        *scope_id = if_nametoindex(if_name + 1);
-      if (*scope_id == 0)
-        *scope_id = atoi(if_name + 1);
-    }
-  }
-  return result;
-#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-}
+ASIO_DECL int poll_read(socket_type s, asio::error_code& ec);
 
-inline int gethostname(char* name, int namelen, asio::error_code& ec)
-{
-  clear_error(ec);
-  int result = error_wrapper(::gethostname(name, namelen), ec);
-#if defined(BOOST_WINDOWS)
-  if (result == 0)
-    clear_error(ec);
-#endif
-  return result;
-}
-
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) \
-  || defined(__MACH__) && defined(__APPLE__)
-
-// The following functions are only needed for emulation of getaddrinfo and
-// getnameinfo.
-
-inline asio::error_code translate_netdb_error(int error)
-{
-  switch (error)
-  {
-  case 0:
-    return asio::error_code();
-  case HOST_NOT_FOUND:
-    return asio::error::host_not_found;
-  case TRY_AGAIN:
-    return asio::error::host_not_found_try_again;
-  case NO_RECOVERY:
-    return asio::error::no_recovery;
-  case NO_DATA:
-    return asio::error::no_data;
-  default:
-    BOOST_ASSERT(false);
-    return asio::error::invalid_argument;
-  }
-}
-
-inline hostent* gethostbyaddr(const char* addr, int length, int af,
-    hostent* result, char* buffer, int buflength, asio::error_code& ec)
-{
-  clear_error(ec);
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-  (void)(buffer);
-  (void)(buflength);
-  hostent* retval = error_wrapper(::gethostbyaddr(addr, length, af), ec);
-  if (!retval)
-    return 0;
-  clear_error(ec);
-  *result = *retval;
-  return retval;
-#elif defined(__sun) || defined(__QNX__)
-  int error = 0;
-  hostent* retval = error_wrapper(::gethostbyaddr_r(addr, length, af, result,
-        buffer, buflength, &error), ec);
-  if (error)
-    ec = translate_netdb_error(error);
-  return retval;
-#elif defined(__MACH__) && defined(__APPLE__)
-  (void)(buffer);
-  (void)(buflength);
-  int error = 0;
-  hostent* retval = error_wrapper(::getipnodebyaddr(
-        addr, length, af, &error), ec);
-  if (error)
-    ec = translate_netdb_error(error);
-  if (!retval)
-    return 0;
-  *result = *retval;
-  return retval;
-#else
-  hostent* retval = 0;
-  int error = 0;
-  error_wrapper(::gethostbyaddr_r(addr, length, af, result, buffer,
-        buflength, &retval, &error), ec);
-  if (error)
-    ec = translate_netdb_error(error);
-  return retval;
-#endif
-}
-
-inline hostent* gethostbyname(const char* name, int af, struct hostent* result,
-    char* buffer, int buflength, int ai_flags, asio::error_code& ec)
-{
-  clear_error(ec);
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-  (void)(buffer);
-  (void)(buflength);
-  (void)(ai_flags);
-  if (af != AF_INET)
-  {
-    ec = asio::error::address_family_not_supported;
-    return 0;
-  }
-  hostent* retval = error_wrapper(::gethostbyname(name), ec);
-  if (!retval)
-    return 0;
-  clear_error(ec);
-  *result = *retval;
-  return result;
-#elif defined(__sun) || defined(__QNX__)
-  (void)(ai_flags);
-  if (af != AF_INET)
-  {
-    ec = asio::error::address_family_not_supported;
-    return 0;
-  }
-  int error = 0;
-  hostent* retval = error_wrapper(::gethostbyname_r(name, result, buffer,
-        buflength, &error), ec);
-  if (error)
-    ec = translate_netdb_error(error);
-  return retval;
-#elif defined(__MACH__) && defined(__APPLE__)
-  (void)(buffer);
-  (void)(buflength);
-  int error = 0;
-  hostent* retval = error_wrapper(::getipnodebyname(
-        name, af, ai_flags, &error), ec);
-  if (error)
-    ec = translate_netdb_error(error);
-  if (!retval)
-    return 0;
-  *result = *retval;
-  return retval;
-#else
-  (void)(ai_flags);
-  if (af != AF_INET)
-  {
-    ec = asio::error::address_family_not_supported;
-    return 0;
-  }
-  hostent* retval = 0;
-  int error = 0;
-  error_wrapper(::gethostbyname_r(name, result,
-        buffer, buflength, &retval, &error), ec);
-  if (error)
-    ec = translate_netdb_error(error);
-  return retval;
-#endif
-}
-
-inline void freehostent(hostent* h)
-{
-#if defined(__MACH__) && defined(__APPLE__)
-  if (h)
-    ::freehostent(h);
-#else
-  (void)(h);
-#endif
-}
-
-// Emulation of getaddrinfo based on implementation in:
-// Stevens, W. R., UNIX Network Programming Vol. 1, 2nd Ed., Prentice-Hall 1998.
-
-struct gai_search
-{
-  const char* host;
-  int family;
-};
+ASIO_DECL int poll_write(socket_type s, asio::error_code& ec);
 
-inline int gai_nsearch(const char* host,
-    const addrinfo_type* hints, gai_search (&search)[2])
-{
-  int search_count = 0;
-  if (host == 0 || host[0] == '\0')
-  {
-    if (hints->ai_flags & AI_PASSIVE)
-    {
-      // No host and AI_PASSIVE implies wildcard bind.
-      switch (hints->ai_family)
-      {
-      case AF_INET:
-        search[search_count].host = "0.0.0.0";
-        search[search_count].family = AF_INET;
-        ++search_count;
-        break;
-      case AF_INET6:
-        search[search_count].host = "0::0";
-        search[search_count].family = AF_INET6;
-        ++search_count;
-        break;
-      case AF_UNSPEC:
-        search[search_count].host = "0::0";
-        search[search_count].family = AF_INET6;
-        ++search_count;
-        search[search_count].host = "0.0.0.0";
-        search[search_count].family = AF_INET;
-        ++search_count;
-        break;
-      default:
-        break;
-      }
-    }
-    else
-    {
-      // No host and not AI_PASSIVE means connect to local host.
-      switch (hints->ai_family)
-      {
-      case AF_INET:
-        search[search_count].host = "localhost";
-        search[search_count].family = AF_INET;
-        ++search_count;
-        break;
-      case AF_INET6:
-        search[search_count].host = "localhost";
-        search[search_count].family = AF_INET6;
-        ++search_count;
-        break;
-      case AF_UNSPEC:
-        search[search_count].host = "localhost";
-        search[search_count].family = AF_INET6;
-        ++search_count;
-        search[search_count].host = "localhost";
-        search[search_count].family = AF_INET;
-        ++search_count;
-        break;
-      default:
-        break;
-      }
-    }
-  }
-  else
-  {
-    // Host is specified.
-    switch (hints->ai_family)
-    {
-    case AF_INET:
-      search[search_count].host = host;
-      search[search_count].family = AF_INET;
-      ++search_count;
-      break;
-    case AF_INET6:
-      search[search_count].host = host;
-      search[search_count].family = AF_INET6;
-      ++search_count;
-      break;
-    case AF_UNSPEC:
-      search[search_count].host = host;
-      search[search_count].family = AF_INET6;
-      ++search_count;
-      search[search_count].host = host;
-      search[search_count].family = AF_INET;
-      ++search_count;
-      break;
-    default:
-      break;
-    }
-  }
-  return search_count;
-}
-
-template <typename T>
-inline T* gai_alloc(std::size_t size = sizeof(T))
-{
-  using namespace std;
-  T* p = static_cast<T*>(::operator new(size, std::nothrow));
-  if (p)
-    memset(p, 0, size);
-  return p;
-}
-
-inline void gai_free(void* p)
-{
-  ::operator delete(p);
-}
+ASIO_DECL int poll_connect(socket_type s, asio::error_code& ec);
 
-inline void gai_strcpy(char* target, const char* source, std::size_t max_size)
-{
-  using namespace std;
-#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) && !defined(UNDER_CE)
-  strcpy_s(target, max_size, source);
-#else
-  *target = 0;
-  strncat(target, source, max_size);
-#endif
-}
-
-enum { gai_clone_flag = 1 << 30 };
-
-inline int gai_aistruct(addrinfo_type*** next, const addrinfo_type* hints,
-    const void* addr, int family)
-{
-  using namespace std;
-
-  addrinfo_type* ai = gai_alloc<addrinfo_type>();
-  if (ai == 0)
-    return EAI_MEMORY;
-
-  ai->ai_next = 0;
-  **next = ai;
-  *next = &ai->ai_next;
-
-  ai->ai_canonname = 0;
-  ai->ai_socktype = hints->ai_socktype;
-  if (ai->ai_socktype == 0)
-    ai->ai_flags |= gai_clone_flag;
-  ai->ai_protocol = hints->ai_protocol;
-  ai->ai_family = family;
-
-  switch (ai->ai_family)
-  {
-  case AF_INET:
-    {
-      sockaddr_in4_type* sinptr = gai_alloc<sockaddr_in4_type>();
-      if (sinptr == 0)
-        return EAI_MEMORY;
-      sinptr->sin_family = AF_INET;
-      memcpy(&sinptr->sin_addr, addr, sizeof(in4_addr_type));
-      ai->ai_addr = reinterpret_cast<sockaddr*>(sinptr);
-      ai->ai_addrlen = sizeof(sockaddr_in4_type);
-      break;
-    }
-  case AF_INET6:
-    {
-      sockaddr_in6_type* sin6ptr = gai_alloc<sockaddr_in6_type>();
-      if (sin6ptr == 0)
-        return EAI_MEMORY;
-      sin6ptr->sin6_family = AF_INET6;
-      memcpy(&sin6ptr->sin6_addr, addr, sizeof(in6_addr_type));
-      ai->ai_addr = reinterpret_cast<sockaddr*>(sin6ptr);
-      ai->ai_addrlen = sizeof(sockaddr_in6_type);
-      break;
-    }
-  default:
-    break;
-  }
-
-  return 0;
-}
-
-inline addrinfo_type* gai_clone(addrinfo_type* ai)
-{
-  using namespace std;
+ASIO_DECL const char* inet_ntop(int af, const void* src, char* dest,
+    size_t length, unsigned long scope_id, asio::error_code& ec);
 
-  addrinfo_type* new_ai = gai_alloc<addrinfo_type>();
-  if (new_ai == 0)
-    return new_ai;
+ASIO_DECL int inet_pton(int af, const char* src, void* dest,
+    unsigned long* scope_id, asio::error_code& ec);
 
-  new_ai->ai_next = ai->ai_next;
-  ai->ai_next = new_ai;
+ASIO_DECL int gethostname(char* name,
+    int namelen, asio::error_code& ec);
 
-  new_ai->ai_flags = 0;
-  new_ai->ai_family = ai->ai_family;
-  new_ai->ai_socktype = ai->ai_socktype;
-  new_ai->ai_protocol = ai->ai_protocol;
-  new_ai->ai_canonname = 0;
-  new_ai->ai_addrlen = ai->ai_addrlen;
-  new_ai->ai_addr = gai_alloc<sockaddr>(ai->ai_addrlen);
-  memcpy(new_ai->ai_addr, ai->ai_addr, ai->ai_addrlen);
+ASIO_DECL asio::error_code getaddrinfo(const char* host,
+    const char* service, const addrinfo_type& hints,
+    addrinfo_type** result, asio::error_code& ec);
 
-  return new_ai;
-}
+ASIO_DECL asio::error_code background_getaddrinfo(
+    const weak_cancel_token_type& cancel_token, const char* host,
+    const char* service, const addrinfo_type& hints,
+    addrinfo_type** result, asio::error_code& ec);
 
-inline int gai_port(addrinfo_type* aihead, int port, int socktype)
-{
-  int num_found = 0;
-
-  for (addrinfo_type* ai = aihead; ai; ai = ai->ai_next)
-  {
-    if (ai->ai_flags & gai_clone_flag)
-    {
-      if (ai->ai_socktype != 0)
-      {
-        ai = gai_clone(ai);
-        if (ai == 0)
-          return -1;
-        // ai now points to newly cloned entry.
-      }
-    }
-    else if (ai->ai_socktype != socktype)
-    {
-      // Ignore if mismatch on socket type.
-      continue;
-    }
-
-    ai->ai_socktype = socktype;
-
-    switch (ai->ai_family)
-    {
-    case AF_INET:
-      {
-        sockaddr_in4_type* sinptr =
-          reinterpret_cast<sockaddr_in4_type*>(ai->ai_addr);
-        sinptr->sin_port = port;
-        ++num_found;
-        break;
-      }
-    case AF_INET6:
-      {
-        sockaddr_in6_type* sin6ptr =
-          reinterpret_cast<sockaddr_in6_type*>(ai->ai_addr);
-        sin6ptr->sin6_port = port;
-        ++num_found;
-        break;
-      }
-    default:
-      break;
-    }
-  }
-
-  return num_found;
-}
-
-inline int gai_serv(addrinfo_type* aihead,
-    const addrinfo_type* hints, const char* serv)
-{
-  using namespace std;
-
-  int num_found = 0;
-
-  if (
-#if defined(AI_NUMERICSERV)
-      (hints->ai_flags & AI_NUMERICSERV) ||
-#endif
-      isdigit(serv[0]))
-  {
-    int port = htons(atoi(serv));
-    if (hints->ai_socktype)
-    {
-      // Caller specifies socket type.
-      int rc = gai_port(aihead, port, hints->ai_socktype);
-      if (rc < 0)
-        return EAI_MEMORY;
-      num_found += rc;
-    }
-    else
-    {
-      // Caller does not specify socket type.
-      int rc = gai_port(aihead, port, SOCK_STREAM);
-      if (rc < 0)
-        return EAI_MEMORY;
-      num_found += rc;
-      rc = gai_port(aihead, port, SOCK_DGRAM);
-      if (rc < 0)
-        return EAI_MEMORY;
-      num_found += rc;
-    }
-  }
-  else
-  {
-    // Try service name with TCP first, then UDP.
-    if (hints->ai_socktype == 0 || hints->ai_socktype == SOCK_STREAM)
-    {
-      servent* sptr = getservbyname(serv, "tcp");
-      if (sptr != 0)
-      {
-        int rc = gai_port(aihead, sptr->s_port, SOCK_STREAM);
-        if (rc < 0)
-          return EAI_MEMORY;
-        num_found += rc;
-      }
-    }
-    if (hints->ai_socktype == 0 || hints->ai_socktype == SOCK_DGRAM)
-    {
-      servent* sptr = getservbyname(serv, "udp");
-      if (sptr != 0)
-      {
-        int rc = gai_port(aihead, sptr->s_port, SOCK_DGRAM);
-        if (rc < 0)
-          return EAI_MEMORY;
-        num_found += rc;
-      }
-    }
-  }
-
-  if (num_found == 0)
-  {
-    if (hints->ai_socktype == 0)
-    {
-      // All calls to getservbyname() failed.
-      return EAI_NONAME;
-    }
-    else
-    {
-      // Service not supported for socket type.
-      return EAI_SERVICE;
-    }
-  }
-
-  return 0;
-}
-
-inline int gai_echeck(const char* host, const char* service,
-    int flags, int family, int socktype, int protocol)
-{
-  (void)(flags);
-  (void)(protocol);
-
-  // Host or service must be specified.
-  if (host == 0 || host[0] == '\0')
-    if (service == 0 || service[0] == '\0')
-      return EAI_NONAME;
-
-  // Check combination of family and socket type.
-  switch (family)
-  {
-  case AF_UNSPEC:
-    break;
-  case AF_INET:
-  case AF_INET6:
-    if (service != 0 && service[0] != '\0')
-      if (socktype != 0 && socktype != SOCK_STREAM && socktype != SOCK_DGRAM)
-        return EAI_SOCKTYPE;
-    break;
-  default:
-    return EAI_FAMILY;
-  }
-
-  return 0;
-}
-
-inline void freeaddrinfo_emulation(addrinfo_type* aihead)
-{
-  addrinfo_type* ai = aihead;
-  while (ai)
-  {
-    gai_free(ai->ai_addr);
-    gai_free(ai->ai_canonname);
-    addrinfo_type* ainext = ai->ai_next;
-    gai_free(ai);
-    ai = ainext;
-  }
-}
-
-inline int getaddrinfo_emulation(const char* host, const char* service,
-    const addrinfo_type* hintsp, addrinfo_type** result)
-{
-  // Set up linked list of addrinfo structures.
-  addrinfo_type* aihead = 0;
-  addrinfo_type** ainext = &aihead;
-  char* canon = 0;
-
-  // Supply default hints if not specified by caller.
-  addrinfo_type hints = addrinfo_type();
-  hints.ai_family = AF_UNSPEC;
-  if (hintsp)
-    hints = *hintsp;
-
-  // If the resolution is not specifically for AF_INET6, remove the AI_V4MAPPED
-  // and AI_ALL flags.
-#if defined(AI_V4MAPPED)
-  if (hints.ai_family != AF_INET6)
-    hints.ai_flags &= ~AI_V4MAPPED;
-#endif
-#if defined(AI_ALL)
-  if (hints.ai_family != AF_INET6)
-    hints.ai_flags &= ~AI_ALL;
-#endif
-
-  // Basic error checking.
-  int rc = gai_echeck(host, service, hints.ai_flags, hints.ai_family,
-      hints.ai_socktype, hints.ai_protocol);
-  if (rc != 0)
-  {
-    freeaddrinfo_emulation(aihead);
-    return rc;
-  }
-
-  gai_search search[2];
-  int search_count = gai_nsearch(host, &hints, search);
-  for (gai_search* sptr = search; sptr < search + search_count; ++sptr)
-  {
-    // Check for IPv4 dotted decimal string.
-    in4_addr_type inaddr;
-    asio::error_code ec;
-    if (socket_ops::inet_pton(AF_INET, sptr->host, &inaddr, 0, ec) == 1)
-    {
-      if (hints.ai_family != AF_UNSPEC && hints.ai_family != AF_INET)
-      {
-        freeaddrinfo_emulation(aihead);
-        gai_free(canon);
-        return EAI_FAMILY;
-      }
-      if (sptr->family == AF_INET)
-      {
-        rc = gai_aistruct(&ainext, &hints, &inaddr, AF_INET);
-        if (rc != 0)
-        {
-          freeaddrinfo_emulation(aihead);
-          gai_free(canon);
-          return rc;
-        }
-      }
-      continue;
-    }
-
-    // Check for IPv6 hex string.
-    in6_addr_type in6addr;
-    if (socket_ops::inet_pton(AF_INET6, sptr->host, &in6addr, 0, ec) == 1)
-    {
-      if (hints.ai_family != AF_UNSPEC && hints.ai_family != AF_INET6)
-      {
-        freeaddrinfo_emulation(aihead);
-        gai_free(canon);
-        return EAI_FAMILY;
-      }
-      if (sptr->family == AF_INET6)
-      {
-        rc = gai_aistruct(&ainext, &hints, &in6addr, AF_INET6);
-        if (rc != 0)
-        {
-          freeaddrinfo_emulation(aihead);
-          gai_free(canon);
-          return rc;
-        }
-      }
-      continue;
-    }
-
-    // Look up hostname.
-    hostent hent;
-    char hbuf[8192] = "";
-    hostent* hptr = socket_ops::gethostbyname(sptr->host,
-        sptr->family, &hent, hbuf, sizeof(hbuf), hints.ai_flags, ec);
-    if (hptr == 0)
-    {
-      if (search_count == 2)
-      {
-        // Failure is OK if there are multiple searches.
-        continue;
-      }
-      freeaddrinfo_emulation(aihead);
-      gai_free(canon);
-      if (ec == asio::error::host_not_found)
-        return EAI_NONAME;
-      if (ec == asio::error::host_not_found_try_again)
-        return EAI_AGAIN;
-      if (ec == asio::error::no_recovery)
-        return EAI_FAIL;
-      if (ec == asio::error::no_data)
-        return EAI_NONAME;
-      return EAI_NONAME;
-    }
-
-    // Check for address family mismatch if one was specified.
-    if (hints.ai_family != AF_UNSPEC && hints.ai_family != hptr->h_addrtype)
-    {
-      freeaddrinfo_emulation(aihead);
-      gai_free(canon);
-      socket_ops::freehostent(hptr);
-      return EAI_FAMILY;
-    }
-
-    // Save canonical name first time.
-    if (host != 0 && host[0] != '\0' && hptr->h_name && hptr->h_name[0]
-        && (hints.ai_flags & AI_CANONNAME) && canon == 0)
-    {
-      std::size_t canon_len = strlen(hptr->h_name) + 1;
-      canon = gai_alloc<char>(canon_len);
-      if (canon == 0)
-      {
-        freeaddrinfo_emulation(aihead);
-        socket_ops::freehostent(hptr);
-        return EAI_MEMORY;
-      }
-      gai_strcpy(canon, hptr->h_name, canon_len);
-    }
-
-    // Create an addrinfo structure for each returned address.
-    for (char** ap = hptr->h_addr_list; *ap; ++ap)
-    {
-      rc = gai_aistruct(&ainext, &hints, *ap, hptr->h_addrtype);
-      if (rc != 0)
-      {
-        freeaddrinfo_emulation(aihead);
-        gai_free(canon);
-        socket_ops::freehostent(hptr);
-        return EAI_FAMILY;
-      }
-    }
-
-    socket_ops::freehostent(hptr);
-  }
-
-  // Check if we found anything.
-  if (aihead == 0)
-  {
-    gai_free(canon);
-    return EAI_NONAME;
-  }
-
-  // Return canonical name in first entry.
-  if (host != 0 && host[0] != '\0' && (hints.ai_flags & AI_CANONNAME))
-  {
-    if (canon)
-    {
-      aihead->ai_canonname = canon;
-      canon = 0;
-    }
-    else
-    {
-      std::size_t canonname_len = strlen(search[0].host) + 1;
-      aihead->ai_canonname = gai_alloc<char>(canonname_len);
-      if (aihead->ai_canonname == 0)
-      {
-        freeaddrinfo_emulation(aihead);
-        return EAI_MEMORY;
-      }
-      gai_strcpy(aihead->ai_canonname, search[0].host, canonname_len);
-    }
-  }
-  gai_free(canon);
-
-  // Process the service name.
-  if (service != 0 && service[0] != '\0')
-  {
-    rc = gai_serv(aihead, &hints, service);
-    if (rc != 0)
-    {
-      freeaddrinfo_emulation(aihead);
-      return rc;
-    }
-  }
-
-  // Return result to caller.
-  *result = aihead;
-  return 0;
-}
-
-inline asio::error_code getnameinfo_emulation(
-    const socket_addr_type* sa, std::size_t salen, char* host,
-    std::size_t hostlen, char* serv, std::size_t servlen, int flags,
-    asio::error_code& ec)
-{
-  using namespace std;
-
-  const char* addr;
-  size_t addr_len;
-  unsigned short port;
-  switch (sa->sa_family)
-  {
-  case AF_INET:
-    if (salen != sizeof(sockaddr_in4_type))
-    {
-      return ec = asio::error::invalid_argument;
-    }
-    addr = reinterpret_cast<const char*>(
-        &reinterpret_cast<const sockaddr_in4_type*>(sa)->sin_addr);
-    addr_len = sizeof(in4_addr_type);
-    port = reinterpret_cast<const sockaddr_in4_type*>(sa)->sin_port;
-    break;
-  case AF_INET6:
-    if (salen != sizeof(sockaddr_in6_type))
-    {
-      return ec = asio::error::invalid_argument;
-    }
-    addr = reinterpret_cast<const char*>(
-        &reinterpret_cast<const sockaddr_in6_type*>(sa)->sin6_addr);
-    addr_len = sizeof(in6_addr_type);
-    port = reinterpret_cast<const sockaddr_in6_type*>(sa)->sin6_port;
-    break;
-  default:
-    return ec = asio::error::address_family_not_supported;
-  }
-
-  if (host && hostlen > 0)
-  {
-    if (flags & NI_NUMERICHOST)
-    {
-      if (socket_ops::inet_ntop(sa->sa_family, addr, host, hostlen, 0, ec) == 0)
-      {
-        return ec;
-      }
-    }
-    else
-    {
-      hostent hent;
-      char hbuf[8192] = "";
-      hostent* hptr = socket_ops::gethostbyaddr(addr,
-          static_cast<int>(addr_len), sa->sa_family,
-          &hent, hbuf, sizeof(hbuf), ec);
-      if (hptr && hptr->h_name && hptr->h_name[0] != '\0')
-      {
-        if (flags & NI_NOFQDN)
-        {
-          char* dot = strchr(hptr->h_name, '.');
-          if (dot)
-          {
-            *dot = 0;
-          }
-        }
-        gai_strcpy(host, hptr->h_name, hostlen);
-        socket_ops::freehostent(hptr);
-      }
-      else
-      {
-        socket_ops::freehostent(hptr);
-        if (flags & NI_NAMEREQD)
-        {
-          return ec = asio::error::host_not_found;
-        }
-        if (socket_ops::inet_ntop(sa->sa_family,
-              addr, host, hostlen, 0, ec) == 0)
-        {
-          return ec;
-        }
-      }
-    }
-  }
-
-  if (serv && servlen > 0)
-  {
-    if (flags & NI_NUMERICSERV)
-    {
-      if (servlen < 6)
-      {
-        return ec = asio::error::no_buffer_space;
-      }
-#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) && !defined(UNDER_CE)
-      sprintf_s(serv, servlen, "%u", ntohs(port));
-#else
-      sprintf(serv, "%u", ntohs(port));
-#endif
-    }
-    else
-    {
-#if defined(BOOST_HAS_THREADS) && defined(BOOST_HAS_PTHREADS)
-      static ::pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
-      ::pthread_mutex_lock(&mutex);
-#endif // defined(BOOST_HAS_THREADS) && defined(BOOST_HAS_PTHREADS)
-      servent* sptr = ::getservbyport(port, (flags & NI_DGRAM) ? "udp" : 0);
-      if (sptr && sptr->s_name && sptr->s_name[0] != '\0')
-      {
-        gai_strcpy(serv, sptr->s_name, servlen);
-      }
-      else
-      {
-        if (servlen < 6)
-        {
-          return ec = asio::error::no_buffer_space;
-        }
-#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) && !defined(UNDER_CE)
-        sprintf_s(serv, servlen, "%u", ntohs(port));
-#else
-        sprintf(serv, "%u", ntohs(port));
-#endif
-      }
-#if defined(BOOST_HAS_THREADS) && defined(BOOST_HAS_PTHREADS)
-      ::pthread_mutex_unlock(&mutex);
-#endif // defined(BOOST_HAS_THREADS) && defined(BOOST_HAS_PTHREADS)
-    }
-  }
-
-  clear_error(ec);
-  return ec;
-}
+ASIO_DECL void freeaddrinfo(addrinfo_type* ai);
 
-#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-       //   || defined(__MACH__) && defined(__APPLE__)
+ASIO_DECL asio::error_code getnameinfo(
+    const socket_addr_type* addr, std::size_t addrlen,
+    char* host, std::size_t hostlen, char* serv,
+    std::size_t servlen, int flags, asio::error_code& ec);
 
-inline asio::error_code translate_addrinfo_error(int error)
-{
-  switch (error)
-  {
-  case 0:
-    return asio::error_code();
-  case EAI_AGAIN:
-    return asio::error::host_not_found_try_again;
-  case EAI_BADFLAGS:
-    return asio::error::invalid_argument;
-  case EAI_FAIL:
-    return asio::error::no_recovery;
-  case EAI_FAMILY:
-    return asio::error::address_family_not_supported;
-  case EAI_MEMORY:
-    return asio::error::no_memory;
-  case EAI_NONAME:
-#if defined(EAI_ADDRFAMILY)
-  case EAI_ADDRFAMILY:
-#endif
-#if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME)
-  case EAI_NODATA:
-#endif
-    return asio::error::host_not_found;
-  case EAI_SERVICE:
-    return asio::error::service_not_found;
-  case EAI_SOCKTYPE:
-    return asio::error::socket_type_not_supported;
-  default: // Possibly the non-portable EAI_SYSTEM.
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-    return asio::error_code(
-        WSAGetLastError(), asio::error::get_system_category());
-#else
-    return asio::error_code(
-        errno, asio::error::get_system_category());
-#endif
-  }
-}
-
-inline asio::error_code getaddrinfo(const char* host,
-    const char* service, const addrinfo_type* hints, addrinfo_type** result,
-    asio::error_code& ec)
-{
-  clear_error(ec);
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-# if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) || defined(UNDER_CE)
-  // Building for Windows XP, Windows Server 2003, or later.
-  int error = ::getaddrinfo(host, service, hints, result);
-  return ec = translate_addrinfo_error(error);
-# else
-  // Building for Windows 2000 or earlier.
-  typedef int (WSAAPI *gai_t)(const char*,
-      const char*, const addrinfo_type*, addrinfo_type**);
-  if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32"))
-  {
-    if (gai_t gai = (gai_t)::GetProcAddress(winsock_module, "getaddrinfo"))
-    {
-      int error = gai(host, service, hints, result);
-      return ec = translate_addrinfo_error(error);
-    }
-  }
-  int error = getaddrinfo_emulation(host, service, hints, result);
-  return ec = translate_addrinfo_error(error);
-# endif
-#elif defined(__MACH__) && defined(__APPLE__)
-  int error = getaddrinfo_emulation(host, service, hints, result);
-  return ec = translate_addrinfo_error(error);
-#else
-  int error = ::getaddrinfo(host, service, hints, result);
-  return ec = translate_addrinfo_error(error);
-#endif
-}
-
-inline void freeaddrinfo(addrinfo_type* ai)
-{
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-# if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) || defined(UNDER_CE)
-  // Building for Windows XP, Windows Server 2003, or later.
-  ::freeaddrinfo(ai);
-# else
-  // Building for Windows 2000 or earlier.
-  typedef int (WSAAPI *fai_t)(addrinfo_type*);
-  if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32"))
-  {
-    if (fai_t fai = (fai_t)::GetProcAddress(winsock_module, "freeaddrinfo"))
-    {
-      fai(ai);
-      return;
-    }
-  }
-  freeaddrinfo_emulation(ai);
-# endif
-#elif defined(__MACH__) && defined(__APPLE__)
-  freeaddrinfo_emulation(ai);
-#else
-  ::freeaddrinfo(ai);
-#endif
-}
-
-inline asio::error_code getnameinfo(const socket_addr_type* addr,
-    std::size_t addrlen, char* host, std::size_t hostlen,
-    char* serv, std::size_t servlen, int flags, asio::error_code& ec)
-{
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-# if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) || defined(UNDER_CE)
-  // Building for Windows XP, Windows Server 2003, or later.
-  clear_error(ec);
-  int error = ::getnameinfo(addr, static_cast<socklen_t>(addrlen),
-      host, static_cast<DWORD>(hostlen),
-      serv, static_cast<DWORD>(servlen), flags);
-  return ec = translate_addrinfo_error(error);
-# else
-  // Building for Windows 2000 or earlier.
-  typedef int (WSAAPI *gni_t)(const socket_addr_type*,
-      int, char*, DWORD, char*, DWORD, int);
-  if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32"))
-  {
-    if (gni_t gni = (gni_t)::GetProcAddress(winsock_module, "getnameinfo"))
-    {
-      clear_error(ec);
-      int error = gni(addr, static_cast<int>(addrlen),
-          host, static_cast<DWORD>(hostlen),
-          serv, static_cast<DWORD>(servlen), flags);
-      return ec = translate_addrinfo_error(error);
-    }
-  }
-  clear_error(ec);
-  return getnameinfo_emulation(addr, addrlen,
-      host, hostlen, serv, servlen, flags, ec);
-# endif
-#elif defined(__MACH__) && defined(__APPLE__)
-  using namespace std; // For memcpy.
-  sockaddr_storage_type tmp_addr;
-  memcpy(&tmp_addr, addr, addrlen);
-  tmp_addr.ss_len = addrlen;
-  addr = reinterpret_cast<socket_addr_type*>(&tmp_addr);
-  clear_error(ec);
-  return getnameinfo_emulation(addr, addrlen,
-      host, hostlen, serv, servlen, flags, ec);
-#else
-  clear_error(ec);
-  int error = ::getnameinfo(addr, addrlen, host, hostlen, serv, servlen, flags);
-  return ec = translate_addrinfo_error(error);
-#endif
-}
-
-inline u_long_type network_to_host_long(u_long_type value)
-{
-  return ntohl(value);
-}
+ASIO_DECL asio::error_code sync_getnameinfo(
+    const socket_addr_type* addr, std::size_t addrlen,
+    char* host, std::size_t hostlen, char* serv,
+    std::size_t servlen, int sock_type, asio::error_code& ec);
 
-inline u_long_type host_to_network_long(u_long_type value)
-{
-  return htonl(value);
-}
+ASIO_DECL asio::error_code background_getnameinfo(
+    const weak_cancel_token_type& cancel_token,
+    const socket_addr_type* addr, std::size_t addrlen,
+    char* host, std::size_t hostlen, char* serv,
+    std::size_t servlen, int sock_type, asio::error_code& ec);
 
-inline u_short_type network_to_host_short(u_short_type value)
-{
-  return ntohs(value);
-}
+ASIO_DECL u_long_type network_to_host_long(u_long_type value);
 
-inline u_short_type host_to_network_short(u_short_type value)
-{
-  return htons(value);
-}
+ASIO_DECL u_long_type host_to_network_long(u_long_type value);
+
+ASIO_DECL u_short_type network_to_host_short(u_short_type value);
+
+ASIO_DECL u_short_type host_to_network_short(u_short_type value);
 
 } // namespace socket_ops
 } // namespace detail
@@ -1909,4 +282,8 @@ inline u_short_type host_to_network_short(u_short_type value)
 
 #include "asio/detail/pop_options.hpp"
 
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/detail/impl/socket_ops.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
 #endif // ASIO_DETAIL_SOCKET_OPS_HPP
diff --git a/ext/asio/asio/detail/socket_option.hpp b/ext/asio/asio/detail/socket_option.hpp
index ac070b7..c9d7896 100644
--- a/ext/asio/asio/detail/socket_option.hpp
+++ b/ext/asio/asio/detail/socket_option.hpp
@@ -1,8 +1,8 @@
 //
-// socket_option.hpp
-// ~~~~~~~~~~~~~~~~~
+// detail/socket_option.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,17 +15,15 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 #include <cstddef>
 #include <stdexcept>
 #include <boost/config.hpp>
 #include <boost/throw_exception.hpp>
-#include "asio/detail/pop_options.hpp"
-
 #include "asio/detail/socket_types.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 namespace detail {
 namespace socket_option {
diff --git a/ext/asio/asio/detail/socket_select_interrupter.hpp b/ext/asio/asio/detail/socket_select_interrupter.hpp
index 62e1063..b05a4ff 100644
--- a/ext/asio/asio/detail/socket_select_interrupter.hpp
+++ b/ext/asio/asio/detail/socket_select_interrupter.hpp
@@ -1,8 +1,8 @@
 //
-// socket_select_interrupter.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// detail/socket_select_interrupter.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,19 +15,16 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 
-#include "asio/detail/push_options.hpp"
-#include <cstdlib>
-#include <boost/throw_exception.hpp>
-#include "asio/detail/pop_options.hpp"
+#if defined(BOOST_WINDOWS) \
+  || defined(__CYGWIN__) \
+  || defined(__SYMBIAN32__)
 
-#include "asio/error.hpp"
-#include "asio/system_error.hpp"
-#include "asio/detail/socket_holder.hpp"
-#include "asio/detail/socket_ops.hpp"
 #include "asio/detail/socket_types.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 namespace detail {
 
@@ -35,135 +32,16 @@ class socket_select_interrupter
 {
 public:
   // Constructor.
-  socket_select_interrupter()
-  {
-    asio::error_code ec;
-    socket_holder acceptor(socket_ops::socket(
-          AF_INET, SOCK_STREAM, IPPROTO_TCP, ec));
-    if (acceptor.get() == invalid_socket)
-    {
-      asio::system_error e(ec, "socket_select_interrupter");
-      boost::throw_exception(e);
-    }
-
-    int opt = 1;
-    socket_ops::setsockopt(acceptor.get(),
-        SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt), ec);
-
-    using namespace std; // For memset.
-    sockaddr_in4_type addr;
-    std::size_t addr_len = sizeof(addr);
-    memset(&addr, 0, sizeof(addr));
-    addr.sin_family = AF_INET;
-    addr.sin_addr.s_addr = inet_addr("127.0.0.1");
-    addr.sin_port = 0;
-    if (socket_ops::bind(acceptor.get(), (const socket_addr_type*)&addr,
-          addr_len, ec) == socket_error_retval)
-    {
-      asio::system_error e(ec, "socket_select_interrupter");
-      boost::throw_exception(e);
-    }
-
-    if (socket_ops::getsockname(acceptor.get(), (socket_addr_type*)&addr,
-          &addr_len, ec) == socket_error_retval)
-    {
-      asio::system_error e(ec, "socket_select_interrupter");
-      boost::throw_exception(e);
-    }
-
-    // Some broken firewalls on Windows will intermittently cause getsockname to
-    // return 0.0.0.0 when the socket is actually bound to 127.0.0.1. We
-    // explicitly specify the target address here to work around this problem.
-    addr.sin_addr.s_addr = inet_addr("127.0.0.1");
-
-    if (socket_ops::listen(acceptor.get(),
-          SOMAXCONN, ec) == socket_error_retval)
-    {
-      asio::system_error e(ec, "socket_select_interrupter");
-      boost::throw_exception(e);
-    }
-
-    socket_holder client(socket_ops::socket(
-          AF_INET, SOCK_STREAM, IPPROTO_TCP, ec));
-    if (client.get() == invalid_socket)
-    {
-      asio::system_error e(ec, "socket_select_interrupter");
-      boost::throw_exception(e);
-    }
-
-    if (socket_ops::connect(client.get(), (const socket_addr_type*)&addr,
-          addr_len, ec) == socket_error_retval)
-    {
-      asio::system_error e(ec, "socket_select_interrupter");
-      boost::throw_exception(e);
-    }
-
-    socket_holder server(socket_ops::accept(acceptor.get(), 0, 0, ec));
-    if (server.get() == invalid_socket)
-    {
-      asio::system_error e(ec, "socket_select_interrupter");
-      boost::throw_exception(e);
-    }
-    
-    ioctl_arg_type non_blocking = 1;
-    if (socket_ops::ioctl(client.get(), FIONBIO, &non_blocking, ec))
-    {
-      asio::system_error e(ec, "socket_select_interrupter");
-      boost::throw_exception(e);
-    }
-
-    opt = 1;
-    socket_ops::setsockopt(client.get(),
-        IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt), ec);
-
-    non_blocking = 1;
-    if (socket_ops::ioctl(server.get(), FIONBIO, &non_blocking, ec))
-    {
-      asio::system_error e(ec, "socket_select_interrupter");
-      boost::throw_exception(e);
-    }
-
-    opt = 1;
-    socket_ops::setsockopt(server.get(),
-        IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt), ec);
-
-    read_descriptor_ = server.release();
-    write_descriptor_ = client.release();
-  }
+  ASIO_DECL socket_select_interrupter();
 
   // Destructor.
-  ~socket_select_interrupter()
-  {
-    asio::error_code ec;
-    if (read_descriptor_ != invalid_socket)
-      socket_ops::close(read_descriptor_, ec);
-    if (write_descriptor_ != invalid_socket)
-      socket_ops::close(write_descriptor_, ec);
-  }
+  ASIO_DECL ~socket_select_interrupter();
 
   // Interrupt the select call.
-  void interrupt()
-  {
-    char byte = 0;
-    socket_ops::buf b;
-    socket_ops::init_buf(b, &byte, 1);
-    asio::error_code ec;
-    socket_ops::send(write_descriptor_, &b, 1, 0, ec);
-  }
+  ASIO_DECL void interrupt();
 
   // Reset the select interrupt. Returns true if the call was interrupted.
-  bool reset()
-  {
-    char data[1024];
-    socket_ops::buf b;
-    socket_ops::init_buf(b, data, sizeof(data));
-    asio::error_code ec;
-    int bytes_read = socket_ops::recv(read_descriptor_, &b, 1, 0, ec);
-    bool was_interrupted = (bytes_read > 0);
-    while (bytes_read == sizeof(data))
-      bytes_read = socket_ops::recv(read_descriptor_, &b, 1, 0, ec);
-    return was_interrupted;
-  }
+  ASIO_DECL bool reset();
 
   // Get the read descriptor to be passed to select.
   socket_type read_descriptor() const
@@ -189,4 +67,12 @@ private:
 
 #include "asio/detail/pop_options.hpp"
 
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/detail/impl/socket_select_interrupter.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
+#endif // defined(BOOST_WINDOWS)
+       // || defined(__CYGWIN__)
+       // || defined(__SYMBIAN32__)
+
 #endif // ASIO_DETAIL_SOCKET_SELECT_INTERRUPTER_HPP
diff --git a/ext/asio/asio/detail/socket_types.hpp b/ext/asio/asio/detail/socket_types.hpp
index 34b3d3e..4e29e51 100644
--- a/ext/asio/asio/detail/socket_types.hpp
+++ b/ext/asio/asio/detail/socket_types.hpp
@@ -1,8 +1,8 @@
 //
-// socket_types.hpp
-// ~~~~~~~~~~~~~~~~
+// detail/socket_types.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,69 +15,19 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
+#include "asio/detail/config.hpp"
 
-#include "asio/detail/push_options.hpp"
 #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
 # if defined(_WINSOCKAPI_) && !defined(_WINSOCK2API_)
 #  error WinSock.h has already been included
 # endif // defined(_WINSOCKAPI_) && !defined(_WINSOCK2API_)
-# if !defined(_WIN32_WINNT) && !defined(_WIN32_WINDOWS)
-#  if defined(_MSC_VER) || defined(__BORLANDC__)
-#   pragma message( \
-  "Please define _WIN32_WINNT or _WIN32_WINDOWS appropriately. For example:\n"\
-  "- add -D_WIN32_WINNT=0x0501 to the compiler command line; or\n"\
-  "- add _WIN32_WINNT=0x0501 to your project's Preprocessor Definitions.\n"\
-  "Assuming _WIN32_WINNT=0x0501 (i.e. Windows XP target).")
-#  else // defined(_MSC_VER) || defined(__BORLANDC__)
-#   warning Please define _WIN32_WINNT or _WIN32_WINDOWS appropriately.
-#   warning For example, add -D_WIN32_WINNT=0x0501 to the compiler command line.
-#   warning Assuming _WIN32_WINNT=0x0501 (i.e. Windows XP target).
-#  endif // defined(_MSC_VER) || defined(__BORLANDC__)
-#  define _WIN32_WINNT 0x0501
-# endif // !defined(_WIN32_WINNT) && !defined(_WIN32_WINDOWS)
-# if defined(_MSC_VER)
-#  if defined(_WIN32) && !defined(WIN32)
-#   if !defined(_WINSOCK2API_)
-#    define WIN32 // Needed for correct types in winsock2.h
-#   else // !defined(_WINSOCK2API_)
-#    error Please define the macro WIN32 in your compiler options
-#   endif // !defined(_WINSOCK2API_)
-#  endif // defined(_WIN32) && !defined(WIN32)
-# endif // defined(_MSC_VER)
 # if defined(__BORLANDC__)
 #  include <stdlib.h> // Needed for __errno
-#  if defined(__WIN32__) && !defined(WIN32)
-#   if !defined(_WINSOCK2API_)
-#    define WIN32 // Needed for correct types in winsock2.h
-#   else // !defined(_WINSOCK2API_)
-#    error Please define the macro WIN32 in your compiler options
-#   endif // !defined(_WINSOCK2API_)
-#  endif // defined(__WIN32__) && !defined(WIN32)
 #  if !defined(_WSPIAPI_H_)
 #   define _WSPIAPI_H_
 #   define ASIO_WSPIAPI_H_DEFINED
 #  endif // !defined(_WSPIAPI_H_)
 # endif // defined(__BORLANDC__)
-# if !defined(ASIO_NO_WIN32_LEAN_AND_MEAN)
-#  if !defined(WIN32_LEAN_AND_MEAN)
-#   define WIN32_LEAN_AND_MEAN
-#  endif // !defined(WIN32_LEAN_AND_MEAN)
-# endif // !defined(ASIO_NO_WIN32_LEAN_AND_MEAN)
-# if !defined(ASIO_NO_NOMINMAX)
-#  if !defined(NOMINMAX)
-#   define NOMINMAX 1
-#  endif // !defined(NOMINMAX)
-# endif // !defined(ASIO_NO_NOMINMAX)
-# if defined(__CYGWIN__)
-#  if !defined(__USE_W32_SOCKETS)
-#   error You must add -D__USE_W32_SOCKETS to your compiler options.
-#  endif // !defined(__USE_W32_SOCKETS)
-# endif // defined(__CYGWIN__)
 # include <winsock2.h>
 # include <ws2tcpip.h>
 # include <mswsock.h>
@@ -96,18 +46,25 @@
 # include "asio/detail/old_win_sdk_compat.hpp"
 #else
 # include <sys/ioctl.h>
-# include <sys/poll.h>
+# if !defined(__SYMBIAN32__)
+#  include <sys/poll.h>
+# endif
 # include <sys/types.h>
-# if defined(__hpux) && !defined(__HP_aCC)
+# include <sys/stat.h>
+# include <fcntl.h>
+# if defined(__hpux)
 #  include <sys/time.h>
-# else
+# endif
+# if !defined(__hpux) || defined(__SELECT)
 #  include <sys/select.h>
 # endif
 # include <sys/socket.h>
 # include <sys/uio.h>
 # include <sys/un.h>
 # include <netinet/in.h>
-# include <netinet/tcp.h>
+# if !defined(__SYMBIAN32__)
+#  include <netinet/tcp.h>
+# endif
 # include <arpa/inet.h>
 # include <netdb.h>
 # include <net/if.h>
@@ -117,7 +74,8 @@
 #  include <sys/sockio.h>
 # endif
 #endif
-#include "asio/detail/pop_options.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 namespace detail {
diff --git a/ext/asio/asio/detail/solaris_fenced_block.hpp b/ext/asio/asio/detail/solaris_fenced_block.hpp
index d337f3b..411c824 100644
--- a/ext/asio/asio/detail/solaris_fenced_block.hpp
+++ b/ext/asio/asio/detail/solaris_fenced_block.hpp
@@ -1,8 +1,8 @@
 //
-// solaris_fenced_block.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~
+// detail/solaris_fenced_block.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,17 +15,13 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
+#include "asio/detail/config.hpp"
 
 #if defined(__sun)
 
-#include "asio/detail/push_options.hpp"
 #include <atomic.h>
-#include "asio/detail/pop_options.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 namespace detail {
@@ -50,8 +46,8 @@ public:
 } // namespace detail
 } // namespace asio
 
-#endif // defined(__sun)
-
 #include "asio/detail/pop_options.hpp"
 
+#endif // defined(__sun)
+
 #endif // ASIO_DETAIL_SOLARIS_FENCED_BLOCK_HPP
diff --git a/ext/asio/asio/detail/strand_service.hpp b/ext/asio/asio/detail/strand_service.hpp
index ea50f41..4885b93 100644
--- a/ext/asio/asio/detail/strand_service.hpp
+++ b/ext/asio/asio/detail/strand_service.hpp
@@ -1,8 +1,8 @@
 //
-// strand_service.hpp
-// ~~~~~~~~~~~~~~~~~~
+// detail/strand_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,23 +15,14 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <boost/functional/hash.hpp>
+#include "asio/detail/config.hpp"
 #include <boost/scoped_ptr.hpp>
-#include "asio/detail/pop_options.hpp"
-
 #include "asio/io_service.hpp"
-#include "asio/detail/call_stack.hpp"
-#include "asio/detail/completion_handler.hpp"
-#include "asio/detail/fenced_block.hpp"
-#include "asio/detail/handler_alloc_helpers.hpp"
-#include "asio/detail/handler_invoke_helpers.hpp"
 #include "asio/detail/mutex.hpp"
 #include "asio/detail/op_queue.hpp"
 #include "asio/detail/operation.hpp"
-#include "asio/detail/service_base.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 namespace detail {
@@ -41,7 +32,10 @@ class strand_service
   : public asio::detail::service_base<strand_service>
 {
 private:
+  // Helper class to re-post the strand on exit.
   struct on_do_complete_exit;
+
+  // Helper class to re-post the strand on exit.
   struct on_dispatch_exit;
 
 public:
@@ -51,11 +45,7 @@ public:
     : public operation
   {
   public:
-    strand_impl()
-      : operation(&strand_service::do_complete),
-        count_(0)
-    {
-    }
+    strand_impl();
 
   private:
     // Only this service will have access to the internal values.
@@ -76,180 +66,29 @@ public:
   typedef strand_impl* implementation_type;
 
   // Construct a new strand service for the specified io_service.
-  explicit strand_service(asio::io_service& io_service)
-    : asio::detail::service_base<strand_service>(io_service),
-      io_service_(asio::use_service<io_service_impl>(io_service)),
-      mutex_(),
-      salt_(0)
-  {
-  }
+  ASIO_DECL explicit strand_service(asio::io_service& io_service);
 
   // Destroy all user-defined handler objects owned by the service.
-  void shutdown_service()
-  {
-    op_queue<operation> ops;
-
-    asio::detail::mutex::scoped_lock lock(mutex_);
-
-    for (std::size_t i = 0; i < num_implementations; ++i)
-      if (strand_impl* impl = implementations_[i].get())
-        ops.push(impl->queue_);
-  }
+  ASIO_DECL void shutdown_service();
 
   // Construct a new strand implementation.
-  void construct(implementation_type& impl)
-  {
-    std::size_t index = boost::hash_value(&impl);
-    boost::hash_combine(index, salt_++);
-    index = index % num_implementations;
-
-    asio::detail::mutex::scoped_lock lock(mutex_);
-
-    if (!implementations_[index])
-      implementations_[index].reset(new strand_impl);
-    impl = implementations_[index].get();
-  }
+  ASIO_DECL void construct(implementation_type& impl);
 
   // Destroy a strand implementation.
-  void destroy(implementation_type& impl)
-  {
-    impl = 0;
-  }
+  void destroy(implementation_type& impl);
 
   // Request the io_service to invoke the given handler.
   template <typename Handler>
-  void dispatch(implementation_type& impl, Handler handler)
-  {
-    // If we are already in the strand then the handler can run immediately.
-    if (call_stack<strand_impl>::contains(impl))
-    {
-      asio::detail::fenced_block b;
-      asio_handler_invoke_helpers::invoke(handler, handler);
-      return;
-    }
-
-    // Allocate and construct an object to wrap the handler.
-    typedef completion_handler<Handler> value_type;
-    typedef handler_alloc_traits<Handler, value_type> alloc_traits;
-    raw_handler_ptr<alloc_traits> raw_ptr(handler);
-    handler_ptr<alloc_traits> ptr(raw_ptr, handler);
-
-    // If we are running inside the io_service, and no other handler is queued
-    // or running, then the handler can run immediately.
-    bool can_dispatch = call_stack<io_service_impl>::contains(&io_service_);
-    impl->mutex_.lock();
-    bool first = (++impl->count_ == 1);
-    if (can_dispatch && first)
-    {
-      // Immediate invocation is allowed.
-      impl->mutex_.unlock();
-
-      // Memory must be releaesed before any upcall is made.
-      ptr.reset();
-
-      // Indicate that this strand is executing on the current thread.
-      call_stack<strand_impl>::context ctx(impl);
-
-      // Ensure the next handler, if any, is scheduled on block exit.
-      on_dispatch_exit on_exit = { &io_service_, impl };
-      (void)on_exit;
-
-      asio::detail::fenced_block b;
-      asio_handler_invoke_helpers::invoke(handler, handler);
-      return;
-    }
-
-    // Immediate invocation is not allowed, so enqueue for later.
-    impl->queue_.push(ptr.get());
-    impl->mutex_.unlock();
-    ptr.release();
-
-    // The first handler to be enqueued is responsible for scheduling the
-    // strand.
-    if (first)
-      io_service_.post_immediate_completion(impl);
-  }
+  void dispatch(implementation_type& impl, Handler handler);
 
   // Request the io_service to invoke the given handler and return immediately.
   template <typename Handler>
-  void post(implementation_type& impl, Handler handler)
-  {
-    // Allocate and construct an object to wrap the handler.
-    typedef completion_handler<Handler> value_type;
-    typedef handler_alloc_traits<Handler, value_type> alloc_traits;
-    raw_handler_ptr<alloc_traits> raw_ptr(handler);
-    handler_ptr<alloc_traits> ptr(raw_ptr, handler);
-
-    // Add the handler to the queue.
-    impl->mutex_.lock();
-    bool first = (++impl->count_ == 1);
-    impl->queue_.push(ptr.get());
-    impl->mutex_.unlock();
-    ptr.release();
-
-    // The first handler to be enqueue is responsible for scheduling the strand.
-    if (first)
-      io_service_.post_immediate_completion(impl);
-  }
+  void post(implementation_type& impl, Handler handler);
 
 private:
-  static void do_complete(io_service_impl* owner, operation* base,
-      asio::error_code /*ec*/, std::size_t /*bytes_transferred*/)
-  {
-    if (owner)
-    {
-      strand_impl* impl = static_cast<strand_impl*>(base);
-
-      // Get the next handler to be executed.
-      impl->mutex_.lock();
-      operation* o = impl->queue_.front();
-      impl->queue_.pop();
-      impl->mutex_.unlock();
-
-      // Indicate that this strand is executing on the current thread.
-      call_stack<strand_impl>::context ctx(impl);
-
-      // Ensure the next handler, if any, is scheduled on block exit.
-      on_do_complete_exit on_exit = { owner, impl };
-      (void)on_exit;
-
-      o->complete(*owner);
-    }
-  }
-
-  // Helper class to re-post the strand on exit.
-  struct on_do_complete_exit
-  {
-    io_service_impl* owner_;
-    strand_impl* impl_;
-
-    ~on_do_complete_exit()
-    {
-      impl_->mutex_.lock();
-      bool more_handlers = (--impl_->count_ > 0);
-      impl_->mutex_.unlock();
-
-      if (more_handlers)
-        owner_->post_immediate_completion(impl_);
-    }
-  };
-
-  // Helper class to re-post the strand on exit.
-  struct on_dispatch_exit
-  {
-    io_service_impl* io_service_;
-    strand_impl* impl_;
-
-    ~on_dispatch_exit()
-    {
-      impl_->mutex_.lock();
-      bool more_handlers = (--impl_->count_ > 0);
-      impl_->mutex_.unlock();
-
-      if (more_handlers)
-        io_service_->post_immediate_completion(impl_);
-    }
-  };
+  ASIO_DECL static void do_complete(io_service_impl* owner,
+      operation* base, asio::error_code ec,
+      std::size_t bytes_transferred);
 
   // The io_service implementation used to post completions.
   io_service_impl& io_service_;
@@ -273,4 +112,9 @@ private:
 
 #include "asio/detail/pop_options.hpp"
 
+#include "asio/detail/impl/strand_service.hpp"
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/detail/impl/strand_service.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
 #endif // ASIO_DETAIL_STRAND_SERVICE_HPP
diff --git a/ext/asio/asio/detail/task_io_service.hpp b/ext/asio/asio/detail/task_io_service.hpp
index eb77c1d..2d69513 100644
--- a/ext/asio/asio/detail/task_io_service.hpp
+++ b/ext/asio/asio/detail/task_io_service.hpp
@@ -1,8 +1,8 @@
 //
-// task_io_service.hpp
-// ~~~~~~~~~~~~~~~~~~~
+// detail/task_io_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,180 +15,59 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
+
+#if !defined(ASIO_HAS_IOCP)
 
+#include <boost/detail/atomic_count.hpp>
 #include "asio/error_code.hpp"
 #include "asio/io_service.hpp"
-#include "asio/detail/call_stack.hpp"
-#include "asio/detail/completion_handler.hpp"
-#include "asio/detail/event.hpp"
-#include "asio/detail/fenced_block.hpp"
-#include "asio/detail/handler_alloc_helpers.hpp"
-#include "asio/detail/handler_invoke_helpers.hpp"
 #include "asio/detail/mutex.hpp"
 #include "asio/detail/op_queue.hpp"
-#include "asio/detail/service_base.hpp"
+#include "asio/detail/reactor_fwd.hpp"
 #include "asio/detail/task_io_service_fwd.hpp"
 #include "asio/detail/task_io_service_operation.hpp"
 
 #include "asio/detail/push_options.hpp"
-#include <boost/detail/atomic_count.hpp>
-#include "asio/detail/pop_options.hpp"
 
 namespace asio {
 namespace detail {
 
-template <typename Task>
 class task_io_service
-  : public asio::detail::service_base<task_io_service<Task> >
+  : public asio::detail::service_base<task_io_service>
 {
 public:
-  typedef task_io_service_operation<Task> operation;
+  typedef task_io_service_operation operation;
 
   // Constructor.
-  task_io_service(asio::io_service& io_service)
-    : asio::detail::service_base<task_io_service<Task> >(io_service),
-      mutex_(),
-      task_(0),
-      task_interrupted_(true),
-      outstanding_work_(0),
-      stopped_(false),
-      shutdown_(false),
-      first_idle_thread_(0)
-  {
-  }
+  ASIO_DECL task_io_service(asio::io_service& io_service);
 
-  void init(size_t /*concurrency_hint*/)
-  {
-  }
+  // How many concurrent threads are likely to run the io_service.
+  ASIO_DECL void init(std::size_t concurrency_hint);
 
   // Destroy all user-defined handler objects owned by the service.
-  void shutdown_service()
-  {
-    asio::detail::mutex::scoped_lock lock(mutex_);
-    shutdown_ = true;
-    lock.unlock();
-
-    // Destroy handler objects.
-    while (!op_queue_.empty())
-    {
-      operation* o = op_queue_.front();
-      op_queue_.pop();
-      if (o != &task_operation_)
-        o->destroy();
-    }
-
-    // Reset to initial state.
-    task_ = 0;
-  }
+  ASIO_DECL void shutdown_service();
 
   // Initialise the task, if required.
-  void init_task()
-  {
-    asio::detail::mutex::scoped_lock lock(mutex_);
-    if (!shutdown_ && !task_)
-    {
-      task_ = &use_service<Task>(this->get_io_service());
-      op_queue_.push(&task_operation_);
-      wake_one_thread_and_unlock(lock);
-    }
-  }
+  ASIO_DECL void init_task();
 
   // Run the event loop until interrupted or no more work.
-  size_t run(asio::error_code& ec)
-  {
-    ec = asio::error_code();
-    if (outstanding_work_ == 0)
-    {
-      stop();
-      return 0;
-    }
-
-    typename call_stack<task_io_service>::context ctx(this);
-
-    idle_thread_info this_idle_thread;
-    this_idle_thread.next = 0;
-
-    asio::detail::mutex::scoped_lock lock(mutex_);
-
-    size_t n = 0;
-    for (; do_one(lock, &this_idle_thread); lock.lock())
-      if (n != (std::numeric_limits<size_t>::max)())
-        ++n;
-    return n;
-  }
+  ASIO_DECL std::size_t run(asio::error_code& ec);
 
   // Run until interrupted or one operation is performed.
-  size_t run_one(asio::error_code& ec)
-  {
-    ec = asio::error_code();
-    if (outstanding_work_ == 0)
-    {
-      stop();
-      return 0;
-    }
-
-    typename call_stack<task_io_service>::context ctx(this);
-
-    idle_thread_info this_idle_thread;
-    this_idle_thread.next = 0;
-
-    asio::detail::mutex::scoped_lock lock(mutex_);
-
-    return do_one(lock, &this_idle_thread);
-  }
+  ASIO_DECL std::size_t run_one(asio::error_code& ec);
 
   // Poll for operations without blocking.
-  size_t poll(asio::error_code& ec)
-  {
-    if (outstanding_work_ == 0)
-    {
-      stop();
-      ec = asio::error_code();
-      return 0;
-    }
-
-    typename call_stack<task_io_service>::context ctx(this);
-
-    asio::detail::mutex::scoped_lock lock(mutex_);
-
-    size_t n = 0;
-    for (; do_one(lock, 0); lock.lock())
-      if (n != (std::numeric_limits<size_t>::max)())
-        ++n;
-    return n;
-  }
+  ASIO_DECL std::size_t poll(asio::error_code& ec);
 
   // Poll for one operation without blocking.
-  size_t poll_one(asio::error_code& ec)
-  {
-    ec = asio::error_code();
-    if (outstanding_work_ == 0)
-    {
-      stop();
-      return 0;
-    }
-
-    typename call_stack<task_io_service>::context ctx(this);
-
-    asio::detail::mutex::scoped_lock lock(mutex_);
-
-    return do_one(lock, 0);
-  }
+  ASIO_DECL std::size_t poll_one(asio::error_code& ec);
 
   // Interrupt the event processing loop.
-  void stop()
-  {
-    asio::detail::mutex::scoped_lock lock(mutex_);
-    stop_all_threads(lock);
-  }
+  ASIO_DECL void stop();
 
   // Reset in preparation for a subsequent run invocation.
-  void reset()
-  {
-    asio::detail::mutex::scoped_lock lock(mutex_);
-    stopped_ = false;
-  }
+  ASIO_DECL void reset();
 
   // Notify that some work has started.
   void work_started()
@@ -205,228 +84,60 @@ public:
 
   // Request invocation of the given handler.
   template <typename Handler>
-  void dispatch(Handler handler)
-  {
-    if (call_stack<task_io_service>::contains(this))
-    {
-      asio::detail::fenced_block b;
-      asio_handler_invoke_helpers::invoke(handler, handler);
-    }
-    else
-      post(handler);
-  }
+  void dispatch(Handler handler);
 
   // Request invocation of the given handler and return immediately.
   template <typename Handler>
-  void post(Handler handler)
-  {
-    // Allocate and construct an operation to wrap the handler.
-    typedef completion_handler<Handler> value_type;
-    typedef handler_alloc_traits<Handler, value_type> alloc_traits;
-    raw_handler_ptr<alloc_traits> raw_ptr(handler);
-    handler_ptr<alloc_traits> ptr(raw_ptr, handler);
-
-    post_immediate_completion(ptr.get());
-    ptr.release();
-  }
+  void post(Handler handler);
 
   // Request invocation of the given operation and return immediately. Assumes
   // that work_started() has not yet been called for the operation.
-  void post_immediate_completion(operation* op)
-  {
-    work_started();
-    post_deferred_completion(op);
-  }
+  ASIO_DECL void post_immediate_completion(operation* op);
 
   // Request invocation of the given operation and return immediately. Assumes
   // that work_started() was previously called for the operation.
-  void post_deferred_completion(operation* op)
-  {
-    asio::detail::mutex::scoped_lock lock(mutex_);
-    op_queue_.push(op);
-    wake_one_thread_and_unlock(lock);
-  }
+  ASIO_DECL void post_deferred_completion(operation* op);
 
   // Request invocation of the given operations and return immediately. Assumes
   // that work_started() was previously called for each operation.
-  void post_deferred_completions(op_queue<operation>& ops)
-  {
-    if (!ops.empty())
-    {
-      asio::detail::mutex::scoped_lock lock(mutex_);
-      op_queue_.push(ops);
-      wake_one_thread_and_unlock(lock);
-    }
-  }
+  ASIO_DECL void post_deferred_completions(op_queue<operation>& ops);
 
 private:
+  // Structure containing information about an idle thread.
   struct idle_thread_info;
 
-  size_t do_one(asio::detail::mutex::scoped_lock& lock,
-      idle_thread_info* this_idle_thread)
-  {
-    bool polling = !this_idle_thread;
-    bool task_has_run = false;
-    while (!stopped_)
-    {
-      if (!op_queue_.empty())
-      {
-        // Prepare to execute first handler from queue.
-        operation* o = op_queue_.front();
-        op_queue_.pop();
-        bool more_handlers = (!op_queue_.empty());
-
-        if (o == &task_operation_)
-        {
-          task_interrupted_ = more_handlers || polling;
-
-          // If the task has already run and we're polling then we're done.
-          if (task_has_run && polling)
-          {
-            task_interrupted_ = true;
-            op_queue_.push(&task_operation_);
-            return 0;
-          }
-          task_has_run = true;
-
-          if (!more_handlers || !wake_one_idle_thread_and_unlock(lock))
-            lock.unlock();
-
-          op_queue<operation> completed_ops;
-          task_cleanup c = { this, &lock, &completed_ops };
-          (void)c;
-
-          // Run the task. May throw an exception. Only block if the operation
-          // queue is empty and we're not polling, otherwise we want to return
-          // as soon as possible.
-          task_->run(!more_handlers && !polling, completed_ops);
-        }
-        else
-        {
-          if (more_handlers)
-            wake_one_thread_and_unlock(lock);
-          else
-            lock.unlock();
-
-          // Ensure the count of outstanding work is decremented on block exit.
-          work_finished_on_block_exit on_exit = { this };
-          (void)on_exit;
-
-          // Complete the operation. May throw an exception.
-          o->complete(*this); // deletes the operation object
-
-          return 1;
-        }
-      }
-      else if (this_idle_thread)
-      {
-        // Nothing to run right now, so just wait for work to do.
-        this_idle_thread->next = first_idle_thread_;
-        first_idle_thread_ = this_idle_thread;
-        this_idle_thread->wakeup_event.clear(lock);
-        this_idle_thread->wakeup_event.wait(lock);
-      }
-      else
-      {
-        return 0;
-      }
-    }
-
-    return 0;
-  }
+  // Run at most one operation. Blocks only if this_idle_thread is non-null.
+  ASIO_DECL std::size_t do_one(mutex::scoped_lock& lock,
+      idle_thread_info* this_idle_thread);
 
   // Stop the task and all idle threads.
-  void stop_all_threads(
-      asio::detail::mutex::scoped_lock& lock)
-  {
-    stopped_ = true;
-
-    while (first_idle_thread_)
-    {
-      idle_thread_info* idle_thread = first_idle_thread_;
-      first_idle_thread_ = idle_thread->next;
-      idle_thread->next = 0;
-      idle_thread->wakeup_event.signal(lock);
-    }
-
-    if (!task_interrupted_ && task_)
-    {
-      task_interrupted_ = true;
-      task_->interrupt();
-    }
-  }
+  ASIO_DECL void stop_all_threads(mutex::scoped_lock& lock);
 
   // Wakes a single idle thread and unlocks the mutex. Returns true if an idle
   // thread was found. If there is no idle thread, returns false and leaves the
   // mutex locked.
-  bool wake_one_idle_thread_and_unlock(
-      asio::detail::mutex::scoped_lock& lock)
-  {
-    if (first_idle_thread_)
-    {
-      idle_thread_info* idle_thread = first_idle_thread_;
-      first_idle_thread_ = idle_thread->next;
-      idle_thread->next = 0;
-      idle_thread->wakeup_event.signal_and_unlock(lock);
-      return true;
-    }
-    return false;
-  }
+  ASIO_DECL bool wake_one_idle_thread_and_unlock(
+      mutex::scoped_lock& lock);
 
   // Wake a single idle thread, or the task, and always unlock the mutex.
-  void wake_one_thread_and_unlock(
-      asio::detail::mutex::scoped_lock& lock)
-  {
-    if (!wake_one_idle_thread_and_unlock(lock))
-    {
-      if (!task_interrupted_ && task_)
-      {
-        task_interrupted_ = true;
-        task_->interrupt();
-      }
-      lock.unlock();
-    }
-  }
+  ASIO_DECL void wake_one_thread_and_unlock(
+      mutex::scoped_lock& lock);
 
   // Helper class to perform task-related operations on block exit.
   struct task_cleanup;
   friend struct task_cleanup;
-  struct task_cleanup
-  {
-    ~task_cleanup()
-    {
-      // Enqueue the completed operations and reinsert the task at the end of
-      // the operation queue.
-      lock_->lock();
-      task_io_service_->task_interrupted_ = true;
-      task_io_service_->op_queue_.push(*ops_);
-      task_io_service_->op_queue_.push(&task_io_service_->task_operation_);
-    }
-
-    task_io_service* task_io_service_;
-    asio::detail::mutex::scoped_lock* lock_;
-    op_queue<operation>* ops_;
-  };
 
   // Helper class to call work_finished() on block exit.
-  struct work_finished_on_block_exit
-  {
-    ~work_finished_on_block_exit()
-    {
-      task_io_service_->work_finished();
-    }
-
-    task_io_service* task_io_service_;
-  };
+  struct work_finished_on_block_exit;
 
   // Mutex to protect access to internal data.
-  asio::detail::mutex mutex_;
+  mutex mutex_;
 
   // The task to be run by this service.
-  Task* task_;
+  reactor* task_;
 
   // Operation object to represent the position of the task in the queue.
-  struct task_operation : public operation
+  struct task_operation : operation
   {
     task_operation() : operation(0) {}
   } task_operation_;
@@ -446,13 +157,6 @@ private:
   // Flag to indicate that the dispatcher has been shut down.
   bool shutdown_;
 
-  // Structure containing information about an idle thread.
-  struct idle_thread_info
-  {
-    event wakeup_event;
-    idle_thread_info* next;
-  };
-
   // The threads that are currently idle.
   idle_thread_info* first_idle_thread_;
 };
@@ -462,4 +166,11 @@ private:
 
 #include "asio/detail/pop_options.hpp"
 
+#include "asio/detail/impl/task_io_service.hpp"
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/detail/impl/task_io_service.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
+#endif // !defined(ASIO_HAS_IOCP)
+
 #endif // ASIO_DETAIL_TASK_IO_SERVICE_HPP
diff --git a/ext/asio/asio/detail/task_io_service_fwd.hpp b/ext/asio/asio/detail/task_io_service_fwd.hpp
index 5b18d1d..b66cb07 100644
--- a/ext/asio/asio/detail/task_io_service_fwd.hpp
+++ b/ext/asio/asio/detail/task_io_service_fwd.hpp
@@ -1,8 +1,8 @@
 //
-// task_io_service_fwd.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~
+// detail/task_io_service_fwd.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,17 +15,12 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
 namespace asio {
 namespace detail {
 
-template <typename Task>
 class task_io_service;
 
 } // namespace detail
 } // namespace asio
 
-#include "asio/detail/pop_options.hpp"
-
 #endif // ASIO_DETAIL_TASK_IO_SERVICE_FWD_HPP
diff --git a/ext/asio/asio/detail/task_io_service_operation.hpp b/ext/asio/asio/detail/task_io_service_operation.hpp
index 6776f69..dd4384a 100644
--- a/ext/asio/asio/detail/task_io_service_operation.hpp
+++ b/ext/asio/asio/detail/task_io_service_operation.hpp
@@ -1,8 +1,8 @@
 //
-// task_io_service_operation.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// detail/task_io_service_operation.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,22 +15,21 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
 #include "asio/error_code.hpp"
 #include "asio/detail/op_queue.hpp"
 #include "asio/detail/task_io_service_fwd.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 namespace detail {
 
 // Base class for all operations. A function pointer is used instead of virtual
 // functions to avoid the associated overhead.
-template <typename Task>
 class task_io_service_operation
 {
 public:
-  void complete(task_io_service<Task>& owner)
+  void complete(task_io_service& owner)
   {
     func_(&owner, this, asio::error_code(), 0);
   }
@@ -41,8 +40,9 @@ public:
   }
 
 protected:
-  typedef void (*func_type)(task_io_service<Task>*,
-      task_io_service_operation*, asio::error_code, std::size_t);
+  typedef void (*func_type)(task_io_service*,
+      task_io_service_operation*,
+      asio::error_code, std::size_t);
 
   task_io_service_operation(func_type func)
     : next_(0),
diff --git a/ext/asio/asio/detail/thread.hpp b/ext/asio/asio/detail/thread.hpp
index 3c9280b..7c4103b 100644
--- a/ext/asio/asio/detail/thread.hpp
+++ b/ext/asio/asio/detail/thread.hpp
@@ -1,8 +1,8 @@
 //
-// thread.hpp
-// ~~~~~~~~~~
+// detail/thread.hpp
+// ~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,11 +15,7 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
+#include "asio/detail/config.hpp"
 
 #if !defined(BOOST_HAS_THREADS) || defined(ASIO_DISABLE_THREADS)
 # include "asio/detail/null_thread.hpp"
@@ -53,6 +49,4 @@ typedef posix_thread thread;
 } // namespace detail
 } // namespace asio
 
-#include "asio/detail/pop_options.hpp"
-
 #endif // ASIO_DETAIL_THREAD_HPP
diff --git a/ext/asio/asio/detail/throw_error.hpp b/ext/asio/asio/detail/throw_error.hpp
index 51d6e48..d39aa92 100644
--- a/ext/asio/asio/detail/throw_error.hpp
+++ b/ext/asio/asio/detail/throw_error.hpp
@@ -1,8 +1,8 @@
 //
-// throw_error.hpp
-// ~~~~~~~~~~~~~~~
+// detail/throw_error.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,25 +15,30 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
+#include "asio/error_code.hpp"
 
 #include "asio/detail/push_options.hpp"
-#include <boost/throw_exception.hpp>
-#include "asio/detail/pop_options.hpp"
-
-#include "asio/error_code.hpp"
-#include "asio/system_error.hpp"
 
 namespace asio {
 namespace detail {
 
+ASIO_DECL void do_throw_error(const asio::error_code& err);
+
+ASIO_DECL void do_throw_error(const asio::error_code& err,
+    const char* location);
+
 inline void throw_error(const asio::error_code& err)
 {
   if (err)
-  {
-    asio::system_error e(err);
-    boost::throw_exception(e);
-  }
+    do_throw_error(err);
+}
+
+inline void throw_error(const asio::error_code& err,
+    const char* location)
+{
+  if (err)
+    do_throw_error(err, location);
 }
 
 } // namespace detail
@@ -41,4 +46,8 @@ inline void throw_error(const asio::error_code& err)
 
 #include "asio/detail/pop_options.hpp"
 
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/detail/impl/throw_error.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
 #endif // ASIO_DETAIL_THROW_ERROR_HPP
diff --git a/ext/asio/asio/detail/timer_op.hpp b/ext/asio/asio/detail/timer_op.hpp
index bf3c3ae..62cd292 100644
--- a/ext/asio/asio/detail/timer_op.hpp
+++ b/ext/asio/asio/detail/timer_op.hpp
@@ -1,8 +1,8 @@
 //
-// timer_op.hpp
-// ~~~~~~~~~~~~
+// detail/timer_op.hpp
+// ~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,10 +15,11 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
+#include "asio/detail/config.hpp"
 #include "asio/detail/operation.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 namespace detail {
 
diff --git a/ext/asio/asio/detail/timer_queue.hpp b/ext/asio/asio/detail/timer_queue.hpp
index 2e4d2d5..514c434 100644
--- a/ext/asio/asio/detail/timer_queue.hpp
+++ b/ext/asio/asio/detail/timer_queue.hpp
@@ -1,8 +1,8 @@
 //
-// timer_queue.hpp
-// ~~~~~~~~~~~~~~~
+// detail/timer_queue.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,21 +15,22 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 #include <cstddef>
-#include <memory>
 #include <vector>
 #include <boost/config.hpp>
 #include <boost/limits.hpp>
-#include "asio/detail/pop_options.hpp"
-
-#include "asio/error.hpp"
-#include "asio/detail/hash_map.hpp"
 #include "asio/detail/op_queue.hpp"
 #include "asio/detail/timer_op.hpp"
 #include "asio/detail/timer_queue_base.hpp"
+#include "asio/error.hpp"
+#include "asio/time_traits.hpp"
+
+#include "asio/detail/push_options.hpp"
+#include <boost/date_time/posix_time/posix_time_types.hpp>
+#include "asio/detail/pop_options.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 namespace detail {
@@ -45,6 +46,26 @@ public:
   // The duration type.
   typedef typename Time_Traits::duration_type duration_type;
 
+  // Per-timer data.
+  class per_timer_data
+  {
+  public:
+    per_timer_data() : next_(0), prev_(0) {}
+
+  private:
+    friend class timer_queue;
+
+    // The operations waiting on the timer.
+    op_queue<timer_op> op_queue_;
+
+    // The index of the timer in the heap.
+    std::size_t heap_index_;
+
+    // Pointers to adjacent timers in a linked list.
+    per_timer_data* next_;
+    per_timer_data* prev_;
+  };
+
   // Constructor.
   timer_queue()
     : timers_(),
@@ -55,35 +76,45 @@ public:
   // Add a new timer to the queue. Returns true if this is the timer that is
   // earliest in the queue, in which case the reactor's event demultiplexing
   // function call may need to be interrupted and restarted.
-  bool enqueue_timer(const time_type& time, timer_op* op, void* token)
+  bool enqueue_timer(const time_type& time, per_timer_data& timer, timer_op* op)
   {
-    // Ensure that there is space for the timer in the heap. We reserve here so
-    // that the push_back below will not throw due to a reallocation failure.
-    heap_.reserve(heap_.size() + 1);
-
-    // Insert the new timer into the hash.
-    typedef typename hash_map<void*, timer>::iterator iterator;
-    typedef typename hash_map<void*, timer>::value_type value_type;
-    std::pair<iterator, bool> result =
-      timers_.insert(value_type(token, timer()));
-    result.first->second.op_queue_.push(op);
-    if (result.second)
+    // Enqueue the timer object.
+    if (timer.prev_ == 0 && &timer != timers_)
     {
-      // Put the new timer at the correct position in the heap.
-      result.first->second.time_ = time;
-      result.first->second.heap_index_ = heap_.size();
-      result.first->second.token_ = token;
-      heap_.push_back(&result.first->second);
-      up_heap(heap_.size() - 1);
+      if (this->is_positive_infinity(time))
+      {
+        // No heap entry is required for timers that never expire.
+        timer.heap_index_ = (std::numeric_limits<std::size_t>::max)();
+      }
+      else
+      {
+        // Put the new timer at the correct position in the heap. This is done
+        // first since push_back() can throw due to allocation failure.
+        timer.heap_index_ = heap_.size();
+        heap_entry entry = { time, &timer };
+        heap_.push_back(entry);
+        up_heap(heap_.size() - 1);
+      }
+
+      // Insert the new timer into the linked list of active timers.
+      timer.next_ = timers_;
+      timer.prev_ = 0;
+      if (timers_)
+        timers_->prev_ = &timer;
+      timers_ = &timer;
     }
 
-    return (heap_[0] == &result.first->second);
+    // Enqueue the individual timer operation.
+    timer.op_queue_.push(op);
+
+    // Interrupt reactor only if newly added timer is first to expire.
+    return timer.heap_index_ == 0 && timer.op_queue_.front() == op;
   }
 
   // Whether there are no timers in the queue.
   virtual bool empty() const
   {
-    return heap_.empty();
+    return timers_ == 0;
   }
 
   // Get the time for the timer that is earliest in the queue.
@@ -93,12 +124,14 @@ public:
       return max_duration;
 
     boost::posix_time::time_duration duration = Time_Traits::to_posix_duration(
-        Time_Traits::subtract(heap_[0]->time_, Time_Traits::now()));
+        Time_Traits::subtract(heap_[0].time_, Time_Traits::now()));
 
     if (duration > boost::posix_time::milliseconds(max_duration))
       duration = boost::posix_time::milliseconds(max_duration);
-    else if (duration < boost::posix_time::milliseconds(0))
+    else if (duration <= boost::posix_time::milliseconds(0))
       duration = boost::posix_time::milliseconds(0);
+    else if (duration < boost::posix_time::milliseconds(1))
+      duration = boost::posix_time::milliseconds(1);
 
     return duration.total_milliseconds();
   }
@@ -110,12 +143,14 @@ public:
       return max_duration;
 
     boost::posix_time::time_duration duration = Time_Traits::to_posix_duration(
-        Time_Traits::subtract(heap_[0]->time_, Time_Traits::now()));
+        Time_Traits::subtract(heap_[0].time_, Time_Traits::now()));
 
     if (duration > boost::posix_time::microseconds(max_duration))
       duration = boost::posix_time::microseconds(max_duration);
-    else if (duration < boost::posix_time::microseconds(0))
+    else if (duration <= boost::posix_time::microseconds(0))
       duration = boost::posix_time::microseconds(0);
+    else if (duration < boost::posix_time::microseconds(1))
+      duration = boost::posix_time::microseconds(1);
 
     return duration.total_microseconds();
   }
@@ -124,77 +159,54 @@ public:
   virtual void get_ready_timers(op_queue<operation>& ops)
   {
     const time_type now = Time_Traits::now();
-    while (!heap_.empty() && !Time_Traits::less_than(now, heap_[0]->time_))
+    while (!heap_.empty() && !Time_Traits::less_than(now, heap_[0].time_))
     {
-      timer* t = heap_[0];
-      ops.push(t->op_queue_);
-      remove_timer(t);
+      per_timer_data* timer = heap_[0].timer_;
+      ops.push(timer->op_queue_);
+      remove_timer(*timer);
     }
   }
 
   // Dequeue all timers.
   virtual void get_all_timers(op_queue<operation>& ops)
   {
-    typename hash_map<void*, timer>::iterator i = timers_.begin();
-    typename hash_map<void*, timer>::iterator end = timers_.end();
-    while (i != end)
+    while (timers_)
     {
-      ops.push(i->second.op_queue_);
-      typename hash_map<void*, timer>::iterator old_i = i++;
-      timers_.erase(old_i);
+      per_timer_data* timer = timers_;
+      timers_ = timers_->next_;
+      ops.push(timer->op_queue_);
+      timer->next_ = 0;
+      timer->prev_ = 0;
     }
 
     heap_.clear();
-    timers_.clear();
   }
 
   // Cancel and dequeue the timers with the given token.
-  std::size_t cancel_timer(void* timer_token, op_queue<operation>& ops)
+  std::size_t cancel_timer(per_timer_data& timer, op_queue<operation>& ops)
   {
     std::size_t num_cancelled = 0;
-    typedef typename hash_map<void*, timer>::iterator iterator;
-    iterator it = timers_.find(timer_token);
-    if (it != timers_.end())
+    if (timer.prev_ != 0 || &timer == timers_)
     {
-      while (timer_op* op = it->second.op_queue_.front())
+      while (timer_op* op = timer.op_queue_.front())
       {
         op->ec_ = asio::error::operation_aborted;
-        it->second.op_queue_.pop();
+        timer.op_queue_.pop();
         ops.push(op);
         ++num_cancelled;
       }
-      remove_timer(&it->second);
+      remove_timer(timer);
     }
     return num_cancelled;
   }
 
 private:
-  // Structure representing a single outstanding timer.
-  struct timer
-  {
-    timer() {}
-    timer(const timer&) {}
-    void operator=(const timer&) {}
-
-    // The time when the timer should fire.
-    time_type time_;
-
-    // The operations waiting on the timer.
-    op_queue<timer_op> op_queue_;
-
-    // The index of the timer in the heap.
-    size_t heap_index_;
-
-    // The token associated with the timer.
-    void* token_;
-  };
-
   // Move the item at the given index up the heap to its correct position.
-  void up_heap(size_t index)
+  void up_heap(std::size_t index)
   {
-    size_t parent = (index - 1) / 2;
+    std::size_t parent = (index - 1) / 2;
     while (index > 0
-        && Time_Traits::less_than(heap_[index]->time_, heap_[parent]->time_))
+        && Time_Traits::less_than(heap_[index].time_, heap_[parent].time_))
     {
       swap_heap(index, parent);
       index = parent;
@@ -203,16 +215,16 @@ private:
   }
 
   // Move the item at the given index down the heap to its correct position.
-  void down_heap(size_t index)
+  void down_heap(std::size_t index)
   {
-    size_t child = index * 2 + 1;
+    std::size_t child = index * 2 + 1;
     while (child < heap_.size())
     {
-      size_t min_child = (child + 1 == heap_.size()
+      std::size_t min_child = (child + 1 == heap_.size()
           || Time_Traits::less_than(
-            heap_[child]->time_, heap_[child + 1]->time_))
+            heap_[child].time_, heap_[child + 1].time_))
         ? child : child + 1;
-      if (Time_Traits::less_than(heap_[index]->time_, heap_[min_child]->time_))
+      if (Time_Traits::less_than(heap_[index].time_, heap_[min_child].time_))
         break;
       swap_heap(index, min_child);
       index = min_child;
@@ -221,20 +233,20 @@ private:
   }
 
   // Swap two entries in the heap.
-  void swap_heap(size_t index1, size_t index2)
+  void swap_heap(std::size_t index1, std::size_t index2)
   {
-    timer* tmp = heap_[index1];
+    heap_entry tmp = heap_[index1];
     heap_[index1] = heap_[index2];
     heap_[index2] = tmp;
-    heap_[index1]->heap_index_ = index1;
-    heap_[index2]->heap_index_ = index2;
+    heap_[index1].timer_->heap_index_ = index1;
+    heap_[index2].timer_->heap_index_ = index2;
   }
 
   // Remove a timer from the heap and list of timers.
-  void remove_timer(timer* t)
+  void remove_timer(per_timer_data& timer)
   {
     // Remove the timer from the heap.
-    size_t index = t->heap_index_;
+    std::size_t index = timer.heap_index_;
     if (!heap_.empty() && index < heap_.size())
     {
       if (index == heap_.size() - 1)
@@ -245,29 +257,112 @@ private:
       {
         swap_heap(index, heap_.size() - 1);
         heap_.pop_back();
-        size_t parent = (index - 1) / 2;
+        std::size_t parent = (index - 1) / 2;
         if (index > 0 && Time_Traits::less_than(
-              heap_[index]->time_, heap_[parent]->time_))
+              heap_[index].time_, heap_[parent].time_))
           up_heap(index);
         else
           down_heap(index);
       }
     }
 
-    // Remove the timer from the hash.
-    typedef typename hash_map<void*, timer>::iterator iterator;
-    iterator it = timers_.find(t->token_);
-    if (it != timers_.end())
-      timers_.erase(it);
+    // Remove the timer from the linked list of active timers.
+    if (timers_ == &timer)
+      timers_ = timer.next_;
+    if (timer.prev_)
+      timer.prev_->next_ = timer.next_;
+    if (timer.next_)
+      timer.next_->prev_= timer.prev_;
+    timer.next_ = 0;
+    timer.prev_ = 0;
+  }
+
+  // Determine if the specified absolute time is positive infinity.
+  template <typename Time_Type>
+  static bool is_positive_infinity(const Time_Type&)
+  {
+    return false;
+  }
+
+  // Determine if the specified absolute time is positive infinity.
+  static bool is_positive_infinity(const boost::posix_time::ptime& time)
+  {
+    return time == boost::posix_time::pos_infin;
   }
 
-  // A hash of timer token to linked lists of timers.
-  hash_map<void*, timer> timers_;
+  // The head of a linked list of all active timers.
+  per_timer_data* timers_;
+
+  struct heap_entry
+  {
+    // The time when the timer should fire.
+    time_type time_;
+
+    // The associated timer with enqueued operations.
+    per_timer_data* timer_;
+  };
 
   // The heap of timers, with the earliest timer at the front.
-  std::vector<timer*> heap_;
+  std::vector<heap_entry> heap_;
 };
 
+#if !defined(ASIO_HEADER_ONLY)
+
+struct forwarding_posix_time_traits : time_traits<boost::posix_time::ptime> {};
+
+// Template specialisation for the commonly used instantation.
+template <>
+class timer_queue<time_traits<boost::posix_time::ptime> >
+  : public timer_queue_base
+{
+public:
+  // The time type.
+  typedef boost::posix_time::ptime time_type;
+
+  // The duration type.
+  typedef boost::posix_time::time_duration duration_type;
+
+  // Per-timer data.
+  typedef timer_queue<forwarding_posix_time_traits>::per_timer_data
+    per_timer_data;
+
+  // Constructor.
+  ASIO_DECL timer_queue();
+
+  // Destructor.
+  ASIO_DECL virtual ~timer_queue();
+
+  // Add a new timer to the queue. Returns true if this is the timer that is
+  // earliest in the queue, in which case the reactor's event demultiplexing
+  // function call may need to be interrupted and restarted.
+  ASIO_DECL bool enqueue_timer(const time_type& time,
+      per_timer_data& timer, timer_op* op);
+
+  // Whether there are no timers in the queue.
+  ASIO_DECL virtual bool empty() const;
+
+  // Get the time for the timer that is earliest in the queue.
+  ASIO_DECL virtual long wait_duration_msec(long max_duration) const;
+
+  // Get the time for the timer that is earliest in the queue.
+  ASIO_DECL virtual long wait_duration_usec(long max_duration) const;
+
+  // Dequeue all timers not later than the current time.
+  ASIO_DECL virtual void get_ready_timers(op_queue<operation>& ops);
+
+  // Dequeue all timers.
+  ASIO_DECL virtual void get_all_timers(op_queue<operation>& ops);
+
+  // Cancel and dequeue the timers with the given token.
+  ASIO_DECL std::size_t cancel_timer(
+      per_timer_data& timer, op_queue<operation>& ops);
+
+private:
+  timer_queue<forwarding_posix_time_traits> impl_;
+};
+
+#endif // !defined(ASIO_HEADER_ONLY)
+
 } // namespace detail
 } // namespace asio
 
diff --git a/ext/asio/asio/detail/timer_queue_base.hpp b/ext/asio/asio/detail/timer_queue_base.hpp
index f978667..0e8d4c7 100644
--- a/ext/asio/asio/detail/timer_queue_base.hpp
+++ b/ext/asio/asio/detail/timer_queue_base.hpp
@@ -1,8 +1,8 @@
 //
-// timer_queue_base.hpp
-// ~~~~~~~~~~~~~~~~~~~~
+// detail/timer_queue_base.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,12 +15,13 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
+#include "asio/detail/config.hpp"
 #include "asio/detail/noncopyable.hpp"
 #include "asio/detail/op_queue.hpp"
 #include "asio/detail/operation.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 namespace detail {
 
diff --git a/ext/asio/asio/detail/timer_queue_fwd.hpp b/ext/asio/asio/detail/timer_queue_fwd.hpp
index 5317244..0cca967 100644
--- a/ext/asio/asio/detail/timer_queue_fwd.hpp
+++ b/ext/asio/asio/detail/timer_queue_fwd.hpp
@@ -1,8 +1,8 @@
 //
-// timer_queue_fwd.hpp
-// ~~~~~~~~~~~~~~~~~~~
+// detail/timer_queue_fwd.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,8 +15,6 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
 namespace asio {
 namespace detail {
 
@@ -26,6 +24,4 @@ class timer_queue;
 } // namespace detail
 } // namespace asio
 
-#include "asio/detail/pop_options.hpp"
-
 #endif // ASIO_DETAIL_TIMER_QUEUE_FWD_HPP
diff --git a/ext/asio/asio/detail/timer_queue_set.hpp b/ext/asio/asio/detail/timer_queue_set.hpp
index 6860867..9e8d428 100644
--- a/ext/asio/asio/detail/timer_queue_set.hpp
+++ b/ext/asio/asio/detail/timer_queue_set.hpp
@@ -1,8 +1,8 @@
 //
-// timer_queue_set.hpp
-// ~~~~~~~~~~~~~~~~~~~
+// detail/timer_queue_set.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,10 +15,11 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
+#include "asio/detail/config.hpp"
 #include "asio/detail/timer_queue_base.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 namespace detail {
 
@@ -26,82 +27,28 @@ class timer_queue_set
 {
 public:
   // Constructor.
-  timer_queue_set()
-    : first_(0)
-  {
-  }
+  ASIO_DECL timer_queue_set();
 
   // Add a timer queue to the set.
-  void insert(timer_queue_base* q)
-  {
-    q->next_ = first_;
-    first_ = q;
-  }
+  ASIO_DECL void insert(timer_queue_base* q);
 
   // Remove a timer queue from the set.
-  void erase(timer_queue_base* q)
-  {
-    if (first_)
-    {
-      if (q == first_)
-      {
-        first_ = q->next_;
-        q->next_ = 0;
-        return;
-      }
-
-      for (timer_queue_base* p = first_; p->next_; p = p->next_)
-      {
-        if (p->next_ == q)
-        {
-          p->next_ = q->next_;
-          q->next_ = 0;
-          return;
-        }
-      }
-    }
-  }
+  ASIO_DECL void erase(timer_queue_base* q);
 
   // Determine whether all queues are empty.
-  bool all_empty() const
-  {
-    for (timer_queue_base* p = first_; p; p = p->next_)
-      if (!p->empty())
-        return false;
-    return true;
-  }
+  ASIO_DECL bool all_empty() const;
 
   // Get the wait duration in milliseconds.
-  long wait_duration_msec(long max_duration) const
-  {
-    long min_duration = max_duration;
-    for (timer_queue_base* p = first_; p; p = p->next_)
-      min_duration = p->wait_duration_msec(min_duration);
-    return min_duration;
-  }
+  ASIO_DECL long wait_duration_msec(long max_duration) const;
 
   // Get the wait duration in microseconds.
-  long wait_duration_usec(long max_duration) const
-  {
-    long min_duration = max_duration;
-    for (timer_queue_base* p = first_; p; p = p->next_)
-      min_duration = p->wait_duration_usec(min_duration);
-    return min_duration;
-  }
+  ASIO_DECL long wait_duration_usec(long max_duration) const;
 
   // Dequeue all ready timers.
-  void get_ready_timers(op_queue<operation>& ops)
-  {
-    for (timer_queue_base* p = first_; p; p = p->next_)
-      p->get_ready_timers(ops);
-  }
+  ASIO_DECL void get_ready_timers(op_queue<operation>& ops);
 
   // Dequeue all timers.
-  void get_all_timers(op_queue<operation>& ops)
-  {
-    for (timer_queue_base* p = first_; p; p = p->next_)
-      p->get_all_timers(ops);
-  }
+  ASIO_DECL void get_all_timers(op_queue<operation>& ops);
 
 private:
   timer_queue_base* first_;
@@ -112,4 +59,8 @@ private:
 
 #include "asio/detail/pop_options.hpp"
 
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/detail/impl/timer_queue_set.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
 #endif // ASIO_DETAIL_TIMER_QUEUE_SET_HPP
diff --git a/ext/asio/asio/detail/timer_scheduler.hpp b/ext/asio/asio/detail/timer_scheduler.hpp
index 6822d3f..1222e63 100644
--- a/ext/asio/asio/detail/timer_scheduler.hpp
+++ b/ext/asio/asio/detail/timer_scheduler.hpp
@@ -1,8 +1,8 @@
 //
-// timer_scheduler.hpp
-// ~~~~~~~~~~~~~~~~~~~
+// detail/timer_scheduler.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,8 +15,7 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
+#include "asio/detail/config.hpp"
 #include "asio/detail/timer_scheduler_fwd.hpp"
 
 #if defined(ASIO_HAS_IOCP)
@@ -31,6 +30,4 @@
 # include "asio/detail/select_reactor.hpp"
 #endif
 
-#include "asio/detail/pop_options.hpp"
-
 #endif // ASIO_DETAIL_TIMER_SCHEDULER_HPP
diff --git a/ext/asio/asio/detail/timer_scheduler_fwd.hpp b/ext/asio/asio/detail/timer_scheduler_fwd.hpp
index d766a87..5fced50 100644
--- a/ext/asio/asio/detail/timer_scheduler_fwd.hpp
+++ b/ext/asio/asio/detail/timer_scheduler_fwd.hpp
@@ -1,8 +1,8 @@
 //
-// timer_scheduler_fwd.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~
+// detail/timer_scheduler_fwd.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,13 +15,19 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 
-#include "asio/detail/dev_poll_reactor_fwd.hpp"
-#include "asio/detail/epoll_reactor_fwd.hpp"
-#include "asio/detail/kqueue_reactor_fwd.hpp"
-#include "asio/detail/select_reactor_fwd.hpp"
-#include "asio/detail/win_iocp_io_service_fwd.hpp"
+#if defined(ASIO_HAS_IOCP)
+# include "asio/detail/win_iocp_io_service_fwd.hpp"
+#elif defined(ASIO_HAS_EPOLL)
+# include "asio/detail/epoll_reactor_fwd.hpp"
+#elif defined(ASIO_HAS_KQUEUE)
+# include "asio/detail/kqueue_reactor_fwd.hpp"
+#elif defined(ASIO_HAS_DEV_POLL)
+# include "asio/detail/dev_poll_reactor_fwd.hpp"
+#else
+# include "asio/detail/select_reactor_fwd.hpp"
+#endif
 
 namespace asio {
 namespace detail {
@@ -35,12 +41,10 @@ typedef kqueue_reactor timer_scheduler;
 #elif defined(ASIO_HAS_DEV_POLL)
 typedef dev_poll_reactor timer_scheduler;
 #else
-typedef select_reactor<false> timer_scheduler;
+typedef select_reactor timer_scheduler;
 #endif
 
 } // namespace detail
 } // namespace asio
 
-#include "asio/detail/pop_options.hpp"
-
 #endif // ASIO_DETAIL_TIMER_SCHEDULER_FWD_HPP
diff --git a/ext/asio/asio/detail/tss_ptr.hpp b/ext/asio/asio/detail/tss_ptr.hpp
index ac67d9f..0218f5f 100644
--- a/ext/asio/asio/detail/tss_ptr.hpp
+++ b/ext/asio/asio/detail/tss_ptr.hpp
@@ -1,8 +1,8 @@
 //
-// tss_ptr.hpp
-// ~~~~~~~~~~~
+// detail/tss_ptr.hpp
+// ~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,11 +15,7 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
+#include "asio/detail/config.hpp"
 
 #if !defined(BOOST_HAS_THREADS) || defined(ASIO_DISABLE_THREADS)
 # include "asio/detail/null_tss_ptr.hpp"
@@ -31,6 +27,8 @@
 # error Only Windows and POSIX are supported!
 #endif
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 namespace detail {
 
diff --git a/ext/asio/asio/detail/wait_handler.hpp b/ext/asio/asio/detail/wait_handler.hpp
new file mode 100644
index 0000000..0df16cb
--- /dev/null
+++ b/ext/asio/asio/detail/wait_handler.hpp
@@ -0,0 +1,76 @@
+//
+// detail/wait_handler.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_WAIT_HANDLER_HPP
+#define ASIO_DETAIL_WAIT_HANDLER_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+#include "asio/detail/fenced_block.hpp"
+#include "asio/detail/handler_alloc_helpers.hpp"
+#include "asio/detail/handler_invoke_helpers.hpp"
+#include "asio/detail/timer_op.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename Handler>
+class wait_handler : public timer_op
+{
+public:
+  ASIO_DEFINE_HANDLER_PTR(wait_handler);
+
+  wait_handler(Handler h)
+    : timer_op(&wait_handler::do_complete),
+      handler_(h)
+  {
+  }
+
+  static void do_complete(io_service_impl* owner, operation* base,
+      asio::error_code /*ec*/, std::size_t /*bytes_transferred*/)
+  {
+    // Take ownership of the handler object.
+    wait_handler* h(static_cast<wait_handler*>(base));
+    ptr p = { boost::addressof(h->handler_), h, h };
+
+    // Make a copy of the handler so that the memory can be deallocated before
+    // the upcall is made. Even if we're not about to make an upcall, a
+    // sub-object of the handler may be the true owner of the memory associated
+    // with the handler. Consequently, a local copy of the handler is required
+    // to ensure that any owning sub-object remains valid until after we have
+    // deallocated the memory here.
+    detail::binder1<Handler, asio::error_code>
+      handler(h->handler_, h->ec_);
+    p.h = boost::addressof(handler.handler_);
+    p.reset();
+
+    // Make the upcall if required.
+    if (owner)
+    {
+      asio::detail::fenced_block b;
+      asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+    }
+  }
+
+private:
+  Handler handler_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_WAIT_HANDLER_HPP
diff --git a/ext/asio/asio/detail/weak_ptr.hpp b/ext/asio/asio/detail/weak_ptr.hpp
new file mode 100644
index 0000000..35dca19
--- /dev/null
+++ b/ext/asio/asio/detail/weak_ptr.hpp
@@ -0,0 +1,39 @@
+//
+// detail/weak_ptr.hpp
+// ~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_WEAK_PTR_HPP
+#define ASIO_DETAIL_WEAK_PTR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+#include <boost/version.hpp>
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1600)
+# include <memory>
+#else
+# include <boost/weak_ptr.hpp>
+#endif
+
+namespace asio {
+namespace detail {
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1600)
+using std::weak_ptr;
+#else
+using boost::weak_ptr;
+#endif
+
+} // namespace detail
+} // namespace asio
+
+#endif // ASIO_DETAIL_WEAK_PTR_HPP
diff --git a/ext/asio/asio/detail/win_event.hpp b/ext/asio/asio/detail/win_event.hpp
index cabb2c3..71ad7e0 100644
--- a/ext/asio/asio/detail/win_event.hpp
+++ b/ext/asio/asio/detail/win_event.hpp
@@ -1,8 +1,8 @@
 //
-// win_event.hpp
-// ~~~~~~~~~~~~~
+// detail/win_event.hpp
+// ~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,23 +15,15 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
+#include "asio/detail/config.hpp"
 
 #if defined(BOOST_WINDOWS)
 
-#include "asio/error.hpp"
-#include "asio/system_error.hpp"
+#include <boost/assert.hpp>
 #include "asio/detail/noncopyable.hpp"
 #include "asio/detail/socket_types.hpp"
 
 #include "asio/detail/push_options.hpp"
-#include <boost/assert.hpp>
-#include <boost/throw_exception.hpp>
-#include "asio/detail/pop_options.hpp"
 
 namespace asio {
 namespace detail {
@@ -41,19 +33,7 @@ class win_event
 {
 public:
   // Constructor.
-  win_event()
-    : event_(::CreateEvent(0, true, false, 0))
-  {
-    if (!event_)
-    {
-      DWORD last_error = ::GetLastError();
-      asio::system_error e(
-          asio::error_code(last_error,
-            asio::error::get_system_category()),
-          "event");
-      boost::throw_exception(e);
-    }
-  }
+  ASIO_DECL win_event();
 
   // Destructor.
   ~win_event()
@@ -105,8 +85,12 @@ private:
 } // namespace detail
 } // namespace asio
 
-#endif // defined(BOOST_WINDOWS)
-
 #include "asio/detail/pop_options.hpp"
 
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/detail/impl/win_event.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
+#endif // defined(BOOST_WINDOWS)
+
 #endif // ASIO_DETAIL_WIN_EVENT_HPP
diff --git a/ext/asio/asio/detail/win_fd_set_adapter.hpp b/ext/asio/asio/detail/win_fd_set_adapter.hpp
index 012a10f..0cb9d8c 100644
--- a/ext/asio/asio/detail/win_fd_set_adapter.hpp
+++ b/ext/asio/asio/detail/win_fd_set_adapter.hpp
@@ -1,8 +1,8 @@
 //
-// win_fd_set_adapter.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~
+// detail/win_fd_set_adapter.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,11 +15,13 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
+
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
 
 #include "asio/detail/socket_types.hpp"
 
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 namespace detail {
@@ -81,8 +83,8 @@ private:
 } // namespace detail
 } // namespace asio
 
-#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-
 #include "asio/detail/pop_options.hpp"
 
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+
 #endif // ASIO_DETAIL_WIN_FD_SET_ADAPTER_HPP
diff --git a/ext/asio/asio/detail/win_fenced_block.hpp b/ext/asio/asio/detail/win_fenced_block.hpp
index 6338488..011f44b 100644
--- a/ext/asio/asio/detail/win_fenced_block.hpp
+++ b/ext/asio/asio/detail/win_fenced_block.hpp
@@ -1,8 +1,8 @@
 //
-// win_fenced_block.hpp
-// ~~~~~~~~~~~~~~~~~~~~
+// detail/win_fenced_block.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,16 +15,14 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
+#include "asio/detail/config.hpp"
 
 #if defined(BOOST_WINDOWS) && !defined(UNDER_CE)
 
 #include "asio/detail/socket_types.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 namespace detail {
 
@@ -35,7 +33,10 @@ public:
   // Constructor.
   win_fenced_block()
   {
-#if defined(BOOST_MSVC) && (BOOST_MSVC < 1400)
+#if defined(__BORLANDC__)
+    LONG barrier = 0;
+    ::InterlockedExchange(&barrier, 1);
+#elif defined(BOOST_MSVC) && ((BOOST_MSVC < 1400) || !defined(MemoryBarrier))
 # if defined(_M_IX86)
 #  pragma warning(push)
 #  pragma warning(disable:4793)
@@ -43,15 +44,18 @@ public:
     __asm { xchg barrier, eax }
 #  pragma warning(pop)
 # endif // defined(_M_IX86)
-#else // defined(BOOST_MSVC) && (BOOST_MSVC < 1400)
+#else
     MemoryBarrier();
-#endif // defined(BOOST_MSVC) && (BOOST_MSVC < 1400)
+#endif
   }
 
   // Destructor.
   ~win_fenced_block()
   {
-#if defined(BOOST_MSVC) && (BOOST_MSVC < 1400)
+#if defined(__BORLANDC__)
+    LONG barrier = 0;
+    ::InterlockedExchange(&barrier, 1);
+#elif defined(BOOST_MSVC) && ((BOOST_MSVC < 1400) || !defined(MemoryBarrier))
 # if defined(_M_IX86)
 #  pragma warning(push)
 #  pragma warning(disable:4793)
@@ -59,17 +63,17 @@ public:
     __asm { xchg barrier, eax }
 #  pragma warning(pop)
 # endif // defined(_M_IX86)
-#else // defined(BOOST_MSVC) && (BOOST_MSVC < 1400)
+#else
     MemoryBarrier();
-#endif // defined(BOOST_MSVC) && (BOOST_MSVC < 1400)
+#endif
   }
 };
 
 } // namespace detail
 } // namespace asio
 
-#endif // defined(BOOST_WINDOWS) && !defined(UNDER_CE)
-
 #include "asio/detail/pop_options.hpp"
 
+#endif // defined(BOOST_WINDOWS) && !defined(UNDER_CE)
+
 #endif // ASIO_DETAIL_WIN_FENCED_BLOCK_HPP
diff --git a/ext/asio/asio/detail/win_iocp_handle_read_op.hpp b/ext/asio/asio/detail/win_iocp_handle_read_op.hpp
new file mode 100644
index 0000000..fb358be
--- /dev/null
+++ b/ext/asio/asio/detail/win_iocp_handle_read_op.hpp
@@ -0,0 +1,101 @@
+//
+// detail/win_iocp_handle_read_op.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2008 Rep Invariant Systems, Inc. (info at repinvariant.com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_WIN_IOCP_HANDLE_READ_OP_HPP
+#define ASIO_DETAIL_WIN_IOCP_HANDLE_READ_OP_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(ASIO_HAS_IOCP)
+
+#include "asio/error.hpp"
+#include <boost/utility/addressof.hpp>
+#include "asio/detail/bind_handler.hpp"
+#include "asio/detail/buffer_sequence_adapter.hpp"
+#include "asio/detail/fenced_block.hpp"
+#include "asio/detail/handler_alloc_helpers.hpp"
+#include "asio/detail/handler_invoke_helpers.hpp"
+#include "asio/detail/operation.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename MutableBufferSequence, typename Handler>
+class win_iocp_handle_read_op : public operation
+{
+public:
+  ASIO_DEFINE_HANDLER_PTR(win_iocp_handle_read_op);
+
+  win_iocp_handle_read_op(const MutableBufferSequence& buffers, Handler handler)
+    : operation(&win_iocp_handle_read_op::do_complete),
+      buffers_(buffers),
+      handler_(handler)
+  {
+  }
+
+  static void do_complete(io_service_impl* owner, operation* base,
+      asio::error_code ec, std::size_t bytes_transferred)
+  {
+    // Take ownership of the operation object.
+    win_iocp_handle_read_op* o(static_cast<win_iocp_handle_read_op*>(base));
+    ptr p = { boost::addressof(o->handler_), o, o };
+
+#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
+    if (owner)
+    {
+      // Check whether buffers are still valid.
+      buffer_sequence_adapter<asio::mutable_buffer,
+          MutableBufferSequence>::validate(o->buffers_);
+    }
+#endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING)
+
+    // Map non-portable errors to their portable counterparts.
+    if (ec.value() == ERROR_HANDLE_EOF)
+      ec = asio::error::eof;
+
+    // Make a copy of the handler so that the memory can be deallocated before
+    // the upcall is made. Even if we're not about to make an upcall, a
+    // sub-object of the handler may be the true owner of the memory associated
+    // with the handler. Consequently, a local copy of the handler is required
+    // to ensure that any owning sub-object remains valid until after we have
+    // deallocated the memory here.
+    detail::binder2<Handler, asio::error_code, std::size_t>
+      handler(o->handler_, ec, bytes_transferred);
+    p.h = boost::addressof(handler.handler_);
+    p.reset();
+
+    // Make the upcall if required.
+    if (owner)
+    {
+      asio::detail::fenced_block b;
+      asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+    }
+  }
+
+private:
+  MutableBufferSequence buffers_;
+  Handler handler_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(ASIO_HAS_IOCP)
+
+#endif // ASIO_DETAIL_WIN_IOCP_HANDLE_READ_OP_HPP
diff --git a/ext/asio/asio/detail/win_iocp_handle_service.hpp b/ext/asio/asio/detail/win_iocp_handle_service.hpp
index bfc159c..34f725f 100644
--- a/ext/asio/asio/detail/win_iocp_handle_service.hpp
+++ b/ext/asio/asio/detail/win_iocp_handle_service.hpp
@@ -1,8 +1,8 @@
 //
-// win_iocp_handle_service.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// detail/win_iocp_handle_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 // Copyright (c) 2008 Rep Invariant Systems, Inc. (info at repinvariant.com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
@@ -16,26 +16,23 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/win_iocp_io_service_fwd.hpp"
+#include "asio/detail/config.hpp"
 
 #if defined(ASIO_HAS_IOCP)
 
-#include "asio/detail/push_options.hpp"
 #include <boost/cstdint.hpp>
-#include "asio/detail/pop_options.hpp"
-
 #include "asio/error.hpp"
 #include "asio/io_service.hpp"
-#include "asio/detail/bind_handler.hpp"
 #include "asio/detail/buffer_sequence_adapter.hpp"
 #include "asio/detail/handler_alloc_helpers.hpp"
-#include "asio/detail/handler_invoke_helpers.hpp"
 #include "asio/detail/mutex.hpp"
 #include "asio/detail/operation.hpp"
+#include "asio/detail/win_iocp_handle_read_op.hpp"
+#include "asio/detail/win_iocp_handle_write_op.hpp"
 #include "asio/detail/win_iocp_io_service.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 namespace detail {
 
@@ -76,75 +73,20 @@ public:
     implementation_type* prev_;
   };
 
-  win_iocp_handle_service(asio::io_service& io_service)
-    : iocp_service_(asio::use_service<win_iocp_io_service>(io_service)),
-      mutex_(),
-      impl_list_(0)
-  {
-  }
+  ASIO_DECL win_iocp_handle_service(asio::io_service& io_service);
 
   // Destroy all user-defined handler objects owned by the service.
-  void shutdown_service()
-  {
-    // Close all implementations, causing all operations to complete.
-    asio::detail::mutex::scoped_lock lock(mutex_);
-    implementation_type* impl = impl_list_;
-    while (impl)
-    {
-      close_for_destruction(*impl);
-      impl = impl->next_;
-    }
-  }
+  ASIO_DECL void shutdown_service();
 
   // Construct a new handle implementation.
-  void construct(implementation_type& impl)
-  {
-    impl.handle_ = INVALID_HANDLE_VALUE;
-    impl.safe_cancellation_thread_id_ = 0;
-
-    // Insert implementation into linked list of all implementations.
-    asio::detail::mutex::scoped_lock lock(mutex_);
-    impl.next_ = impl_list_;
-    impl.prev_ = 0;
-    if (impl_list_)
-      impl_list_->prev_ = &impl;
-    impl_list_ = &impl;
-  }
+  ASIO_DECL void construct(implementation_type& impl);
 
   // Destroy a handle implementation.
-  void destroy(implementation_type& impl)
-  {
-    close_for_destruction(impl);
-    
-    // Remove implementation from linked list of all implementations.
-    asio::detail::mutex::scoped_lock lock(mutex_);
-    if (impl_list_ == &impl)
-      impl_list_ = impl.next_;
-    if (impl.prev_)
-      impl.prev_->next_ = impl.next_;
-    if (impl.next_)
-      impl.next_->prev_= impl.prev_;
-    impl.next_ = 0;
-    impl.prev_ = 0;
-  }
+  ASIO_DECL void destroy(implementation_type& impl);
 
   // Assign a native handle to a handle implementation.
-  asio::error_code assign(implementation_type& impl,
-      const native_type& native_handle, asio::error_code& ec)
-  {
-    if (is_open(impl))
-    {
-      ec = asio::error::already_open;
-      return ec;
-    }
-
-    if (iocp_service_.register_handle(native_handle, ec))
-      return ec;
-
-    impl.handle_ = native_handle;
-    ec = asio::error_code();
-    return ec;
-  }
+  ASIO_DECL asio::error_code assign(implementation_type& impl,
+      const native_type& native_handle, asio::error_code& ec);
 
   // Determine whether the handle is open.
   bool is_open(const implementation_type& impl) const
@@ -153,26 +95,8 @@ public:
   }
 
   // Destroy a handle implementation.
-  asio::error_code close(implementation_type& impl,
-      asio::error_code& ec)
-  {
-    if (is_open(impl))
-    {
-      if (!::CloseHandle(impl.handle_))
-      {
-        DWORD last_error = ::GetLastError();
-        ec = asio::error_code(last_error,
-            asio::error::get_system_category());
-        return ec;
-      }
-
-      impl.handle_ = INVALID_HANDLE_VALUE;
-      impl.safe_cancellation_thread_id_ = 0;
-    }
-
-    ec = asio::error_code();
-    return ec;
-  }
+  ASIO_DECL asio::error_code close(implementation_type& impl,
+      asio::error_code& ec);
 
   // Get the native handle representation.
   native_type native(const implementation_type& impl) const
@@ -181,106 +105,8 @@ public:
   }
 
   // Cancel all operations associated with the handle.
-  asio::error_code cancel(implementation_type& impl,
-      asio::error_code& ec)
-  {
-    if (!is_open(impl))
-    {
-      ec = asio::error::bad_descriptor;
-    }
-    else if (FARPROC cancel_io_ex_ptr = ::GetProcAddress(
-          ::GetModuleHandleA("KERNEL32"), "CancelIoEx"))
-    {
-      // The version of Windows supports cancellation from any thread.
-      typedef BOOL (WINAPI* cancel_io_ex_t)(HANDLE, LPOVERLAPPED);
-      cancel_io_ex_t cancel_io_ex = (cancel_io_ex_t)cancel_io_ex_ptr;
-      if (!cancel_io_ex(impl.handle_, 0))
-      {
-        DWORD last_error = ::GetLastError();
-        if (last_error == ERROR_NOT_FOUND)
-        {
-          // ERROR_NOT_FOUND means that there were no operations to be
-          // cancelled. We swallow this error to match the behaviour on other
-          // platforms.
-          ec = asio::error_code();
-        }
-        else
-        {
-          ec = asio::error_code(last_error,
-              asio::error::get_system_category());
-        }
-      }
-      else
-      {
-        ec = asio::error_code();
-      }
-    }
-    else if (impl.safe_cancellation_thread_id_ == 0)
-    {
-      // No operations have been started, so there's nothing to cancel.
-      ec = asio::error_code();
-    }
-    else if (impl.safe_cancellation_thread_id_ == ::GetCurrentThreadId())
-    {
-      // Asynchronous operations have been started from the current thread only,
-      // so it is safe to try to cancel them using CancelIo.
-      if (!::CancelIo(impl.handle_))
-      {
-        DWORD last_error = ::GetLastError();
-        ec = asio::error_code(last_error,
-            asio::error::get_system_category());
-      }
-      else
-      {
-        ec = asio::error_code();
-      }
-    }
-    else
-    {
-      // Asynchronous operations have been started from more than one thread,
-      // so cancellation is not safe.
-      ec = asio::error::operation_not_supported;
-    }
-
-    return ec;
-  }
-
-  class overlapped_wrapper
-    : public OVERLAPPED
-  {
-  public:
-    explicit overlapped_wrapper(asio::error_code& ec)
-    {
-      Internal = 0;
-      InternalHigh = 0;
-      Offset = 0;
-      OffsetHigh = 0;
-
-      // Create a non-signalled manual-reset event, for GetOverlappedResult.
-      hEvent = ::CreateEvent(0, TRUE, FALSE, 0);
-      if (hEvent)
-      {
-        // As documented in GetQueuedCompletionStatus, setting the low order
-        // bit of this event prevents our synchronous writes from being treated
-        // as completion port events.
-        *reinterpret_cast<DWORD_PTR*>(&hEvent) |= 1;
-      }
-      else
-      {
-        DWORD last_error = ::GetLastError();
-        ec = asio::error_code(last_error,
-            asio::error::get_system_category());
-      }
-    }
-
-    ~overlapped_wrapper()
-    {
-      if (hEvent)
-      {
-        ::CloseHandle(hEvent);
-      }
-    }
-  };
+  ASIO_DECL asio::error_code cancel(implementation_type& impl,
+      asio::error_code& ec);
 
   // Write the given data. Returns the number of bytes written.
   template <typename ConstBufferSequence>
@@ -296,109 +122,13 @@ public:
   size_t write_some_at(implementation_type& impl, boost::uint64_t offset,
       const ConstBufferSequence& buffers, asio::error_code& ec)
   {
-    if (!is_open(impl))
-    {
-      ec = asio::error::bad_descriptor;
-      return 0;
-    }
-
     asio::const_buffer buffer =
       buffer_sequence_adapter<asio::const_buffer,
         ConstBufferSequence>::first(buffers);
 
-    // A request to write 0 bytes on a handle is a no-op.
-    if (asio::buffer_size(buffer) == 0)
-    {
-      ec = asio::error_code();
-      return 0;
-    }
-
-    overlapped_wrapper overlapped(ec);
-    if (ec)
-    {
-      return 0;
-    }
-
-    // Write the data. 
-    overlapped.Offset = offset & 0xFFFFFFFF;
-    overlapped.OffsetHigh = (offset >> 32) & 0xFFFFFFFF;
-    BOOL ok = ::WriteFile(impl.handle_,
-        asio::buffer_cast<LPCVOID>(buffer),
-        static_cast<DWORD>(asio::buffer_size(buffer)), 0, &overlapped);
-    if (!ok) 
-    {
-      DWORD last_error = ::GetLastError();
-      if (last_error != ERROR_IO_PENDING)
-      {
-        ec = asio::error_code(last_error,
-            asio::error::get_system_category());
-        return 0;
-      }
-    }
-
-    // Wait for the operation to complete.
-    DWORD bytes_transferred = 0;
-    ok = ::GetOverlappedResult(impl.handle_,
-        &overlapped, &bytes_transferred, TRUE);
-    if (!ok)
-    {
-      DWORD last_error = ::GetLastError();
-      ec = asio::error_code(last_error,
-          asio::error::get_system_category());
-      return 0;
-    }
-
-    ec = asio::error_code();
-    return bytes_transferred;
+    return do_write(impl, offset, buffer, ec);
   }
 
-  template <typename ConstBufferSequence, typename Handler>
-  class write_op : public operation
-  {
-  public:
-    write_op(const ConstBufferSequence& buffers, Handler handler)
-      : operation(&write_op::do_complete),
-        buffers_(buffers),
-        handler_(handler)
-    {
-    }
-
-    static void do_complete(io_service_impl* owner, operation* base,
-        asio::error_code ec, std::size_t bytes_transferred)
-    {
-      // Take ownership of the operation object.
-      write_op* o(static_cast<write_op*>(base));
-      typedef handler_alloc_traits<Handler, write_op> alloc_traits;
-      handler_ptr<alloc_traits> ptr(o->handler_, o);
-
-      // Make the upcall if required.
-      if (owner)
-      {
-#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
-        // Check whether buffers are still valid.
-        buffer_sequence_adapter<asio::const_buffer,
-            ConstBufferSequence>::validate(o->buffers_);
-#endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING)
-
-        // Make a copy of the handler so that the memory can be deallocated
-        // before the upcall is made. Even if we're not about to make an
-        // upcall, a sub-object of the handler may be the true owner of the
-        // memory associated with the handler. Consequently, a local copy of
-        // the handler is required to ensure that any owning sub-object remains
-        // valid until after we have deallocated the memory here.
-        detail::binder2<Handler, asio::error_code, std::size_t>
-          handler(o->handler_, ec, bytes_transferred);
-        ptr.reset();
-        asio::detail::fenced_block b;
-        asio_handler_invoke_helpers::invoke(handler, handler);
-      }
-    }
-
-  private:
-    ConstBufferSequence buffers_;
-    Handler handler_;
-  };
-
   // Start an asynchronous write. The data being written must be valid for the
   // lifetime of the asynchronous operation.
   template <typename ConstBufferSequence, typename Handler>
@@ -415,15 +145,16 @@ public:
       const ConstBufferSequence& buffers, Handler handler)
   {
     // Allocate and construct an operation to wrap the handler.
-    typedef write_op<ConstBufferSequence, Handler> value_type;
-    typedef handler_alloc_traits<Handler, value_type> alloc_traits;
-    raw_handler_ptr<alloc_traits> raw_ptr(handler);
-    handler_ptr<alloc_traits> ptr(raw_ptr, buffers, handler);
+    typedef win_iocp_handle_write_op<ConstBufferSequence, Handler> op;
+    typename op::ptr p = { boost::addressof(handler),
+      asio_handler_alloc_helpers::allocate(
+        sizeof(op), handler), 0 };
+    p.p = new (p.v) op(buffers, handler);
 
     start_write_op(impl, offset,
         buffer_sequence_adapter<asio::const_buffer,
-          ConstBufferSequence>::first(buffers), ptr.get());
-    ptr.release();
+          ConstBufferSequence>::first(buffers), p.p);
+    p.v = p.p = 0;
   }
 
   // Read some data. Returns the number of bytes received.
@@ -439,129 +170,13 @@ public:
   size_t read_some_at(implementation_type& impl, boost::uint64_t offset,
       const MutableBufferSequence& buffers, asio::error_code& ec)
   {
-    if (!is_open(impl))
-    {
-      ec = asio::error::bad_descriptor;
-      return 0;
-    }
-    
     asio::mutable_buffer buffer =
       buffer_sequence_adapter<asio::mutable_buffer,
         MutableBufferSequence>::first(buffers);
 
-    // A request to read 0 bytes on a stream handle is a no-op.
-    if (asio::buffer_size(buffer) == 0)
-    {
-      ec = asio::error_code();
-      return 0;
-    }
-
-    overlapped_wrapper overlapped(ec);
-    if (ec)
-    {
-      return 0;
-    }
-
-    // Read some data.
-    overlapped.Offset = offset & 0xFFFFFFFF;
-    overlapped.OffsetHigh = (offset >> 32) & 0xFFFFFFFF;
-    BOOL ok = ::ReadFile(impl.handle_,
-        asio::buffer_cast<LPVOID>(buffer),
-        static_cast<DWORD>(asio::buffer_size(buffer)), 0, &overlapped);
-    if (!ok) 
-    {
-      DWORD last_error = ::GetLastError();
-      if (last_error != ERROR_IO_PENDING && last_error != ERROR_MORE_DATA)
-      {
-        if (last_error == ERROR_HANDLE_EOF)
-        {
-          ec = asio::error::eof;
-        }
-        else
-        {
-          ec = asio::error_code(last_error,
-              asio::error::get_system_category());
-        }
-        return 0;
-      }
-    }
-
-    // Wait for the operation to complete.
-    DWORD bytes_transferred = 0;
-    ok = ::GetOverlappedResult(impl.handle_,
-        &overlapped, &bytes_transferred, TRUE);
-    if (!ok)
-    {
-      DWORD last_error = ::GetLastError();
-      if (last_error == ERROR_HANDLE_EOF)
-      {
-        ec = asio::error::eof;
-      }
-      else
-      {
-        ec = asio::error_code(last_error,
-            asio::error::get_system_category());
-      }
-      return 0;
-    }
-
-    ec = asio::error_code();
-    return bytes_transferred;
+    return do_read(impl, offset, buffer, ec);
   }
 
-  template <typename MutableBufferSequence, typename Handler>
-  class read_op : public operation
-  {
-  public:
-    read_op(const MutableBufferSequence& buffers, Handler handler)
-      : operation(&read_op::do_complete),
-        buffers_(buffers),
-        handler_(handler)
-    {
-    }
-
-    static void do_complete(io_service_impl* owner, operation* base,
-        asio::error_code ec, std::size_t bytes_transferred)
-    {
-      // Take ownership of the operation object.
-      read_op* o(static_cast<read_op*>(base));
-      typedef handler_alloc_traits<Handler, read_op> alloc_traits;
-      handler_ptr<alloc_traits> ptr(o->handler_, o);
-
-      // Make the upcall if required.
-      if (owner)
-      {
-#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
-        // Check whether buffers are still valid.
-        buffer_sequence_adapter<asio::mutable_buffer,
-            MutableBufferSequence>::validate(o->buffers_);
-#endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING)
-
-        // Map non-portable errors to their portable counterparts.
-        if (ec.value() == ERROR_HANDLE_EOF)
-        {
-          ec = asio::error::eof;
-        }
-
-        // Make a copy of the handler so that the memory can be deallocated
-        // before the upcall is made. Even if we're not about to make an
-        // upcall, a sub-object of the handler may be the true owner of the
-        // memory associated with the handler. Consequently, a local copy of
-        // the handler is required to ensure that any owning sub-object remains
-        // valid until after we have deallocated the memory here.
-        detail::binder2<Handler, asio::error_code, std::size_t>
-          handler(o->handler_, ec, bytes_transferred);
-        ptr.reset();
-        asio::detail::fenced_block b;
-        asio_handler_invoke_helpers::invoke(handler, handler);
-      }
-    }
-
-  private:
-    MutableBufferSequence buffers_;
-    Handler handler_;
-  };
-
   // Start an asynchronous read. The buffer for the data being received must be
   // valid for the lifetime of the asynchronous operation.
   template <typename MutableBufferSequence, typename Handler>
@@ -579,15 +194,16 @@ public:
       const MutableBufferSequence& buffers, Handler handler)
   {
     // Allocate and construct an operation to wrap the handler.
-    typedef read_op<MutableBufferSequence, Handler> value_type;
-    typedef handler_alloc_traits<Handler, value_type> alloc_traits;
-    raw_handler_ptr<alloc_traits> raw_ptr(handler);
-    handler_ptr<alloc_traits> ptr(raw_ptr, buffers, handler);
+    typedef win_iocp_handle_read_op<MutableBufferSequence, Handler> op;
+    typename op::ptr p = { boost::addressof(handler),
+      asio_handler_alloc_helpers::allocate(
+        sizeof(op), handler), 0 };
+    p.p = new (p.v) op(buffers, handler);
 
     start_read_op(impl, offset,
         buffer_sequence_adapter<asio::mutable_buffer,
-          MutableBufferSequence>::first(buffers), ptr.get());
-    ptr.release();
+          MutableBufferSequence>::first(buffers), p.p);
+    p.v = p.p = 0;
   }
 
 private:
@@ -613,113 +229,42 @@ private:
   void async_read_some_at(implementation_type& impl, boost::uint64_t offset,
       const null_buffers& buffers, Handler handler);
 
+  // Helper class for waiting for synchronous operations to complete.
+  class overlapped_wrapper;
+
+  // Helper function to perform a synchronous write operation.
+  ASIO_DECL size_t do_write(implementation_type& impl,
+      boost::uint64_t offset, const asio::const_buffer& buffer,
+      asio::error_code& ec);
+
   // Helper function to start a write operation.
-  void start_write_op(implementation_type& impl, boost::uint64_t offset,
-      const asio::const_buffer& buffer, operation* op)
-  {
-    update_cancellation_thread_id(impl);
-    iocp_service_.work_started();
+  ASIO_DECL void start_write_op(implementation_type& impl,
+      boost::uint64_t offset, const asio::const_buffer& buffer,
+      operation* op);
 
-    if (!is_open(impl))
-    {
-      iocp_service_.on_completion(op, asio::error::bad_descriptor);
-    }
-    else if (asio::buffer_size(buffer) == 0)
-    {
-      // A request to write 0 bytes on a handle is a no-op.
-      iocp_service_.on_completion(op);
-    }
-    else
-    {
-      DWORD bytes_transferred = 0;
-      op->Offset = offset & 0xFFFFFFFF;
-      op->OffsetHigh = (offset >> 32) & 0xFFFFFFFF;
-      BOOL ok = ::WriteFile(impl.handle_,
-          asio::buffer_cast<LPCVOID>(buffer),
-          static_cast<DWORD>(asio::buffer_size(buffer)),
-          &bytes_transferred, op);
-      DWORD last_error = ::GetLastError();
-      if (!ok && last_error != ERROR_IO_PENDING
-          && last_error != ERROR_MORE_DATA)
-      {
-        iocp_service_.on_completion(op, last_error, bytes_transferred);
-      }
-      else
-      {
-        iocp_service_.on_pending(op);
-      }
-    }
-  }
+  // Helper function to perform a synchronous write operation.
+  ASIO_DECL size_t do_read(implementation_type& impl,
+      boost::uint64_t offset, const asio::mutable_buffer& buffer,
+      asio::error_code& ec);
 
   // Helper function to start a read operation.
-  void start_read_op(implementation_type& impl, boost::uint64_t offset,
-      const asio::mutable_buffer& buffer, operation* op)
-  {
-    update_cancellation_thread_id(impl);
-    iocp_service_.work_started();
-
-    if (!is_open(impl))
-    {
-      iocp_service_.on_completion(op, asio::error::bad_descriptor);
-    }
-    else if (asio::buffer_size(buffer) == 0)
-    {
-      // A request to read 0 bytes on a handle is a no-op.
-      iocp_service_.on_completion(op);
-    }
-    else
-    {
-      DWORD bytes_transferred = 0;
-      op->Offset = offset & 0xFFFFFFFF;
-      op->OffsetHigh = (offset >> 32) & 0xFFFFFFFF;
-      BOOL ok = ::ReadFile(impl.handle_,
-          asio::buffer_cast<LPVOID>(buffer),
-          static_cast<DWORD>(asio::buffer_size(buffer)),
-          &bytes_transferred, op);
-      DWORD last_error = ::GetLastError();
-      if (!ok && last_error != ERROR_IO_PENDING
-          && last_error != ERROR_MORE_DATA)
-      {
-        iocp_service_.on_completion(op, last_error, bytes_transferred);
-      }
-      else
-      {
-        iocp_service_.on_pending(op);
-      }
-    }
-  }
+  ASIO_DECL void start_read_op(implementation_type& impl,
+      boost::uint64_t offset, const asio::mutable_buffer& buffer,
+      operation* op);
 
   // Update the ID of the thread from which cancellation is safe.
-  void update_cancellation_thread_id(implementation_type& impl)
-  {
-#if defined(ASIO_ENABLE_CANCELIO)
-    if (impl.safe_cancellation_thread_id_ == 0)
-      impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId();
-    else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId())
-      impl.safe_cancellation_thread_id_ = ~DWORD(0);
-#else // defined(ASIO_ENABLE_CANCELIO)
-    (void)impl;
-#endif // defined(ASIO_ENABLE_CANCELIO)
-  }
+  ASIO_DECL void update_cancellation_thread_id(implementation_type& impl);
 
   // Helper function to close a handle when the associated object is being
   // destroyed.
-  void close_for_destruction(implementation_type& impl)
-  {
-    if (is_open(impl))
-    {
-      ::CloseHandle(impl.handle_);
-      impl.handle_ = INVALID_HANDLE_VALUE;
-      impl.safe_cancellation_thread_id_ = 0;
-    }
-  }
+  ASIO_DECL void close_for_destruction(implementation_type& impl);
 
   // The IOCP service used for running asynchronous operations and dispatching
   // handlers.
   win_iocp_io_service& iocp_service_;
 
   // Mutex to protect access to the linked list of implementations.
-  asio::detail::mutex mutex_;
+  mutex mutex_;
 
   // The head of a linked list of all implementations.
   implementation_type* impl_list_;
@@ -728,8 +273,12 @@ private:
 } // namespace detail
 } // namespace asio
 
-#endif // defined(ASIO_HAS_IOCP)
-
 #include "asio/detail/pop_options.hpp"
 
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/detail/impl/win_iocp_handle_service.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
+#endif // defined(ASIO_HAS_IOCP)
+
 #endif // ASIO_DETAIL_WIN_IOCP_HANDLE_SERVICE_HPP
diff --git a/ext/asio/asio/detail/win_iocp_handle_write_op.hpp b/ext/asio/asio/detail/win_iocp_handle_write_op.hpp
new file mode 100644
index 0000000..ddfe8fc
--- /dev/null
+++ b/ext/asio/asio/detail/win_iocp_handle_write_op.hpp
@@ -0,0 +1,97 @@
+//
+// detail/win_iocp_handle_write_op.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2008 Rep Invariant Systems, Inc. (info at repinvariant.com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_WIN_IOCP_HANDLE_WRITE_OP_HPP
+#define ASIO_DETAIL_WIN_IOCP_HANDLE_WRITE_OP_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(ASIO_HAS_IOCP)
+
+#include "asio/error.hpp"
+#include <boost/utility/addressof.hpp>
+#include "asio/detail/bind_handler.hpp"
+#include "asio/detail/buffer_sequence_adapter.hpp"
+#include "asio/detail/fenced_block.hpp"
+#include "asio/detail/handler_alloc_helpers.hpp"
+#include "asio/detail/handler_invoke_helpers.hpp"
+#include "asio/detail/operation.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename ConstBufferSequence, typename Handler>
+class win_iocp_handle_write_op : public operation
+{
+public:
+  ASIO_DEFINE_HANDLER_PTR(win_iocp_handle_write_op);
+
+  win_iocp_handle_write_op(const ConstBufferSequence& buffers, Handler handler)
+    : operation(&win_iocp_handle_write_op::do_complete),
+      buffers_(buffers),
+      handler_(handler)
+  {
+  }
+
+  static void do_complete(io_service_impl* owner, operation* base,
+      asio::error_code ec, std::size_t bytes_transferred)
+  {
+    // Take ownership of the operation object.
+    win_iocp_handle_write_op* o(static_cast<win_iocp_handle_write_op*>(base));
+    ptr p = { boost::addressof(o->handler_), o, o };
+
+#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
+    if (owner)
+    {
+      // Check whether buffers are still valid.
+      buffer_sequence_adapter<asio::const_buffer,
+          ConstBufferSequence>::validate(o->buffers_);
+    }
+#endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING)
+
+    // Make a copy of the handler so that the memory can be deallocated before
+    // the upcall is made. Even if we're not about to make an upcall, a
+    // sub-object of the handler may be the true owner of the memory associated
+    // with the handler. Consequently, a local copy of the handler is required
+    // to ensure that any owning sub-object remains valid until after we have
+    // deallocated the memory here.
+    detail::binder2<Handler, asio::error_code, std::size_t>
+      handler(o->handler_, ec, bytes_transferred);
+    p.h = boost::addressof(handler.handler_);
+    p.reset();
+
+    // Make the upcall if required.
+    if (owner)
+    {
+      asio::detail::fenced_block b;
+      asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+    }
+  }
+
+private:
+  ConstBufferSequence buffers_;
+  Handler handler_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(ASIO_HAS_IOCP)
+
+#endif // ASIO_DETAIL_WIN_IOCP_HANDLE_WRITE_OP_HPP
diff --git a/ext/asio/asio/detail/win_iocp_io_service.hpp b/ext/asio/asio/detail/win_iocp_io_service.hpp
index fd899c1..c8974b6 100644
--- a/ext/asio/asio/detail/win_iocp_io_service.hpp
+++ b/ext/asio/asio/detail/win_iocp_io_service.hpp
@@ -1,8 +1,8 @@
 //
-// win_iocp_io_service.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~
+// detail/win_iocp_io_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,33 +15,24 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/win_iocp_io_service_fwd.hpp"
+#include "asio/detail/config.hpp"
 
 #if defined(ASIO_HAS_IOCP)
 
-#include "asio/detail/push_options.hpp"
-#include <boost/limits.hpp>
-#include <boost/throw_exception.hpp>
-#include "asio/detail/pop_options.hpp"
-
+#include <boost/scoped_ptr.hpp>
 #include "asio/io_service.hpp"
-#include "asio/system_error.hpp"
-#include "asio/detail/call_stack.hpp"
-#include "asio/detail/completion_handler.hpp"
-#include "asio/detail/fenced_block.hpp"
-#include "asio/detail/handler_alloc_helpers.hpp"
-#include "asio/detail/handler_invoke_helpers.hpp"
 #include "asio/detail/mutex.hpp"
 #include "asio/detail/op_queue.hpp"
-#include "asio/detail/service_base.hpp"
 #include "asio/detail/socket_types.hpp"
 #include "asio/detail/timer_op.hpp"
 #include "asio/detail/timer_queue_base.hpp"
 #include "asio/detail/timer_queue_fwd.hpp"
 #include "asio/detail/timer_queue_set.hpp"
+#include "asio/detail/win_iocp_io_service_fwd.hpp"
 #include "asio/detail/win_iocp_operation.hpp"
+#include "asio/detail/thread.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 namespace detail {
@@ -52,69 +43,13 @@ class win_iocp_io_service
   : public asio::detail::service_base<win_iocp_io_service>
 {
 public:
-  typedef win_iocp_operation operation;
-
   // Constructor.
-  win_iocp_io_service(asio::io_service& io_service)
-    : asio::detail::service_base<win_iocp_io_service>(io_service),
-      iocp_(),
-      outstanding_work_(0),
-      stopped_(0),
-      shutdown_(0),
-      timer_thread_(0),
-      timer_interrupt_issued_(false)
-  {
-  }
+  ASIO_DECL win_iocp_io_service(asio::io_service& io_service);
 
-  void init(size_t concurrency_hint)
-  {
-    iocp_.handle = ::CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0,
-        static_cast<DWORD>((std::min<size_t>)(concurrency_hint, DWORD(~0))));
-    if (!iocp_.handle)
-    {
-      DWORD last_error = ::GetLastError();
-      asio::system_error e(
-          asio::error_code(last_error,
-            asio::error::get_system_category()),
-          "iocp");
-      boost::throw_exception(e);
-    }
-  }
+  ASIO_DECL void init(size_t concurrency_hint);
 
   // Destroy all user-defined handler objects owned by the service.
-  void shutdown_service()
-  {
-    ::InterlockedExchange(&shutdown_, 1);
-
-    while (::InterlockedExchangeAdd(&outstanding_work_, 0) > 0)
-    {
-      op_queue<operation> ops;
-      timer_queues_.get_all_timers(ops);
-      ops.push(completed_ops_);
-      if (!ops.empty())
-      {
-        while (operation* op = ops.front())
-        {
-          ops.pop();
-          ::InterlockedDecrement(&outstanding_work_);
-          op->destroy();
-        }
-      }
-      else
-      {
-        DWORD bytes_transferred = 0;
-        dword_ptr_t completion_key = 0;
-        LPOVERLAPPED overlapped = 0;
-        ::GetQueuedCompletionStatus(iocp_.handle, &bytes_transferred,
-            &completion_key, &overlapped, max_timeout);
-        if (overlapped)
-        {
-          ::InterlockedDecrement(&outstanding_work_);
-          static_cast<operation*>(overlapped)->destroy();
-        }
-      }
-    }
-  }
+  ASIO_DECL void shutdown_service();
 
   // Initialise the task. Nothing to do here.
   void init_task()
@@ -122,106 +57,23 @@ public:
   }
 
   // Register a handle with the IO completion port.
-  asio::error_code register_handle(
-      HANDLE handle, asio::error_code& ec)
-  {
-    if (::CreateIoCompletionPort(handle, iocp_.handle, 0, 0) == 0)
-    {
-      DWORD last_error = ::GetLastError();
-      ec = asio::error_code(last_error,
-          asio::error::get_system_category());
-    }
-    else
-    {
-      ec = asio::error_code();
-    }
-    return ec;
-  }
+  ASIO_DECL asio::error_code register_handle(
+      HANDLE handle, asio::error_code& ec);
 
   // Run the event loop until stopped or no more work.
-  size_t run(asio::error_code& ec)
-  {
-    if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0)
-    {
-      stop();
-      ec = asio::error_code();
-      return 0;
-    }
-
-    call_stack<win_iocp_io_service>::context ctx(this);
-
-    size_t n = 0;
-    while (do_one(true, ec))
-      if (n != (std::numeric_limits<size_t>::max)())
-        ++n;
-    return n;
-  }
+  ASIO_DECL size_t run(asio::error_code& ec);
 
   // Run until stopped or one operation is performed.
-  size_t run_one(asio::error_code& ec)
-  {
-    if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0)
-    {
-      stop();
-      ec = asio::error_code();
-      return 0;
-    }
-
-    call_stack<win_iocp_io_service>::context ctx(this);
-
-    return do_one(true, ec);
-  }
+  ASIO_DECL size_t run_one(asio::error_code& ec);
 
   // Poll for operations without blocking.
-  size_t poll(asio::error_code& ec)
-  {
-    if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0)
-    {
-      stop();
-      ec = asio::error_code();
-      return 0;
-    }
-
-    call_stack<win_iocp_io_service>::context ctx(this);
-
-    size_t n = 0;
-    while (do_one(false, ec))
-      if (n != (std::numeric_limits<size_t>::max)())
-        ++n;
-    return n;
-  }
+  ASIO_DECL size_t poll(asio::error_code& ec);
 
   // Poll for one operation without blocking.
-  size_t poll_one(asio::error_code& ec)
-  {
-    if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0)
-    {
-      stop();
-      ec = asio::error_code();
-      return 0;
-    }
-
-    call_stack<win_iocp_io_service>::context ctx(this);
-
-    return do_one(false, ec);
-  }
+  ASIO_DECL size_t poll_one(asio::error_code& ec);
 
   // Stop the event processing loop.
-  void stop()
-  {
-    if (::InterlockedExchange(&stopped_, 1) == 0)
-    {
-      if (!::PostQueuedCompletionStatus(iocp_.handle, 0, 0, 0))
-      {
-        DWORD last_error = ::GetLastError();
-        asio::system_error e(
-            asio::error_code(last_error,
-              asio::error::get_system_category()),
-            "pqcs");
-        boost::throw_exception(e);
-      }
-    }
-  }
+  ASIO_DECL void stop();
 
   // Reset in preparation for a subsequent run invocation.
   void reset()
@@ -244,34 +96,15 @@ public:
 
   // Request invocation of the given handler.
   template <typename Handler>
-  void dispatch(Handler handler)
-  {
-    if (call_stack<win_iocp_io_service>::contains(this))
-    {
-      asio::detail::fenced_block b;
-      asio_handler_invoke_helpers::invoke(handler, handler);
-    }
-    else
-      post(handler);
-  }
+  void dispatch(Handler handler);
 
   // Request invocation of the given handler and return immediately.
   template <typename Handler>
-  void post(Handler handler)
-  {
-    // Allocate and construct an operation to wrap the handler.
-    typedef completion_handler<Handler> value_type;
-    typedef handler_alloc_traits<Handler, value_type> alloc_traits;
-    raw_handler_ptr<alloc_traits> raw_ptr(handler);
-    handler_ptr<alloc_traits> ptr(raw_ptr, handler);
-
-    post_immediate_completion(ptr.get());
-    ptr.release();
-  }
+  void post(Handler handler);
 
   // Request invocation of the given operation and return immediately. Assumes
   // that work_started() has not yet been called for the operation.
-  void post_immediate_completion(operation* op)
+  void post_immediate_completion(win_iocp_operation* op)
   {
     work_started();
     post_deferred_completion(op);
@@ -279,170 +112,50 @@ public:
 
   // Request invocation of the given operation and return immediately. Assumes
   // that work_started() was previously called for the operation.
-  void post_deferred_completion(operation* op)
-  {
-    // Flag the operation as ready.
-    op->ready_ = 1;
-
-    // Enqueue the operation on the I/O completion port.
-    if (!::PostQueuedCompletionStatus(iocp_.handle,
-          0, overlapped_contains_result, op))
-    {
-      // Out of resources. Put on completed queue instead.
-      asio::detail::mutex::scoped_lock lock(timer_mutex_);
-      completed_ops_.push(op);
-    }
-  }
+  ASIO_DECL void post_deferred_completion(win_iocp_operation* op);
 
   // Request invocation of the given operation and return immediately. Assumes
   // that work_started() was previously called for the operations.
-  void post_deferred_completions(op_queue<operation>& ops)
-  {
-    while (operation* op = ops.front())
-    {
-      ops.pop();
-
-      // Flag the operation as ready.
-      op->ready_ = 1;
-
-      // Enqueue the operation on the I/O completion port.
-      if (!::PostQueuedCompletionStatus(iocp_.handle,
-            0, overlapped_contains_result, op))
-      {
-        // Out of resources. Put on completed queue instead.
-        asio::detail::mutex::scoped_lock lock(timer_mutex_);
-        completed_ops_.push(op);
-        completed_ops_.push(ops);
-      }
-    }
-  }
+  ASIO_DECL void post_deferred_completions(
+      op_queue<win_iocp_operation>& ops);
 
   // Called after starting an overlapped I/O operation that did not complete
   // immediately. The caller must have already called work_started() prior to
   // starting the operation.
-  void on_pending(operation* op)
-  {
-    if (::InterlockedCompareExchange(&op->ready_, 1, 0) == 1)
-    {
-      // Enqueue the operation on the I/O completion port.
-      if (!::PostQueuedCompletionStatus(iocp_.handle,
-            0, overlapped_contains_result, op))
-      {
-        // Out of resources. Put on completed queue instead.
-        asio::detail::mutex::scoped_lock lock(timer_mutex_);
-        completed_ops_.push(op);
-      }
-    }
-  }
+  ASIO_DECL void on_pending(win_iocp_operation* op);
 
   // Called after starting an overlapped I/O operation that completed
   // immediately. The caller must have already called work_started() prior to
   // starting the operation.
-  void on_completion(operation* op,
-      DWORD last_error = 0, DWORD bytes_transferred = 0)
-  {
-    // Flag that the operation is ready for invocation.
-    op->ready_ = 1;
-
-    // Store results in the OVERLAPPED structure.
-    op->Internal = asio::error::get_system_category();
-    op->Offset = last_error;
-    op->OffsetHigh = bytes_transferred;
-
-    // Enqueue the operation on the I/O completion port.
-    if (!::PostQueuedCompletionStatus(iocp_.handle,
-          0, overlapped_contains_result, op))
-    {
-      // Out of resources. Put on completed queue instead.
-      asio::detail::mutex::scoped_lock lock(timer_mutex_);
-      completed_ops_.push(op);
-    }
-  }
+  ASIO_DECL void on_completion(win_iocp_operation* op,
+      DWORD last_error = 0, DWORD bytes_transferred = 0);
 
   // Called after starting an overlapped I/O operation that completed
   // immediately. The caller must have already called work_started() prior to
   // starting the operation.
-  void on_completion(operation* op,
-      const asio::error_code& ec, DWORD bytes_transferred = 0)
-  {
-    // Flag that the operation is ready for invocation.
-    op->ready_ = 1;
-
-    // Store results in the OVERLAPPED structure.
-    op->Internal = ec.category();
-    op->Offset = ec.value();
-    op->OffsetHigh = bytes_transferred;
-
-    // Enqueue the operation on the I/O completion port.
-    if (!::PostQueuedCompletionStatus(iocp_.handle,
-          0, overlapped_contains_result, op))
-    {
-      // Out of resources. Put on completed queue instead.
-      asio::detail::mutex::scoped_lock lock(timer_mutex_);
-      completed_ops_.push(op);
-    }
-  }
+  ASIO_DECL void on_completion(win_iocp_operation* op,
+      const asio::error_code& ec, DWORD bytes_transferred = 0);
 
   // Add a new timer queue to the service.
   template <typename Time_Traits>
-  void add_timer_queue(timer_queue<Time_Traits>& timer_queue)
-  {
-    asio::detail::mutex::scoped_lock lock(timer_mutex_);
-    timer_queues_.insert(&timer_queue);
-  }
+  void add_timer_queue(timer_queue<Time_Traits>& timer_queue);
 
   // Remove a timer queue from the service.
   template <typename Time_Traits>
-  void remove_timer_queue(timer_queue<Time_Traits>& timer_queue)
-  {
-    asio::detail::mutex::scoped_lock lock(timer_mutex_);
-    timer_queues_.erase(&timer_queue);
-  }
+  void remove_timer_queue(timer_queue<Time_Traits>& timer_queue);
 
   // Schedule a new operation in the given timer queue to expire at the
   // specified absolute time.
   template <typename Time_Traits>
-  void schedule_timer(timer_queue<Time_Traits>& timer_queue,
-      const typename Time_Traits::time_type& time, timer_op* op, void* token)
-  {
-    // If the service has been shut down we silently discard the timer.
-    if (::InterlockedExchangeAdd(&shutdown_, 0) != 0)
-      return;
-
-    asio::detail::mutex::scoped_lock lock(timer_mutex_);
-    bool interrupt = timer_queue.enqueue_timer(time, op, token);
-    work_started();
-    if (interrupt && !timer_interrupt_issued_)
-    {
-      timer_interrupt_issued_ = true;
-      lock.unlock();
-      ::PostQueuedCompletionStatus(iocp_.handle,
-          0, steal_timer_dispatching, 0);
-    }
-  }
+  void schedule_timer(timer_queue<Time_Traits>& queue,
+      const typename Time_Traits::time_type& time,
+      typename timer_queue<Time_Traits>::per_timer_data& timer, timer_op* op);
 
   // Cancel the timer associated with the given token. Returns the number of
   // handlers that have been posted or dispatched.
   template <typename Time_Traits>
-  std::size_t cancel_timer(timer_queue<Time_Traits>& timer_queue, void* token)
-  {
-    // If the service has been shut down we silently ignore the cancellation.
-    if (::InterlockedExchangeAdd(&shutdown_, 0) != 0)
-      return 0;
-
-    asio::detail::mutex::scoped_lock lock(timer_mutex_);
-    op_queue<operation> ops;
-    std::size_t n = timer_queue.cancel_timer(token, ops);
-    post_deferred_completions(ops);
-    if (n > 0 && !timer_interrupt_issued_)
-    {
-      timer_interrupt_issued_ = true;
-      lock.unlock();
-      ::PostQueuedCompletionStatus(iocp_.handle,
-          0, steal_timer_dispatching, 0);
-    }
-    return n;
-  }
+  std::size_t cancel_timer(timer_queue<Time_Traits>& queue,
+      typename timer_queue<Time_Traits>::per_timer_data& timer);
 
 private:
 #if defined(WINVER) && (WINVER < 0x0500)
@@ -456,181 +169,30 @@ private:
   // Dequeues at most one operation from the I/O completion port, and then
   // executes it. Returns the number of operations that were dequeued (i.e.
   // either 0 or 1).
-  size_t do_one(bool block, asio::error_code& ec)
-  {
-    long this_thread_id = static_cast<long>(::GetCurrentThreadId());
-
-    for (;;)
-    {
-      // Try to acquire responsibility for dispatching timers.
-      bool dispatching_timers = (::InterlockedCompareExchange(
-            &timer_thread_, this_thread_id, 0) == 0);
-
-      // Calculate timeout for GetQueuedCompletionStatus call.
-      DWORD timeout = max_timeout;
-      if (dispatching_timers)
-      {
-        asio::detail::mutex::scoped_lock lock(timer_mutex_);
-        timer_interrupt_issued_ = false;
-        timeout = get_timeout();
-      }
-
-      // Get the next operation from the queue.
-      DWORD bytes_transferred = 0;
-      dword_ptr_t completion_key = 0;
-      LPOVERLAPPED overlapped = 0;
-      ::SetLastError(0);
-      BOOL ok = ::GetQueuedCompletionStatus(iocp_.handle, &bytes_transferred,
-          &completion_key, &overlapped, block ? timeout : 0);
-      DWORD last_error = ::GetLastError();
-
-      // Dispatch any pending timers.
-      if (dispatching_timers)
-      {
-        asio::detail::mutex::scoped_lock lock(timer_mutex_);
-        op_queue<operation> ops;
-        ops.push(completed_ops_);
-        timer_queues_.get_ready_timers(ops);
-        post_deferred_completions(ops);
-      }
-
-      if (!ok && overlapped == 0)
-      {
-        if (block && last_error == WAIT_TIMEOUT)
-        {
-          // Relinquish responsibility for dispatching timers.
-          if (dispatching_timers)
-          {
-            ::InterlockedCompareExchange(&timer_thread_, 0, this_thread_id);
-          }
-
-          continue;
-        }
-
-        // Transfer responsibility for dispatching timers to another thread.
-        if (dispatching_timers && ::InterlockedCompareExchange(
-              &timer_thread_, 0, this_thread_id) == this_thread_id)
-        {
-          ::PostQueuedCompletionStatus(iocp_.handle,
-              0, transfer_timer_dispatching, 0);
-        }
-
-        ec = asio::error_code();
-        return 0;
-      }
-      else if (overlapped)
-      {
-        operation* op = static_cast<operation*>(overlapped);
-        asio::error_code result_ec(last_error,
-            asio::error::get_system_category());
-
-        // Transfer responsibility for dispatching timers to another thread.
-        if (dispatching_timers && ::InterlockedCompareExchange(
-              &timer_thread_, 0, this_thread_id) == this_thread_id)
-        {
-          ::PostQueuedCompletionStatus(iocp_.handle,
-              0, transfer_timer_dispatching, 0);
-        }
-
-        // We may have been passed the last_error and bytes_transferred in the
-        // OVERLAPPED structure itself.
-        if (completion_key == overlapped_contains_result)
-        {
-          result_ec = asio::error_code(static_cast<int>(op->Offset),
-              static_cast<asio::error_category>(op->Internal));
-          bytes_transferred = op->OffsetHigh;
-        }
-
-        // Otherwise ensure any result has been saved into the OVERLAPPED
-        // structure.
-        else
-        {
-          op->Internal = result_ec.category();
-          op->Offset = result_ec.value();
-          op->OffsetHigh = bytes_transferred;
-        }
-
-        // Dispatch the operation only if ready. The operation may not be ready
-        // if the initiating function (e.g. a call to WSARecv) has not yet
-        // returned. This is because the initiating function still wants access
-        // to the operation's OVERLAPPED structure.
-        if (::InterlockedCompareExchange(&op->ready_, 1, 0) == 1)
-        {
-          // Ensure the count of outstanding work is decremented on block exit.
-          work_finished_on_block_exit on_exit = { this };
-          (void)on_exit;
-
-          op->complete(*this, result_ec, bytes_transferred);
-          ec = asio::error_code();
-          return 1;
-        }
-      }
-      else if (completion_key == transfer_timer_dispatching)
-      {
-        // Woken up to try to acquire responsibility for dispatching timers.
-        ::InterlockedCompareExchange(&timer_thread_, 0, this_thread_id);
-      }
-      else if (completion_key == steal_timer_dispatching)
-      {
-        // Woken up to steal responsibility for dispatching timers.
-        ::InterlockedExchange(&timer_thread_, 0);
-      }
-      else
-      {
-        // Relinquish responsibility for dispatching timers. If the io_service
-        // is not being stopped then the thread will get an opportunity to
-        // reacquire timer responsibility on the next loop iteration.
-        if (dispatching_timers)
-        {
-          ::InterlockedCompareExchange(&timer_thread_, 0, this_thread_id);
-        }
-
-        // The stopped_ flag is always checked to ensure that any leftover
-        // interrupts from a previous run invocation are ignored.
-        if (::InterlockedExchangeAdd(&stopped_, 0) != 0)
-        {
-          // Wake up next thread that is blocked on GetQueuedCompletionStatus.
-          if (!::PostQueuedCompletionStatus(iocp_.handle, 0, 0, 0))
-          {
-            last_error = ::GetLastError();
-            ec = asio::error_code(last_error,
-                asio::error::get_system_category());
-            return 0;
-          }
-
-          ec = asio::error_code();
-          return 0;
-        }
-      }
-    }
-  }
+  ASIO_DECL size_t do_one(bool block, asio::error_code& ec);
 
-  // Get the timeout value for the GetQueuedCompletionStatus call. The timeout
-  // value is returned as a number of milliseconds. We will wait no longer than
-  // 1000 milliseconds.
-  DWORD get_timeout()
-  {
-    return timer_queues_.wait_duration_msec(max_timeout);
-  }
+  // Helper function to add a new timer queue.
+  ASIO_DECL void do_add_timer_queue(timer_queue_base& queue);
+
+  // Helper function to remove a timer queue.
+  ASIO_DECL void do_remove_timer_queue(timer_queue_base& queue);
+
+  // Called to recalculate and update the timeout.
+  ASIO_DECL void update_timeout();
 
   // Helper class to call work_finished() on block exit.
-  struct work_finished_on_block_exit
-  {
-    ~work_finished_on_block_exit()
-    {
-      io_service_->work_finished();
-    }
+  struct work_finished_on_block_exit;
 
-    win_iocp_io_service* io_service_;
+  // Helper class for managing a HANDLE.
+  struct auto_handle
+  {
+    HANDLE handle;
+    auto_handle() : handle(0) {}
+    ~auto_handle() { if (handle) ::CloseHandle(handle); }
   };
 
   // The IO completion port used for queueing operations.
-  struct iocp_holder
-  {
-    HANDLE handle;
-    iocp_holder() : handle(0) {}
-    ~iocp_holder() { if (handle) ::CloseHandle(handle); }
-  } iocp_;
+  auto_handle iocp_;
 
   // The count of unfinished work.
   long outstanding_work_;
@@ -643,44 +205,61 @@ private:
 
   enum
   {
-    // Maximum GetQueuedCompletionStatus timeout, in milliseconds.
-    max_timeout = 500,
+    // Timeout to use with GetQueuedCompletionStatus. Some versions of windows
+    // have a "bug" where a call to GetQueuedCompletionStatus can appear stuck
+    // even though there are events waiting on the queue. Using a timeout helps
+    // to work around the issue.
+    gqcs_timeout = 500,
+
+    // Maximum waitable timer timeout, in milliseconds.
+    max_timeout_msec = 5 * 60 * 1000,
 
-    // Completion key value to indicate that responsibility for dispatching
-    // timers is being cooperatively transferred from one thread to another.
-    transfer_timer_dispatching = 1,
+    // Maximum waitable timer timeout, in microseconds.
+    max_timeout_usec = max_timeout_msec * 1000,
 
-    // Completion key value to indicate that responsibility for dispatching
-    // timers should be stolen from another thread.
-    steal_timer_dispatching = 2,
+    // Completion key value used to wake up a thread to dispatch timers or
+    // completed operations.
+    wake_for_dispatch = 1,
 
     // Completion key value to indicate that an operation has posted with the
     // original last_error and bytes_transferred values stored in the fields of
     // the OVERLAPPED structure.
-    overlapped_contains_result = 3
+    overlapped_contains_result = 2
   };
 
-  // The thread that's currently in charge of dispatching timers.
-  long timer_thread_;
+  // Function object for processing timeouts in a background thread.
+  struct timer_thread_function;
+  friend struct timer_thread_function;
+
+  // Background thread used for processing timeouts.
+  boost::scoped_ptr<thread> timer_thread_;
+
+  // A waitable timer object used for waiting for timeouts.
+  auto_handle waitable_timer_;
 
-  // Mutex for protecting access to the timer queues.
-  mutex timer_mutex_;
+  // Non-zero if timers or completed operations need to be dispatched.
+  long dispatch_required_;
 
-  // Whether a thread has been interrupted to process a new timeout.
-  bool timer_interrupt_issued_;
+  // Mutex for protecting access to the timer queues and completed operations.
+  mutex dispatch_mutex_;
 
   // The timer queues.
   timer_queue_set timer_queues_;
 
   // The operations that are ready to dispatch.
-  op_queue<operation> completed_ops_;
+  op_queue<win_iocp_operation> completed_ops_;
 };
 
 } // namespace detail
 } // namespace asio
 
-#endif // defined(ASIO_HAS_IOCP)
-
 #include "asio/detail/pop_options.hpp"
 
+#include "asio/detail/impl/win_iocp_io_service.hpp"
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/detail/impl/win_iocp_io_service.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
+#endif // defined(ASIO_HAS_IOCP)
+
 #endif // ASIO_DETAIL_WIN_IOCP_IO_SERVICE_HPP
diff --git a/ext/asio/asio/detail/win_iocp_io_service_fwd.hpp b/ext/asio/asio/detail/win_iocp_io_service_fwd.hpp
index 29d2a05..9f03743 100644
--- a/ext/asio/asio/detail/win_iocp_io_service_fwd.hpp
+++ b/ext/asio/asio/detail/win_iocp_io_service_fwd.hpp
@@ -1,8 +1,8 @@
 //
-// win_iocp_io_service_fwd.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// detail/win_iocp_io_service_fwd.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,22 +15,9 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
-
-#include "asio/detail/socket_types.hpp"
-
-// This service is only supported on Win32 (NT4 and later).
-#if !defined(ASIO_DISABLE_IOCP)
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-#if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0400)
-#if !defined(UNDER_CE)
-
-// Define this to indicate that IOCP is supported on the target platform.
-#define ASIO_HAS_IOCP 1
+#if defined(ASIO_HAS_IOCP)
 
 namespace asio {
 namespace detail {
@@ -41,11 +28,6 @@ class win_iocp_overlapped_ptr;
 } // namespace detail
 } // namespace asio
 
-#endif // !defined(UNDER_CE)
-#endif // defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0400)
-#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-#endif // !defined(ASIO_DISABLE_IOCP)
-
-#include "asio/detail/pop_options.hpp"
+#endif // defined(ASIO_HAS_IOCP)
 
 #endif // ASIO_DETAIL_WIN_IOCP_IO_SERVICE_FWD_HPP
diff --git a/ext/asio/asio/detail/win_iocp_null_buffers_op.hpp b/ext/asio/asio/detail/win_iocp_null_buffers_op.hpp
new file mode 100644
index 0000000..e39fff7
--- /dev/null
+++ b/ext/asio/asio/detail/win_iocp_null_buffers_op.hpp
@@ -0,0 +1,112 @@
+//
+// detail/win_iocp_null_buffers_op.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_WIN_IOCP_NULL_BUFFERS_OP_HPP
+#define ASIO_DETAIL_WIN_IOCP_NULL_BUFFERS_OP_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(ASIO_HAS_IOCP)
+
+#include <boost/utility/addressof.hpp>
+#include "asio/detail/bind_handler.hpp"
+#include "asio/detail/buffer_sequence_adapter.hpp"
+#include "asio/detail/fenced_block.hpp"
+#include "asio/detail/handler_alloc_helpers.hpp"
+#include "asio/detail/handler_invoke_helpers.hpp"
+#include "asio/detail/reactor_op.hpp"
+#include "asio/detail/socket_ops.hpp"
+#include "asio/error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename Handler>
+class win_iocp_null_buffers_op : public reactor_op
+{
+public:
+  ASIO_DEFINE_HANDLER_PTR(win_iocp_null_buffers_op);
+
+  win_iocp_null_buffers_op(socket_ops::weak_cancel_token_type cancel_token,
+      Handler handler)
+    : reactor_op(&win_iocp_null_buffers_op::do_perform,
+        &win_iocp_null_buffers_op::do_complete),
+      cancel_token_(cancel_token),
+      handler_(handler)
+  {
+  }
+
+  static bool do_perform(reactor_op*)
+  {
+    return true;
+  }
+
+  static void do_complete(io_service_impl* owner, operation* base,
+      asio::error_code ec, std::size_t bytes_transferred)
+  {
+    // Take ownership of the operation object.
+    win_iocp_null_buffers_op* o(static_cast<win_iocp_null_buffers_op*>(base));
+    ptr p = { boost::addressof(o->handler_), o, o };
+
+    // The reactor may have stored a result in the operation object.
+    if (o->ec_)
+      ec = o->ec_;
+
+    // Map non-portable errors to their portable counterparts.
+    if (ec.value() == ERROR_NETNAME_DELETED)
+    {
+      if (o->cancel_token_.expired())
+        ec = asio::error::operation_aborted;
+      else
+        ec = asio::error::connection_reset;
+    }
+    else if (ec.value() == ERROR_PORT_UNREACHABLE)
+    {
+      ec = asio::error::connection_refused;
+    }
+
+    // Make a copy of the handler so that the memory can be deallocated before
+    // the upcall is made. Even if we're not about to make an upcall, a
+    // sub-object of the handler may be the true owner of the memory associated
+    // with the handler. Consequently, a local copy of the handler is required
+    // to ensure that any owning sub-object remains valid until after we have
+    // deallocated the memory here.
+    detail::binder2<Handler, asio::error_code, std::size_t>
+      handler(o->handler_, ec, bytes_transferred);
+    p.h = boost::addressof(handler.handler_);
+    p.reset();
+
+    // Make the upcall if required.
+    if (owner)
+    {
+      asio::detail::fenced_block b;
+      asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+    }
+  }
+
+private:
+  socket_ops::weak_cancel_token_type cancel_token_;
+  Handler handler_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(ASIO_HAS_IOCP)
+
+#endif // ASIO_DETAIL_WIN_IOCP_NULL_BUFFERS_OP_HPP
diff --git a/ext/asio/asio/detail/win_iocp_operation.hpp b/ext/asio/asio/detail/win_iocp_operation.hpp
index ac81062..649edd1 100644
--- a/ext/asio/asio/detail/win_iocp_operation.hpp
+++ b/ext/asio/asio/detail/win_iocp_operation.hpp
@@ -1,8 +1,8 @@
 //
-// win_iocp_operation.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~
+// detail/win_iocp_operation.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,14 +15,15 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/win_iocp_io_service_fwd.hpp"
+#include "asio/detail/config.hpp"
 
 #if defined(ASIO_HAS_IOCP)
 
-#include "asio/error_code.hpp"
 #include "asio/detail/op_queue.hpp"
+#include "asio/detail/win_iocp_io_service_fwd.hpp"
+#include "asio/error_code.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 namespace detail {
@@ -82,8 +83,8 @@ private:
 } // namespace detail
 } // namespace asio
 
-#endif // defined(ASIO_HAS_IOCP)
-
 #include "asio/detail/pop_options.hpp"
 
+#endif // defined(ASIO_HAS_IOCP)
+
 #endif // ASIO_DETAIL_WIN_IOCP_OPERATION_HPP
diff --git a/ext/asio/asio/detail/win_iocp_overlapped_op.hpp b/ext/asio/asio/detail/win_iocp_overlapped_op.hpp
new file mode 100644
index 0000000..f2b7ddf
--- /dev/null
+++ b/ext/asio/asio/detail/win_iocp_overlapped_op.hpp
@@ -0,0 +1,84 @@
+//
+// detail/win_iocp_overlapped_op.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_WIN_IOCP_OVERLAPPED_OP_HPP
+#define ASIO_DETAIL_WIN_IOCP_OVERLAPPED_OP_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(ASIO_HAS_IOCP)
+
+#include "asio/error.hpp"
+#include <boost/utility/addressof.hpp>
+#include "asio/detail/bind_handler.hpp"
+#include "asio/detail/fenced_block.hpp"
+#include "asio/detail/handler_alloc_helpers.hpp"
+#include "asio/detail/handler_invoke_helpers.hpp"
+#include "asio/detail/operation.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename Handler>
+class win_iocp_overlapped_op : public operation
+{
+public:
+  ASIO_DEFINE_HANDLER_PTR(win_iocp_overlapped_op);
+
+  win_iocp_overlapped_op(Handler handler)
+    : operation(&win_iocp_overlapped_op::do_complete),
+      handler_(handler)
+  {
+  }
+
+  static void do_complete(io_service_impl* owner, operation* base,
+      asio::error_code ec, std::size_t bytes_transferred)
+  {
+    // Take ownership of the operation object.
+    win_iocp_overlapped_op* o(static_cast<win_iocp_overlapped_op*>(base));
+    ptr p = { boost::addressof(o->handler_), o, o };
+
+    // Make a copy of the handler so that the memory can be deallocated before
+    // the upcall is made. Even if we're not about to make an upcall, a
+    // sub-object of the handler may be the true owner of the memory associated
+    // with the handler. Consequently, a local copy of the handler is required
+    // to ensure that any owning sub-object remains valid until after we have
+    // deallocated the memory here.
+    detail::binder2<Handler, asio::error_code, std::size_t>
+      handler(o->handler_, ec, bytes_transferred);
+    p.h = boost::addressof(handler.handler_);
+    p.reset();
+
+    // Make the upcall if required.
+    if (owner)
+    {
+      asio::detail::fenced_block b;
+      asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+    }
+  }
+
+private:
+  Handler handler_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(ASIO_HAS_IOCP)
+
+#endif // ASIO_DETAIL_WIN_IOCP_OVERLAPPED_OP_HPP
diff --git a/ext/asio/asio/detail/win_iocp_overlapped_ptr.hpp b/ext/asio/asio/detail/win_iocp_overlapped_ptr.hpp
index 47a3f70..919affe 100644
--- a/ext/asio/asio/detail/win_iocp_overlapped_ptr.hpp
+++ b/ext/asio/asio/detail/win_iocp_overlapped_ptr.hpp
@@ -1,8 +1,8 @@
 //
-// win_iocp_overlapped_ptr.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// detail/win_iocp_overlapped_ptr.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,16 +15,18 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/win_iocp_io_service_fwd.hpp"
+#include "asio/detail/config.hpp"
 
 #if defined(ASIO_HAS_IOCP)
 
-#include "asio/detail/fenced_block.hpp"
+#include <boost/utility/addressof.hpp>
+#include "asio/io_service.hpp"
+#include "asio/detail/handler_alloc_helpers.hpp"
 #include "asio/detail/noncopyable.hpp"
+#include "asio/detail/win_iocp_overlapped_op.hpp"
 #include "asio/detail/win_iocp_io_service.hpp"
-#include "asio/detail/win_iocp_operation.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 namespace detail {
@@ -74,13 +76,15 @@ public:
   template <typename Handler>
   void reset(asio::io_service& io_service, Handler handler)
   {
-    typedef overlapped_op<Handler> value_type;
-    typedef handler_alloc_traits<Handler, value_type> alloc_traits;
-    raw_handler_ptr<alloc_traits> raw_ptr(handler);
-    handler_ptr<alloc_traits> ptr(raw_ptr, handler);
+    typedef win_iocp_overlapped_op<Handler> op;
+    typename op::ptr p = { boost::addressof(handler),
+      asio_handler_alloc_helpers::allocate(
+        sizeof(op), handler), 0 };
+    p.p = new (p.v) op(handler);
     io_service.impl_.work_started();
     reset();
-    ptr_ = ptr.release();
+    ptr_ = p.p;
+    p.v = p.p = 0;
     iocp_service_ = &io_service.impl_;
   }
 
@@ -122,44 +126,6 @@ public:
   }
 
 private:
-  template <typename Handler>
-  struct overlapped_op : public win_iocp_operation
-  {
-    overlapped_op(Handler handler)
-      : win_iocp_operation(&overlapped_op::do_complete),
-        handler_(handler)
-    {
-    }
-
-    static void do_complete(io_service_impl* owner, operation* base,
-        asio::error_code ec, std::size_t bytes_transferred)
-    {
-      // Take ownership of the operation object.
-      overlapped_op* o(static_cast<overlapped_op*>(base));
-      typedef handler_alloc_traits<Handler, overlapped_op> alloc_traits;
-      handler_ptr<alloc_traits> ptr(o->handler_, o);
-
-      // Make the upcall if required.
-      if (owner)
-      {
-        // Make a copy of the handler so that the memory can be deallocated
-        // before the upcall is made. Even if we're not about to make an
-        // upcall, a sub-object of the handler may be the true owner of the
-        // memory associated with the handler. Consequently, a local copy of
-        // the handler is required to ensure that any owning sub-object remains
-        // valid until after we have deallocated the memory here.
-        detail::binder2<Handler, asio::error_code, std::size_t>
-          handler(o->handler_, ec, bytes_transferred);
-        ptr.reset();
-        asio::detail::fenced_block b;
-        asio_handler_invoke_helpers::invoke(handler, handler);
-      }
-    }
-
-  private:
-    Handler handler_;
-  };
-
   win_iocp_operation* ptr_;
   win_iocp_io_service* iocp_service_;
 };
@@ -167,8 +133,8 @@ private:
 } // namespace detail
 } // namespace asio
 
-#endif // defined(ASIO_HAS_IOCP)
-
 #include "asio/detail/pop_options.hpp"
 
+#endif // defined(ASIO_HAS_IOCP)
+
 #endif // ASIO_DETAIL_WIN_IOCP_OVERLAPPED_PTR_HPP
diff --git a/ext/asio/asio/detail/win_iocp_serial_port_service.hpp b/ext/asio/asio/detail/win_iocp_serial_port_service.hpp
index ed5f75e..bf3a692 100644
--- a/ext/asio/asio/detail/win_iocp_serial_port_service.hpp
+++ b/ext/asio/asio/detail/win_iocp_serial_port_service.hpp
@@ -1,8 +1,8 @@
 //
-// win_iocp_serial_port_service.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// detail/win_iocp_serial_port_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 // Copyright (c) 2008 Rep Invariant Systems, Inc. (info at repinvariant.com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
@@ -16,21 +16,17 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <cstring>
-#include <string>
-#include "asio/detail/pop_options.hpp"
-
-#include "asio/detail/win_iocp_io_service_fwd.hpp"
+#include "asio/detail/config.hpp"
 
-#if defined(ASIO_HAS_IOCP)
+#if defined(ASIO_HAS_IOCP) && defined(ASIO_HAS_SERIAL_PORT)
 
+#include <string>
 #include "asio/error.hpp"
 #include "asio/io_service.hpp"
 #include "asio/detail/win_iocp_handle_service.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 namespace detail {
 
@@ -38,133 +34,56 @@ namespace detail {
 class win_iocp_serial_port_service
 {
 public:
-  // The native type of a stream handle.
+  // The native type of a serial port.
   typedef win_iocp_handle_service::native_type native_type;
 
-  // The implementation type of the stream handle.
+  // The implementation type of the serial port.
   typedef win_iocp_handle_service::implementation_type implementation_type;
 
-  win_iocp_serial_port_service(asio::io_service& io_service)
-    : handle_service_(io_service)
-  {
-  }
+  // Constructor.
+  ASIO_DECL win_iocp_serial_port_service(
+      asio::io_service& io_service);
 
   // Destroy all user-defined handler objects owned by the service.
-  void shutdown_service()
-  {
-  }
+  ASIO_DECL void shutdown_service();
 
-  // Construct a new handle implementation.
+  // Construct a new serial port implementation.
   void construct(implementation_type& impl)
   {
     handle_service_.construct(impl);
   }
 
-  // Destroy a handle implementation.
+  // Destroy a serial port implementation.
   void destroy(implementation_type& impl)
   {
     handle_service_.destroy(impl);
   }
 
   // Open the serial port using the specified device name.
-  asio::error_code open(implementation_type& impl,
-      const std::string& device, asio::error_code& ec)
-  {
-    if (is_open(impl))
-    {
-      ec = asio::error::already_open;
-      return ec;
-    }
-
-    // For convenience, add a leading \\.\ sequence if not already present.
-    std::string name = (device[0] == '\\') ? device : "\\\\.\\" + device;
-
-    // Open a handle to the serial port.
-    ::HANDLE handle = ::CreateFileA(name.c_str(),
-        GENERIC_READ | GENERIC_WRITE, 0, 0,
-        OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
-    if (handle == INVALID_HANDLE_VALUE)
-    {
-      DWORD last_error = ::GetLastError();
-      ec = asio::error_code(last_error,
-          asio::error::get_system_category());
-      return ec;
-    }
-
-    // Determine the initial serial port parameters.
-    using namespace std; // For memcpy.
-    ::DCB dcb;
-    memset(&dcb, 0, sizeof(DCB));
-    dcb.DCBlength = sizeof(DCB);
-    if (!::GetCommState(handle, &dcb))
-    {
-      DWORD last_error = ::GetLastError();
-      ::CloseHandle(handle);
-      ec = asio::error_code(last_error,
-          asio::error::get_system_category());
-      return ec;
-    }
-
-    // Set some default serial port parameters. This implementation does not
-    // support changing these, so they might as well be in a known state.
-    dcb.fBinary = TRUE; // Win32 only supports binary mode.
-    dcb.fDsrSensitivity = FALSE;
-    dcb.fNull = FALSE; // Do not ignore NULL characters.
-    dcb.fAbortOnError = FALSE; // Ignore serial framing errors.
-    if (!::SetCommState(handle, &dcb))
-    {
-      DWORD last_error = ::GetLastError();
-      ::CloseHandle(handle);
-      ec = asio::error_code(last_error,
-          asio::error::get_system_category());
-      return ec;
-    }
-
-    // Set up timeouts so that the serial port will behave similarly to a
-    // network socket. Reads wait for at least one byte, then return with
-    // whatever they have. Writes return once everything is out the door.
-    ::COMMTIMEOUTS timeouts;
-    timeouts.ReadIntervalTimeout = 1;
-    timeouts.ReadTotalTimeoutMultiplier = 0;
-    timeouts.ReadTotalTimeoutConstant = 0;
-    timeouts.WriteTotalTimeoutMultiplier = 0;
-    timeouts.WriteTotalTimeoutConstant = 0;
-    if (!::SetCommTimeouts(handle, &timeouts))
-    {
-      DWORD last_error = ::GetLastError();
-      ::CloseHandle(handle);
-      ec = asio::error_code(last_error,
-          asio::error::get_system_category());
-      return ec;
-    }
-
-    // We're done. Take ownership of the serial port handle.
-    if (handle_service_.assign(impl, handle, ec))
-      ::CloseHandle(handle);
-    return ec;
-  }
+  ASIO_DECL asio::error_code open(implementation_type& impl,
+      const std::string& device, asio::error_code& ec);
 
-  // Assign a native handle to a handle implementation.
+  // Assign a native handle to a serial port implementation.
   asio::error_code assign(implementation_type& impl,
       const native_type& native_handle, asio::error_code& ec)
   {
     return handle_service_.assign(impl, native_handle, ec);
   }
 
-  // Determine whether the handle is open.
+  // Determine whether the serial port is open.
   bool is_open(const implementation_type& impl) const
   {
     return handle_service_.is_open(impl);
   }
 
-  // Destroy a handle implementation.
+  // Destroy a serial port implementation.
   asio::error_code close(implementation_type& impl,
       asio::error_code& ec)
   {
     return handle_service_.close(impl, ec);
   }
 
-  // Get the native handle representation.
+  // Get the native serial port representation.
   native_type native(implementation_type& impl)
   {
     return handle_service_.native(impl);
@@ -182,32 +101,9 @@ public:
   asio::error_code set_option(implementation_type& impl,
       const SettableSerialPortOption& option, asio::error_code& ec)
   {
-    using namespace std; // For memcpy.
-
-    ::DCB dcb;
-    memset(&dcb, 0, sizeof(DCB));
-    dcb.DCBlength = sizeof(DCB);
-    if (!::GetCommState(handle_service_.native(impl), &dcb))
-    {
-      DWORD last_error = ::GetLastError();
-      ec = asio::error_code(last_error,
-          asio::error::get_system_category());
-      return ec;
-    }
-
-    if (option.store(dcb, ec))
-      return ec;
-
-    if (!::SetCommState(handle_service_.native(impl), &dcb))
-    {
-      DWORD last_error = ::GetLastError();
-      ec = asio::error_code(last_error,
-          asio::error::get_system_category());
-      return ec;
-    }
-
-    ec = asio::error_code();
-    return ec;
+    return do_set_option(impl,
+        &win_iocp_serial_port_service::store_option<SettableSerialPortOption>,
+        &option, ec);
   }
 
   // Get an option from the serial port.
@@ -215,20 +111,9 @@ public:
   asio::error_code get_option(const implementation_type& impl,
       GettableSerialPortOption& option, asio::error_code& ec) const
   {
-    using namespace std; // For memcpy.
-
-    ::DCB dcb;
-    memset(&dcb, 0, sizeof(DCB));
-    dcb.DCBlength = sizeof(DCB);
-    if (!::GetCommState(handle_service_.native(impl), &dcb))
-    {
-      DWORD last_error = ::GetLastError();
-      ec = asio::error_code(last_error,
-          asio::error::get_system_category());
-      return ec;
-    }
-
-    return option.load(dcb, ec);
+    return do_get_option(impl,
+        &win_iocp_serial_port_service::load_option<GettableSerialPortOption>,
+        &option, ec);
   }
 
   // Send a break sequence to the serial port.
@@ -274,6 +159,41 @@ public:
   }
 
 private:
+  // Function pointer type for storing a serial port option.
+  typedef asio::error_code (*store_function_type)(
+      const void*, ::DCB&, asio::error_code&);
+
+  // Helper function template to store a serial port option.
+  template <typename SettableSerialPortOption>
+  static asio::error_code store_option(const void* option,
+      ::DCB& storage, asio::error_code& ec)
+  {
+    return static_cast<const SettableSerialPortOption*>(option)->store(
+        storage, ec);
+  }
+
+  // Helper function to set a serial port option.
+  ASIO_DECL asio::error_code do_set_option(
+      implementation_type& impl, store_function_type store,
+      const void* option, asio::error_code& ec);
+
+  // Function pointer type for loading a serial port option.
+  typedef asio::error_code (*load_function_type)(
+      void*, const ::DCB&, asio::error_code&);
+
+  // Helper function template to load a serial port option.
+  template <typename GettableSerialPortOption>
+  static asio::error_code load_option(void* option,
+      const ::DCB& storage, asio::error_code& ec)
+  {
+    return static_cast<GettableSerialPortOption*>(option)->load(storage, ec);
+  }
+
+  // Helper function to get a serial port option.
+  ASIO_DECL asio::error_code do_get_option(
+      const implementation_type& impl, load_function_type load,
+      void* option, asio::error_code& ec) const;
+
   // The implementation used for initiating asynchronous operations.
   win_iocp_handle_service handle_service_;
 };
@@ -281,8 +201,12 @@ private:
 } // namespace detail
 } // namespace asio
 
-#endif // defined(ASIO_HAS_IOCP)
-
 #include "asio/detail/pop_options.hpp"
 
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/detail/impl/win_iocp_serial_port_service.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
+#endif // defined(ASIO_HAS_IOCP) && defined(ASIO_HAS_SERIAL_PORT)
+
 #endif // ASIO_DETAIL_WIN_IOCP_SERIAL_PORT_SERVICE_HPP
diff --git a/ext/asio/asio/detail/win_iocp_socket_accept_op.hpp b/ext/asio/asio/detail/win_iocp_socket_accept_op.hpp
new file mode 100644
index 0000000..a71c7c0
--- /dev/null
+++ b/ext/asio/asio/detail/win_iocp_socket_accept_op.hpp
@@ -0,0 +1,158 @@
+//
+// detail/win_iocp_socket_accept_op.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_WIN_IOCP_SOCKET_ACCEPT_OP_HPP
+#define ASIO_DETAIL_WIN_IOCP_SOCKET_ACCEPT_OP_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(ASIO_HAS_IOCP)
+
+#include <boost/utility/addressof.hpp>
+#include "asio/detail/bind_handler.hpp"
+#include "asio/detail/buffer_sequence_adapter.hpp"
+#include "asio/detail/fenced_block.hpp"
+#include "asio/detail/handler_alloc_helpers.hpp"
+#include "asio/detail/handler_invoke_helpers.hpp"
+#include "asio/detail/operation.hpp"
+#include "asio/detail/socket_ops.hpp"
+#include "asio/detail/win_iocp_socket_service_base.hpp"
+#include "asio/error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename Socket, typename Protocol, typename Handler>
+class win_iocp_socket_accept_op : public operation
+{
+public:
+  ASIO_DEFINE_HANDLER_PTR(win_iocp_socket_accept_op);
+
+  win_iocp_socket_accept_op(win_iocp_socket_service_base& socket_service,
+      socket_type socket, Socket& peer, const Protocol& protocol,
+      typename Protocol::endpoint* peer_endpoint,
+      bool enable_connection_aborted, Handler handler)
+    : operation(&win_iocp_socket_accept_op::do_complete),
+      socket_service_(socket_service),
+      socket_(socket),
+      peer_(peer),
+      protocol_(protocol),
+      peer_endpoint_(peer_endpoint),
+      enable_connection_aborted_(enable_connection_aborted),
+      handler_(handler)
+  {
+  }
+
+  socket_holder& new_socket()
+  {
+    return new_socket_;
+  }
+
+  void* output_buffer()
+  {
+    return output_buffer_;
+  }
+
+  DWORD address_length()
+  {
+    return sizeof(sockaddr_storage_type) + 16;
+  }
+
+  static void do_complete(io_service_impl* owner, operation* base,
+      asio::error_code ec, std::size_t /*bytes_transferred*/)
+  {
+    // Take ownership of the operation object.
+    win_iocp_socket_accept_op* o(static_cast<win_iocp_socket_accept_op*>(base));
+    ptr p = { boost::addressof(o->handler_), o, o };
+
+    if (owner)
+    {
+      typename Protocol::endpoint peer_endpoint;
+      std::size_t addr_len = peer_endpoint.capacity();
+      socket_ops::complete_iocp_accept(o->socket_,
+          o->output_buffer(), o->address_length(),
+          peer_endpoint.data(), &addr_len,
+          o->new_socket_.get(), ec);
+
+      // Restart the accept operation if we got the connection_aborted error
+      // and the enable_connection_aborted socket option is not set.
+      if (ec == asio::error::connection_aborted
+          && !o->enable_connection_aborted_)
+      {
+        o->reset();
+        o->socket_service_.restart_accept_op(o->socket_,
+            o->new_socket_, o->protocol_.family(),
+            o->protocol_.type(), o->protocol_.protocol(),
+            o->output_buffer(), o->address_length(), o);
+        p.v = p.p = 0;
+        return;
+      }
+
+      // If the socket was successfully accepted, transfer ownership of the
+      // socket to the peer object.
+      if (!ec)
+      {
+        o->peer_.assign(o->protocol_,
+            typename Socket::native_type(
+              o->new_socket_.get(), peer_endpoint), ec);
+        if (!ec)
+          o->new_socket_.release();
+      }
+
+      // Pass endpoint back to caller.
+      if (o->peer_endpoint_)
+        *o->peer_endpoint_ = peer_endpoint;
+    }
+
+    // Make a copy of the handler so that the memory can be deallocated before
+    // the upcall is made. Even if we're not about to make an upcall, a
+    // sub-object of the handler may be the true owner of the memory associated
+    // with the handler. Consequently, a local copy of the handler is required
+    // to ensure that any owning sub-object remains valid until after we have
+    // deallocated the memory here.
+    detail::binder1<Handler, asio::error_code>
+      handler(o->handler_, ec);
+    p.h = boost::addressof(handler.handler_);
+    p.reset();
+
+    // Make the upcall if required.
+    if (owner)
+    {
+      asio::detail::fenced_block b;
+      asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+    }
+  }
+
+private:
+  win_iocp_socket_service_base& socket_service_;
+  socket_type socket_;
+  socket_holder new_socket_;
+  Socket& peer_;
+  Protocol protocol_;
+  typename Protocol::endpoint* peer_endpoint_;
+  unsigned char output_buffer_[(sizeof(sockaddr_storage_type) + 16) * 2];
+  bool enable_connection_aborted_;
+  Handler handler_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(ASIO_HAS_IOCP)
+
+#endif // ASIO_DETAIL_WIN_IOCP_SOCKET_ACCEPT_OP_HPP
diff --git a/ext/asio/asio/detail/win_iocp_socket_recv_op.hpp b/ext/asio/asio/detail/win_iocp_socket_recv_op.hpp
new file mode 100644
index 0000000..3ab4fcb
--- /dev/null
+++ b/ext/asio/asio/detail/win_iocp_socket_recv_op.hpp
@@ -0,0 +1,108 @@
+//
+// detail/win_iocp_socket_recv_op.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_WIN_IOCP_SOCKET_RECV_OP_HPP
+#define ASIO_DETAIL_WIN_IOCP_SOCKET_RECV_OP_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(ASIO_HAS_IOCP)
+
+#include <boost/utility/addressof.hpp>
+#include "asio/detail/bind_handler.hpp"
+#include "asio/detail/buffer_sequence_adapter.hpp"
+#include "asio/detail/fenced_block.hpp"
+#include "asio/detail/handler_alloc_helpers.hpp"
+#include "asio/detail/handler_invoke_helpers.hpp"
+#include "asio/detail/operation.hpp"
+#include "asio/detail/socket_ops.hpp"
+#include "asio/error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename MutableBufferSequence, typename Handler>
+class win_iocp_socket_recv_op : public operation
+{
+public:
+  ASIO_DEFINE_HANDLER_PTR(win_iocp_socket_recv_op);
+
+  win_iocp_socket_recv_op(socket_ops::state_type state,
+      socket_ops::weak_cancel_token_type cancel_token,
+      const MutableBufferSequence& buffers, Handler handler)
+    : operation(&win_iocp_socket_recv_op::do_complete),
+      state_(state),
+      cancel_token_(cancel_token),
+      buffers_(buffers),
+      handler_(handler)
+  {
+  }
+
+  static void do_complete(io_service_impl* owner, operation* base,
+      asio::error_code ec, std::size_t bytes_transferred)
+  {
+    // Take ownership of the operation object.
+    win_iocp_socket_recv_op* o(static_cast<win_iocp_socket_recv_op*>(base));
+    ptr p = { boost::addressof(o->handler_), o, o };
+
+#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
+    // Check whether buffers are still valid.
+    if (owner)
+    {
+      buffer_sequence_adapter<asio::mutable_buffer,
+          MutableBufferSequence>::validate(o->buffers_);
+    }
+#endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING)
+
+    socket_ops::complete_iocp_recv(o->state_, o->cancel_token_,
+        buffer_sequence_adapter<asio::mutable_buffer,
+          MutableBufferSequence>::all_empty(o->buffers_),
+        ec, bytes_transferred);
+
+    // Make a copy of the handler so that the memory can be deallocated before
+    // the upcall is made. Even if we're not about to make an upcall, a
+    // sub-object of the handler may be the true owner of the memory associated
+    // with the handler. Consequently, a local copy of the handler is required
+    // to ensure that any owning sub-object remains valid until after we have
+    // deallocated the memory here.
+    detail::binder2<Handler, asio::error_code, std::size_t>
+      handler(o->handler_, ec, bytes_transferred);
+    p.h = boost::addressof(handler.handler_);
+    p.reset();
+
+    // Make the upcall if required.
+    if (owner)
+    {
+      asio::detail::fenced_block b;
+      asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+    }
+  }
+
+private:
+  socket_ops::state_type state_;
+  socket_ops::weak_cancel_token_type cancel_token_;
+  MutableBufferSequence buffers_;
+  Handler handler_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(ASIO_HAS_IOCP)
+
+#endif // ASIO_DETAIL_WIN_IOCP_SOCKET_RECV_OP_HPP
diff --git a/ext/asio/asio/detail/win_iocp_socket_recvfrom_op.hpp b/ext/asio/asio/detail/win_iocp_socket_recvfrom_op.hpp
new file mode 100644
index 0000000..d1e2ece
--- /dev/null
+++ b/ext/asio/asio/detail/win_iocp_socket_recvfrom_op.hpp
@@ -0,0 +1,116 @@
+//
+// detail/win_iocp_socket_recvfrom_op.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_WIN_IOCP_SOCKET_RECVFROM_OP_HPP
+#define ASIO_DETAIL_WIN_IOCP_SOCKET_RECVFROM_OP_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(ASIO_HAS_IOCP)
+
+#include <boost/utility/addressof.hpp>
+#include "asio/detail/bind_handler.hpp"
+#include "asio/detail/buffer_sequence_adapter.hpp"
+#include "asio/detail/fenced_block.hpp"
+#include "asio/detail/handler_alloc_helpers.hpp"
+#include "asio/detail/handler_invoke_helpers.hpp"
+#include "asio/detail/operation.hpp"
+#include "asio/detail/socket_ops.hpp"
+#include "asio/error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename MutableBufferSequence, typename Endpoint, typename Handler>
+class win_iocp_socket_recvfrom_op : public operation
+{
+public:
+  ASIO_DEFINE_HANDLER_PTR(win_iocp_socket_recvfrom_op);
+
+  win_iocp_socket_recvfrom_op(Endpoint& endpoint,
+      socket_ops::weak_cancel_token_type cancel_token,
+      const MutableBufferSequence& buffers, Handler handler)
+    : operation(&win_iocp_socket_recvfrom_op::do_complete),
+      endpoint_(endpoint),
+      endpoint_size_(static_cast<int>(endpoint.capacity())),
+      cancel_token_(cancel_token),
+      buffers_(buffers),
+      handler_(handler)
+  {
+  }
+
+  int& endpoint_size()
+  {
+    return endpoint_size_;
+  }
+
+  static void do_complete(io_service_impl* owner, operation* base,
+      asio::error_code ec, std::size_t bytes_transferred)
+  {
+    // Take ownership of the operation object.
+    win_iocp_socket_recvfrom_op* o(
+        static_cast<win_iocp_socket_recvfrom_op*>(base));
+    ptr p = { boost::addressof(o->handler_), o, o };
+
+#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
+    // Check whether buffers are still valid.
+    if (owner)
+    {
+      buffer_sequence_adapter<asio::mutable_buffer,
+          MutableBufferSequence>::validate(o->buffers_);
+    }
+#endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING)
+
+    socket_ops::complete_iocp_recvfrom(o->cancel_token_, ec);
+
+    // Record the size of the endpoint returned by the operation.
+    o->endpoint_.resize(o->endpoint_size_);
+
+    // Make a copy of the handler so that the memory can be deallocated before
+    // the upcall is made. Even if we're not about to make an upcall, a
+    // sub-object of the handler may be the true owner of the memory associated
+    // with the handler. Consequently, a local copy of the handler is required
+    // to ensure that any owning sub-object remains valid until after we have
+    // deallocated the memory here.
+    detail::binder2<Handler, asio::error_code, std::size_t>
+      handler(o->handler_, ec, bytes_transferred);
+    p.h = boost::addressof(handler.handler_);
+    p.reset();
+
+    // Make the upcall if required.
+    if (owner)
+    {
+      asio::detail::fenced_block b;
+      asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+    }
+  }
+
+private:
+  Endpoint& endpoint_;
+  int endpoint_size_;
+  socket_ops::weak_cancel_token_type cancel_token_;
+  MutableBufferSequence buffers_;
+  Handler handler_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(ASIO_HAS_IOCP)
+
+#endif // ASIO_DETAIL_WIN_IOCP_SOCKET_RECVFROM_OP_HPP
diff --git a/ext/asio/asio/detail/win_iocp_socket_send_op.hpp b/ext/asio/asio/detail/win_iocp_socket_send_op.hpp
new file mode 100644
index 0000000..56f3f2d
--- /dev/null
+++ b/ext/asio/asio/detail/win_iocp_socket_send_op.hpp
@@ -0,0 +1,102 @@
+//
+// detail/win_iocp_socket_send_op.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_WIN_IOCP_SOCKET_SEND_OP_HPP
+#define ASIO_DETAIL_WIN_IOCP_SOCKET_SEND_OP_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(ASIO_HAS_IOCP)
+
+#include <boost/utility/addressof.hpp>
+#include "asio/detail/bind_handler.hpp"
+#include "asio/detail/buffer_sequence_adapter.hpp"
+#include "asio/detail/fenced_block.hpp"
+#include "asio/detail/handler_alloc_helpers.hpp"
+#include "asio/detail/handler_invoke_helpers.hpp"
+#include "asio/detail/operation.hpp"
+#include "asio/detail/socket_ops.hpp"
+#include "asio/error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename ConstBufferSequence, typename Handler>
+class win_iocp_socket_send_op : public operation
+{
+public:
+  ASIO_DEFINE_HANDLER_PTR(win_iocp_socket_send_op);
+
+  win_iocp_socket_send_op(socket_ops::weak_cancel_token_type cancel_token,
+      const ConstBufferSequence& buffers, Handler handler)
+    : operation(&win_iocp_socket_send_op::do_complete),
+      cancel_token_(cancel_token),
+      buffers_(buffers),
+      handler_(handler)
+  {
+  }
+
+  static void do_complete(io_service_impl* owner, operation* base,
+      asio::error_code ec, std::size_t bytes_transferred)
+  {
+    // Take ownership of the operation object.
+    win_iocp_socket_send_op* o(static_cast<win_iocp_socket_send_op*>(base));
+    ptr p = { boost::addressof(o->handler_), o, o };
+
+#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
+    // Check whether buffers are still valid.
+    if (owner)
+    {
+      buffer_sequence_adapter<asio::const_buffer,
+          ConstBufferSequence>::validate(o->buffers_);
+    }
+#endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING)
+
+    socket_ops::complete_iocp_send(o->cancel_token_, ec);
+
+    // Make a copy of the handler so that the memory can be deallocated before
+    // the upcall is made. Even if we're not about to make an upcall, a
+    // sub-object of the handler may be the true owner of the memory associated
+    // with the handler. Consequently, a local copy of the handler is required
+    // to ensure that any owning sub-object remains valid until after we have
+    // deallocated the memory here.
+    detail::binder2<Handler, asio::error_code, std::size_t>
+      handler(o->handler_, ec, bytes_transferred);
+    p.h = boost::addressof(handler.handler_);
+    p.reset();
+
+    // Make the upcall if required.
+    if (owner)
+    {
+      asio::detail::fenced_block b;
+      asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+    }
+  }
+
+private:
+  socket_ops::weak_cancel_token_type cancel_token_;
+  ConstBufferSequence buffers_;
+  Handler handler_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(ASIO_HAS_IOCP)
+
+#endif // ASIO_DETAIL_WIN_IOCP_SOCKET_SEND_OP_HPP
diff --git a/ext/asio/asio/detail/win_iocp_socket_service.hpp b/ext/asio/asio/detail/win_iocp_socket_service.hpp
index cb1d203..b476f8b 100644
--- a/ext/asio/asio/detail/win_iocp_socket_service.hpp
+++ b/ext/asio/asio/detail/win_iocp_socket_service.hpp
@@ -1,8 +1,8 @@
 //
-// win_iocp_socket_service.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// detail/win_iocp_socket_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,19 +15,12 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/win_iocp_io_service_fwd.hpp"
+#include "asio/detail/config.hpp"
 
 #if defined(ASIO_HAS_IOCP)
 
-#include "asio/detail/push_options.hpp"
 #include <cstring>
-#include <boost/shared_ptr.hpp>
-#include <boost/type_traits/is_same.hpp>
-#include <boost/weak_ptr.hpp>
-#include "asio/detail/pop_options.hpp"
-
+#include <boost/utility/addressof.hpp>
 #include "asio/error.hpp"
 #include "asio/io_service.hpp"
 #include "asio/socket_base.hpp"
@@ -37,20 +30,27 @@
 #include "asio/detail/handler_alloc_helpers.hpp"
 #include "asio/detail/handler_invoke_helpers.hpp"
 #include "asio/detail/mutex.hpp"
-#include "asio/detail/null_buffers_op.hpp"
 #include "asio/detail/operation.hpp"
+#include "asio/detail/reactive_socket_connect_op.hpp"
 #include "asio/detail/reactor.hpp"
 #include "asio/detail/reactor_op.hpp"
 #include "asio/detail/socket_holder.hpp"
 #include "asio/detail/socket_ops.hpp"
 #include "asio/detail/socket_types.hpp"
 #include "asio/detail/win_iocp_io_service.hpp"
+#include "asio/detail/win_iocp_null_buffers_op.hpp"
+#include "asio/detail/win_iocp_socket_accept_op.hpp"
+#include "asio/detail/win_iocp_socket_recvfrom_op.hpp"
+#include "asio/detail/win_iocp_socket_send_op.hpp"
+#include "asio/detail/win_iocp_socket_service_base.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 namespace detail {
 
 template <typename Protocol>
-class win_iocp_socket_service
+class win_iocp_socket_service : public win_iocp_socket_service_base
 {
 public:
   // The protocol type.
@@ -59,10 +59,6 @@ public:
   // The endpoint type.
   typedef typename Protocol::endpoint endpoint_type;
 
-  struct noop_deleter { void operator()(void*) {} };
-  typedef boost::shared_ptr<void> shared_cancel_token_type;
-  typedef boost::weak_ptr<void> weak_cancel_token_type;
-
   // The native type of a socket.
   class native_type
   {
@@ -92,11 +88,6 @@ public:
       return socket_;
     }
 
-    HANDLE as_handle() const
-    {
-      return reinterpret_cast<HANDLE>(socket_);
-    }
-
     bool have_remote_endpoint() const
     {
       return have_remote_endpoint_;
@@ -114,148 +105,44 @@ public:
   };
 
   // The implementation type of the socket.
-  class implementation_type
+  struct implementation_type :
+    win_iocp_socket_service_base::base_implementation_type
   {
-  public:
     // Default constructor.
     implementation_type()
-      : socket_(invalid_socket),
-        flags_(0),
-        cancel_token_(),
-        protocol_(endpoint_type().protocol()),
-        next_(0),
-        prev_(0)
+      : protocol_(endpoint_type().protocol()),
+        have_remote_endpoint_(false),
+        remote_endpoint_()
     {
     }
 
-  private:
-    // Only this service will have access to the internal values.
-    friend class win_iocp_socket_service;
-
-    // The native socket representation.
-    native_type socket_;
-
-    enum
-    {
-      enable_connection_aborted = 1, // User wants connection_aborted errors.
-      close_might_block = 2, // User set linger option for blocking close.
-      user_set_non_blocking = 4 // The user wants a non-blocking socket.
-    };
-
-    // Flags indicating the current state of the socket.
-    unsigned char flags_;
-
-    // We use a shared pointer as a cancellation token here to work around the
-    // broken Windows support for cancellation. MSDN says that when you call
-    // closesocket any outstanding WSARecv or WSASend operations will complete
-    // with the error ERROR_OPERATION_ABORTED. In practice they complete with
-    // ERROR_NETNAME_DELETED, which means you can't tell the difference between
-    // a local cancellation and the socket being hard-closed by the peer.
-    shared_cancel_token_type cancel_token_;
-
     // The protocol associated with the socket.
     protocol_type protocol_;
 
-    // Per-descriptor data used by the reactor.
-    reactor::per_descriptor_data reactor_data_;
-
-#if defined(ASIO_ENABLE_CANCELIO)
-    // The ID of the thread from which it is safe to cancel asynchronous
-    // operations. 0 means no asynchronous operations have been started yet.
-    // ~0 means asynchronous operations have been started from more than one
-    // thread, and cancellation is not supported for the socket.
-    DWORD safe_cancellation_thread_id_;
-#endif // defined(ASIO_ENABLE_CANCELIO)
+    // Whether we have a cached remote endpoint.
+    bool have_remote_endpoint_;
 
-    // Pointers to adjacent socket implementations in linked list.
-    implementation_type* next_;
-    implementation_type* prev_;
+    // A cached remote endpoint.
+    endpoint_type remote_endpoint_;
   };
 
   // Constructor.
   win_iocp_socket_service(asio::io_service& io_service)
-    : io_service_(io_service),
-      iocp_service_(use_service<win_iocp_io_service>(io_service)),
-      reactor_(0),
-      mutex_(),
-      impl_list_(0)
-  {
-  }
-
-  // Destroy all user-defined handler objects owned by the service.
-  void shutdown_service()
+    : win_iocp_socket_service_base(io_service)
   {
-    // Close all implementations, causing all operations to complete.
-    asio::detail::mutex::scoped_lock lock(mutex_);
-    implementation_type* impl = impl_list_;
-    while (impl)
-    {
-      asio::error_code ignored_ec;
-      close_for_destruction(*impl);
-      impl = impl->next_;
-    }
-  }
-
-  // Construct a new socket implementation.
-  void construct(implementation_type& impl)
-  {
-    impl.socket_ = invalid_socket;
-    impl.flags_ = 0;
-    impl.cancel_token_.reset();
-#if defined(ASIO_ENABLE_CANCELIO)
-    impl.safe_cancellation_thread_id_ = 0;
-#endif // defined(ASIO_ENABLE_CANCELIO)
-
-    // Insert implementation into linked list of all implementations.
-    asio::detail::mutex::scoped_lock lock(mutex_);
-    impl.next_ = impl_list_;
-    impl.prev_ = 0;
-    if (impl_list_)
-      impl_list_->prev_ = &impl;
-    impl_list_ = &impl;
-  }
-
-  // Destroy a socket implementation.
-  void destroy(implementation_type& impl)
-  {
-    close_for_destruction(impl);
-
-    // Remove implementation from linked list of all implementations.
-    asio::detail::mutex::scoped_lock lock(mutex_);
-    if (impl_list_ == &impl)
-      impl_list_ = impl.next_;
-    if (impl.prev_)
-      impl.prev_->next_ = impl.next_;
-    if (impl.next_)
-      impl.next_->prev_= impl.prev_;
-    impl.next_ = 0;
-    impl.prev_ = 0;
   }
 
   // Open a new socket implementation.
   asio::error_code open(implementation_type& impl,
       const protocol_type& protocol, asio::error_code& ec)
   {
-    if (is_open(impl))
+    if (!do_open(impl, protocol.family(),
+          protocol.type(), protocol.protocol(), ec))
     {
-      ec = asio::error::already_open;
-      return ec;
+      impl.protocol_ = protocol;
+      impl.have_remote_endpoint_ = false;
+      impl.remote_endpoint_ = endpoint_type();
     }
-
-    socket_holder sock(socket_ops::socket(protocol.family(), protocol.type(),
-          protocol.protocol(), ec));
-    if (sock.get() == invalid_socket)
-      return ec;
-
-    HANDLE sock_as_handle = reinterpret_cast<HANDLE>(sock.get());
-    if (iocp_service_.register_handle(sock_as_handle, ec))
-      return ec;
-
-    impl.socket_ = sock.release();
-    impl.flags_ = 0;
-    impl.cancel_token_.reset(static_cast<void*>(0), noop_deleter());
-    impl.protocol_ = protocol;
-    ec = asio::error_code();
     return ec;
   }
 
@@ -264,247 +151,40 @@ public:
       const protocol_type& protocol, const native_type& native_socket,
       asio::error_code& ec)
   {
-    if (is_open(impl))
-    {
-      ec = asio::error::already_open;
-      return ec;
-    }
-
-    if (iocp_service_.register_handle(native_socket.as_handle(), ec))
-      return ec;
-
-    impl.socket_ = native_socket;
-    impl.flags_ = 0;
-    impl.cancel_token_.reset(static_cast<void*>(0), noop_deleter());
-    impl.protocol_ = protocol;
-    ec = asio::error_code();
-    return ec;
-  }
-
-  // Determine whether the socket is open.
-  bool is_open(const implementation_type& impl) const
-  {
-    return impl.socket_ != invalid_socket;
-  }
-
-  // Destroy a socket implementation.
-  asio::error_code close(implementation_type& impl,
-      asio::error_code& ec)
-  {
-    if (is_open(impl))
+    if (!do_assign(impl, protocol.type(), native_socket, ec))
     {
-      // Check if the reactor was created, in which case we need to close the
-      // socket on the reactor as well to cancel any operations that might be
-      // running there.
-      reactor* r = static_cast<reactor*>(
-            interlocked_compare_exchange_pointer(
-              reinterpret_cast<void**>(&reactor_), 0, 0));
-      if (r)
-        r->close_descriptor(impl.socket_, impl.reactor_data_);
-
-      if (socket_ops::close(impl.socket_, ec) == socket_error_retval)
-        return ec;
-
-      impl.socket_ = invalid_socket;
-      impl.flags_ = 0;
-      impl.cancel_token_.reset();
-#if defined(ASIO_ENABLE_CANCELIO)
-      impl.safe_cancellation_thread_id_ = 0;
-#endif // defined(ASIO_ENABLE_CANCELIO)
+      impl.protocol_ = protocol;
+      impl.have_remote_endpoint_ = native_socket.have_remote_endpoint();
+      impl.remote_endpoint_ = native_socket.remote_endpoint();
     }
-
-    ec = asio::error_code();
     return ec;
   }
 
   // Get the native socket representation.
   native_type native(implementation_type& impl)
   {
-    return impl.socket_;
-  }
-
-  // Cancel all operations associated with the socket.
-  asio::error_code cancel(implementation_type& impl,
-      asio::error_code& ec)
-  {
-    if (!is_open(impl))
-    {
-      ec = asio::error::bad_descriptor;
-      return ec;
-    }
-    else if (FARPROC cancel_io_ex_ptr = ::GetProcAddress(
-          ::GetModuleHandleA("KERNEL32"), "CancelIoEx"))
-    {
-      // The version of Windows supports cancellation from any thread.
-      typedef BOOL (WINAPI* cancel_io_ex_t)(HANDLE, LPOVERLAPPED);
-      cancel_io_ex_t cancel_io_ex = (cancel_io_ex_t)cancel_io_ex_ptr;
-      socket_type sock = impl.socket_;
-      HANDLE sock_as_handle = reinterpret_cast<HANDLE>(sock);
-      if (!cancel_io_ex(sock_as_handle, 0))
-      {
-        DWORD last_error = ::GetLastError();
-        if (last_error == ERROR_NOT_FOUND)
-        {
-          // ERROR_NOT_FOUND means that there were no operations to be
-          // cancelled. We swallow this error to match the behaviour on other
-          // platforms.
-          ec = asio::error_code();
-        }
-        else
-        {
-          ec = asio::error_code(last_error,
-              asio::error::get_system_category());
-        }
-      }
-      else
-      {
-        ec = asio::error_code();
-      }
-    }
-#if defined(ASIO_ENABLE_CANCELIO)
-    else if (impl.safe_cancellation_thread_id_ == 0)
-    {
-      // No operations have been started, so there's nothing to cancel.
-      ec = asio::error_code();
-    }
-    else if (impl.safe_cancellation_thread_id_ == ::GetCurrentThreadId())
-    {
-      // Asynchronous operations have been started from the current thread only,
-      // so it is safe to try to cancel them using CancelIo.
-      socket_type sock = impl.socket_;
-      HANDLE sock_as_handle = reinterpret_cast<HANDLE>(sock);
-      if (!::CancelIo(sock_as_handle))
-      {
-        DWORD last_error = ::GetLastError();
-        ec = asio::error_code(last_error,
-            asio::error::get_system_category());
-      }
-      else
-      {
-        ec = asio::error_code();
-      }
-    }
-    else
-    {
-      // Asynchronous operations have been started from more than one thread,
-      // so cancellation is not safe.
-      ec = asio::error::operation_not_supported;
-    }
-#else // defined(ASIO_ENABLE_CANCELIO)
-    else
-    {
-      // Cancellation is not supported as CancelIo may not be used.
-      ec = asio::error::operation_not_supported;
-    }
-#endif // defined(ASIO_ENABLE_CANCELIO)
-
-    return ec;
-  }
-
-  // Determine whether the socket is at the out-of-band data mark.
-  bool at_mark(const implementation_type& impl,
-      asio::error_code& ec) const
-  {
-    if (!is_open(impl))
-    {
-      ec = asio::error::bad_descriptor;
-      return false;
-    }
-
-    asio::detail::ioctl_arg_type value = 0;
-    socket_ops::ioctl(impl.socket_, SIOCATMARK, &value, ec);
-    return ec ? false : value != 0;
-  }
-
-  // Determine the number of bytes available for reading.
-  std::size_t available(const implementation_type& impl,
-      asio::error_code& ec) const
-  {
-    if (!is_open(impl))
-    {
-      ec = asio::error::bad_descriptor;
-      return 0;
-    }
-
-    asio::detail::ioctl_arg_type value = 0;
-    socket_ops::ioctl(impl.socket_, FIONREAD, &value, ec);
-    return ec ? static_cast<std::size_t>(0) : static_cast<std::size_t>(value);
+    if (impl.have_remote_endpoint_)
+      return native_type(impl.socket_, impl.remote_endpoint_);
+    return native_type(impl.socket_);
   }
 
   // Bind the socket to the specified local endpoint.
   asio::error_code bind(implementation_type& impl,
       const endpoint_type& endpoint, asio::error_code& ec)
   {
-    if (!is_open(impl))
-    {
-      ec = asio::error::bad_descriptor;
-      return ec;
-    }
-
     socket_ops::bind(impl.socket_, endpoint.data(), endpoint.size(), ec);
     return ec;
   }
 
-  // Place the socket into the state where it will listen for new connections.
-  asio::error_code listen(implementation_type& impl, int backlog,
-      asio::error_code& ec)
-  {
-    if (!is_open(impl))
-    {
-      ec = asio::error::bad_descriptor;
-      return ec;
-    }
-
-    socket_ops::listen(impl.socket_, backlog, ec);
-    return ec;
-  }
-
   // Set a socket option.
   template <typename Option>
   asio::error_code set_option(implementation_type& impl,
       const Option& option, asio::error_code& ec)
   {
-    if (!is_open(impl))
-    {
-      ec = asio::error::bad_descriptor;
-      return ec;
-    }
-
-    if (option.level(impl.protocol_) == custom_socket_option_level
-        && option.name(impl.protocol_) == enable_connection_aborted_option)
-    {
-      if (option.size(impl.protocol_) != sizeof(int))
-      {
-        ec = asio::error::invalid_argument;
-      }
-      else
-      {
-        if (*reinterpret_cast<const int*>(option.data(impl.protocol_)))
-          impl.flags_ |= implementation_type::enable_connection_aborted;
-        else
-          impl.flags_ &= ~implementation_type::enable_connection_aborted;
-        ec = asio::error_code();
-      }
-      return ec;
-    }
-    else
-    {
-      if (option.level(impl.protocol_) == SOL_SOCKET
-          && option.name(impl.protocol_) == SO_LINGER)
-      {
-        const ::linger* linger_option =
-          reinterpret_cast<const ::linger*>(option.data(impl.protocol_));
-        if (linger_option->l_onoff != 0 && linger_option->l_linger != 0)
-          impl.flags_ |= implementation_type::close_might_block;
-        else
-          impl.flags_ &= ~implementation_type::close_might_block;
-      }
-
-      socket_ops::setsockopt(impl.socket_,
-          option.level(impl.protocol_), option.name(impl.protocol_),
-          option.data(impl.protocol_), option.size(impl.protocol_), ec);
-      return ec;
-    }
+    socket_ops::setsockopt(impl.socket_, impl.state_,
+        option.level(impl.protocol_), option.name(impl.protocol_),
+        option.data(impl.protocol_), option.size(impl.protocol_), ec);
+    return ec;
   }
 
   // Set a socket option.
@@ -512,65 +192,12 @@ public:
   asio::error_code get_option(const implementation_type& impl,
       Option& option, asio::error_code& ec) const
   {
-    if (!is_open(impl))
-    {
-      ec = asio::error::bad_descriptor;
-      return ec;
-    }
-
-    if (option.level(impl.protocol_) == custom_socket_option_level
-        && option.name(impl.protocol_) == enable_connection_aborted_option)
-    {
-      if (option.size(impl.protocol_) != sizeof(int))
-      {
-        ec = asio::error::invalid_argument;
-      }
-      else
-      {
-        int* target = reinterpret_cast<int*>(option.data(impl.protocol_));
-        if (impl.flags_ & implementation_type::enable_connection_aborted)
-          *target = 1;
-        else
-          *target = 0;
-        option.resize(impl.protocol_, sizeof(int));
-        ec = asio::error_code();
-      }
-      return ec;
-    }
-    else
-    {
-      size_t size = option.size(impl.protocol_);
-      socket_ops::getsockopt(impl.socket_,
-          option.level(impl.protocol_), option.name(impl.protocol_),
-          option.data(impl.protocol_), &size, ec);
-      if (!ec)
-        option.resize(impl.protocol_, size);
-      return ec;
-    }
-  }
-
-  // Perform an IO control command on the socket.
-  template <typename IO_Control_Command>
-  asio::error_code io_control(implementation_type& impl,
-      IO_Control_Command& command, asio::error_code& ec)
-  {
-    if (!is_open(impl))
-    {
-      ec = asio::error::bad_descriptor;
-      return ec;
-    }
-
-    socket_ops::ioctl(impl.socket_, command.name(),
-        static_cast<ioctl_arg_type*>(command.data()), ec);
-
-    if (!ec && command.name() == static_cast<int>(FIONBIO))
-    {
-      if (*static_cast<ioctl_arg_type*>(command.data()))
-        impl.flags_ |= implementation_type::user_set_non_blocking;
-      else
-        impl.flags_ &= ~implementation_type::user_set_non_blocking;
-    }
-
+    std::size_t size = option.size(impl.protocol_);
+    socket_ops::getsockopt(impl.socket_, impl.state_,
+        option.level(impl.protocol_), option.name(impl.protocol_),
+        option.data(impl.protocol_), &size, ec);
+    if (!ec)
+      option.resize(impl.protocol_, size);
     return ec;
   }
 
@@ -578,12 +205,6 @@ public:
   endpoint_type local_endpoint(const implementation_type& impl,
       asio::error_code& ec) const
   {
-    if (!is_open(impl))
-    {
-      ec = asio::error::bad_descriptor;
-      return endpoint_type();
-    }
-
     endpoint_type endpoint;
     std::size_t addr_len = endpoint.capacity();
     if (socket_ops::getsockname(impl.socket_, endpoint.data(), &addr_len, ec))
@@ -596,210 +217,13 @@ public:
   endpoint_type remote_endpoint(const implementation_type& impl,
       asio::error_code& ec) const
   {
-    if (!is_open(impl))
-    {
-      ec = asio::error::bad_descriptor;
+    endpoint_type endpoint = impl.remote_endpoint_;
+    std::size_t addr_len = endpoint.capacity();
+    if (socket_ops::getpeername(impl.socket_, endpoint.data(),
+          &addr_len, impl.have_remote_endpoint_, ec))
       return endpoint_type();
-    }
-
-    if (impl.socket_.have_remote_endpoint())
-    {
-      // Check if socket is still connected.
-      DWORD connect_time = 0;
-      size_t connect_time_len = sizeof(connect_time);
-      if (socket_ops::getsockopt(impl.socket_, SOL_SOCKET, SO_CONNECT_TIME,
-            &connect_time, &connect_time_len, ec) == socket_error_retval)
-      {
-        return endpoint_type();
-      }
-      if (connect_time == 0xFFFFFFFF)
-      {
-        ec = asio::error::not_connected;
-        return endpoint_type();
-      }
-
-      ec = asio::error_code();
-      return impl.socket_.remote_endpoint();
-    }
-    else
-    {
-      endpoint_type endpoint;
-      std::size_t addr_len = endpoint.capacity();
-      if (socket_ops::getpeername(impl.socket_, endpoint.data(), &addr_len, ec))
-        return endpoint_type();
-      endpoint.resize(addr_len);
-      return endpoint;
-    }
-  }
-
-  /// Disable sends or receives on the socket.
-  asio::error_code shutdown(implementation_type& impl,
-      socket_base::shutdown_type what, asio::error_code& ec)
-  {
-    if (!is_open(impl))
-    {
-      ec = asio::error::bad_descriptor;
-      return ec;
-    }
-
-    socket_ops::shutdown(impl.socket_, what, ec);
-    return ec;
-  }
-
-  // Send the given data to the peer. Returns the number of bytes sent.
-  template <typename ConstBufferSequence>
-  size_t send(implementation_type& impl, const ConstBufferSequence& buffers,
-      socket_base::message_flags flags, asio::error_code& ec)
-  {
-    if (!is_open(impl))
-    {
-      ec = asio::error::bad_descriptor;
-      return 0;
-    }
-
-    buffer_sequence_adapter<asio::const_buffer,
-        ConstBufferSequence> bufs(buffers);
-
-    // A request to receive 0 bytes on a stream socket is a no-op.
-    if (impl.protocol_.type() == SOCK_STREAM && bufs.all_empty())
-    {
-      ec = asio::error_code();
-      return 0;
-    }
-
-    // Send the data.
-    DWORD bytes_transferred = 0;
-    int result = ::WSASend(impl.socket_, bufs.buffers(),
-        bufs.count(), &bytes_transferred, flags, 0, 0);
-    if (result != 0)
-    {
-      DWORD last_error = ::WSAGetLastError();
-      if (last_error == ERROR_NETNAME_DELETED)
-        last_error = WSAECONNRESET;
-      else if (last_error == ERROR_PORT_UNREACHABLE)
-        last_error = WSAECONNREFUSED;
-      ec = asio::error_code(last_error,
-          asio::error::get_system_category());
-      return 0;
-    }
-
-    ec = asio::error_code();
-    return bytes_transferred;
-  }
-
-  // Wait until data can be sent without blocking.
-  size_t send(implementation_type& impl, const null_buffers&,
-      socket_base::message_flags, asio::error_code& ec)
-  {
-    if (!is_open(impl))
-    {
-      ec = asio::error::bad_descriptor;
-      return 0;
-    }
-
-    // Wait for socket to become ready.
-    socket_ops::poll_write(impl.socket_, ec);
-
-    return 0;
-  }
-
-  template <typename ConstBufferSequence, typename Handler>
-  class send_op : public operation
-  {
-  public:
-    send_op(weak_cancel_token_type cancel_token,
-        const ConstBufferSequence& buffers, Handler handler)
-      : operation(&send_op::do_complete),
-        cancel_token_(cancel_token),
-        buffers_(buffers),
-        handler_(handler)
-    {
-    }
-
-    static void do_complete(io_service_impl* owner, operation* base,
-        asio::error_code ec, std::size_t bytes_transferred)
-    {
-      // Take ownership of the operation object.
-      send_op* o(static_cast<send_op*>(base));
-      typedef handler_alloc_traits<Handler, send_op> alloc_traits;
-      handler_ptr<alloc_traits> ptr(o->handler_, o);
-
-      // Make the upcall if required.
-      if (owner)
-      {
-#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
-        // Check whether buffers are still valid.
-        buffer_sequence_adapter<asio::const_buffer,
-            ConstBufferSequence>::validate(o->buffers_);
-#endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING)
-
-        // Map non-portable errors to their portable counterparts.
-        if (ec.value() == ERROR_NETNAME_DELETED)
-        {
-          if (o->cancel_token_.expired())
-            ec = asio::error::operation_aborted;
-          else
-            ec = asio::error::connection_reset;
-        }
-        else if (ec.value() == ERROR_PORT_UNREACHABLE)
-        {
-          ec = asio::error::connection_refused;
-        }
-
-        // Make a copy of the handler so that the memory can be deallocated
-        // before the upcall is made. Even if we're not about to make an
-        // upcall, a sub-object of the handler may be the true owner of the
-        // memory associated with the handler. Consequently, a local copy of
-        // the handler is required to ensure that any owning sub-object remains
-        // valid until after we have deallocated the memory here.
-        detail::binder2<Handler, asio::error_code, std::size_t>
-          handler(o->handler_, ec, bytes_transferred);
-        ptr.reset();
-        asio::detail::fenced_block b;
-        asio_handler_invoke_helpers::invoke(handler, handler);
-      }
-    }
-
-  private:
-    weak_cancel_token_type cancel_token_;
-    ConstBufferSequence buffers_;
-    Handler handler_;
-  };
-
-  // Start an asynchronous send. The data being sent must be valid for the
-  // lifetime of the asynchronous operation.
-  template <typename ConstBufferSequence, typename Handler>
-  void async_send(implementation_type& impl, const ConstBufferSequence& buffers,
-      socket_base::message_flags flags, Handler handler)
-  {
-    // Allocate and construct an operation to wrap the handler.
-    typedef send_op<ConstBufferSequence, Handler> value_type;
-    typedef handler_alloc_traits<Handler, value_type> alloc_traits;
-    raw_handler_ptr<alloc_traits> raw_ptr(handler);
-    handler_ptr<alloc_traits> ptr(raw_ptr,
-        impl.cancel_token_, buffers, handler);
-
-    buffer_sequence_adapter<asio::const_buffer,
-        ConstBufferSequence> bufs(buffers);
-
-    start_send_op(impl, bufs.buffers(), bufs.count(), flags,
-        impl.protocol_.type() == SOCK_STREAM && bufs.all_empty(), ptr.get());
-    ptr.release();
-  }
-
-  // Start an asynchronous wait until data can be sent without blocking.
-  template <typename Handler>
-  void async_send(implementation_type& impl, const null_buffers&,
-      socket_base::message_flags, Handler handler)
-  {
-    // Allocate and construct an operation to wrap the handler.
-    typedef null_buffers_op<Handler> value_type;
-    typedef handler_alloc_traits<Handler, value_type> alloc_traits;
-    raw_handler_ptr<alloc_traits> raw_ptr(handler);
-    handler_ptr<alloc_traits> ptr(raw_ptr, handler);
-
-    start_reactor_op(impl, reactor::write_op, ptr.get());
-    ptr.release();
+    endpoint.resize(addr_len);
+    return endpoint;
   }
 
   // Send a datagram to the specified endpoint. Returns the number of bytes
@@ -809,107 +233,25 @@ public:
       const endpoint_type& destination, socket_base::message_flags flags,
       asio::error_code& ec)
   {
-    if (!is_open(impl))
-    {
-      ec = asio::error::bad_descriptor;
-      return 0;
-    }
-
     buffer_sequence_adapter<asio::const_buffer,
         ConstBufferSequence> bufs(buffers);
 
-    // Send the data.
-    DWORD bytes_transferred = 0;
-    int result = ::WSASendTo(impl.socket_, bufs.buffers(), bufs.count(),
-        &bytes_transferred, flags, destination.data(),
-        static_cast<int>(destination.size()), 0, 0);
-    if (result != 0)
-    {
-      DWORD last_error = ::WSAGetLastError();
-      if (last_error == ERROR_PORT_UNREACHABLE)
-        last_error = WSAECONNREFUSED;
-      ec = asio::error_code(last_error,
-          asio::error::get_system_category());
-      return 0;
-    }
-
-    ec = asio::error_code();
-    return bytes_transferred;
+    return socket_ops::sync_sendto(impl.socket_, impl.state_,
+        bufs.buffers(), bufs.count(), flags,
+        destination.data(), destination.size(), ec);
   }
 
   // Wait until data can be sent without blocking.
   size_t send_to(implementation_type& impl, const null_buffers&,
-      socket_base::message_flags, const endpoint_type&,
+      const endpoint_type&, socket_base::message_flags,
       asio::error_code& ec)
   {
-    if (!is_open(impl))
-    {
-      ec = asio::error::bad_descriptor;
-      return 0;
-    }
-
     // Wait for socket to become ready.
     socket_ops::poll_write(impl.socket_, ec);
 
     return 0;
   }
 
-  template <typename ConstBufferSequence, typename Handler>
-  class send_to_op : public operation
-  {
-  public:
-    send_to_op(weak_cancel_token_type cancel_token,
-        const ConstBufferSequence& buffers, Handler handler)
-      : operation(&send_to_op::do_complete),
-        cancel_token_(cancel_token),
-        buffers_(buffers),
-        handler_(handler)
-    {
-    }
-
-    static void do_complete(io_service_impl* owner, operation* base,
-        asio::error_code ec, std::size_t bytes_transferred)
-    {
-      // Take ownership of the operation object.
-      send_to_op* o(static_cast<send_to_op*>(base));
-      typedef handler_alloc_traits<Handler, send_to_op> alloc_traits;
-      handler_ptr<alloc_traits> ptr(o->handler_, o);
-
-      // Make the upcall if required.
-      if (owner)
-      {
-#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
-        // Check whether buffers are still valid.
-        buffer_sequence_adapter<asio::const_buffer,
-            ConstBufferSequence>::validate(o->buffers_);
-#endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING)
-
-        // Map non-portable errors to their portable counterparts.
-        if (ec.value() == ERROR_PORT_UNREACHABLE)
-        {
-          ec = asio::error::connection_refused;
-        }
-
-        // Make a copy of the handler so that the memory can be deallocated
-        // before the upcall is made. Even if we're not about to make an
-        // upcall, a sub-object of the handler may be the true owner of the
-        // memory associated with the handler. Consequently, a local copy of
-        // the handler is required to ensure that any owning sub-object remains
-        // valid until after we have deallocated the memory here.
-        detail::binder2<Handler, asio::error_code, std::size_t>
-          handler(o->handler_, ec, bytes_transferred);
-        ptr.reset();
-        asio::detail::fenced_block b;
-        asio_handler_invoke_helpers::invoke(handler, handler);
-      }
-    }
-
-  private:
-    weak_cancel_token_type cancel_token_;
-    ConstBufferSequence buffers_;
-    Handler handler_;
-  };
-
   // Start an asynchronous send. The data being sent must be valid for the
   // lifetime of the asynchronous operation.
   template <typename ConstBufferSequence, typename Handler>
@@ -918,233 +260,35 @@ public:
       socket_base::message_flags flags, Handler handler)
   {
     // Allocate and construct an operation to wrap the handler.
-    typedef send_to_op<ConstBufferSequence, Handler> value_type;
-    typedef handler_alloc_traits<Handler, value_type> alloc_traits;
-    raw_handler_ptr<alloc_traits> raw_ptr(handler);
-    handler_ptr<alloc_traits> ptr(raw_ptr,
-        impl.cancel_token_, buffers, handler);
+    typedef win_iocp_socket_send_op<ConstBufferSequence, Handler> op;
+    typename op::ptr p = { boost::addressof(handler),
+      asio_handler_alloc_helpers::allocate(
+        sizeof(op), handler), 0 };
+    p.p = new (p.v) op(impl.cancel_token_, buffers, handler);
 
     buffer_sequence_adapter<asio::const_buffer,
         ConstBufferSequence> bufs(buffers);
 
-    start_send_to_op(impl, bufs.buffers(),
-        bufs.count(), destination, flags, ptr.get());
-    ptr.release();
+    start_send_to_op(impl, bufs.buffers(), bufs.count(),
+        destination.data(), static_cast<int>(destination.size()),
+        flags, p.p);
+    p.v = p.p = 0;
   }
 
   // Start an asynchronous wait until data can be sent without blocking.
   template <typename Handler>
   void async_send_to(implementation_type& impl, const null_buffers&,
-      socket_base::message_flags, const endpoint_type&, Handler handler)
-  {
-    // Allocate and construct an operation to wrap the handler.
-    typedef null_buffers_op<Handler> value_type;
-    typedef handler_alloc_traits<Handler, value_type> alloc_traits;
-    raw_handler_ptr<alloc_traits> raw_ptr(handler);
-    handler_ptr<alloc_traits> ptr(raw_ptr, handler);
-
-    start_reactor_op(impl, reactor::write_op, ptr.get());
-    ptr.release();
-  }
-
-  // Receive some data from the peer. Returns the number of bytes received.
-  template <typename MutableBufferSequence>
-  size_t receive(implementation_type& impl,
-      const MutableBufferSequence& buffers,
-      socket_base::message_flags flags, asio::error_code& ec)
-  {
-    if (!is_open(impl))
-    {
-      ec = asio::error::bad_descriptor;
-      return 0;
-    }
-
-    buffer_sequence_adapter<asio::mutable_buffer,
-        MutableBufferSequence> bufs(buffers);
-
-    // A request to receive 0 bytes on a stream socket is a no-op.
-    if (impl.protocol_.type() == SOCK_STREAM && bufs.all_empty())
-    {
-      ec = asio::error_code();
-      return 0;
-    }
-
-    // Receive some data.
-    DWORD bytes_transferred = 0;
-    DWORD recv_flags = flags;
-    int result = ::WSARecv(impl.socket_, bufs.buffers(),
-        bufs.count(), &bytes_transferred, &recv_flags, 0, 0);
-    if (result != 0)
-    {
-      DWORD last_error = ::WSAGetLastError();
-      if (last_error == ERROR_NETNAME_DELETED)
-        last_error = WSAECONNRESET;
-      else if (last_error == ERROR_PORT_UNREACHABLE)
-        last_error = WSAECONNREFUSED;
-      ec = asio::error_code(last_error,
-          asio::error::get_system_category());
-      return 0;
-    }
-    if (bytes_transferred == 0 && impl.protocol_.type() == SOCK_STREAM)
-    {
-      ec = asio::error::eof;
-      return 0;
-    }
-
-    ec = asio::error_code();
-    return bytes_transferred;
-  }
-
-  // Wait until data can be received without blocking.
-  size_t receive(implementation_type& impl, const null_buffers&,
-      socket_base::message_flags, asio::error_code& ec)
-  {
-    if (!is_open(impl))
-    {
-      ec = asio::error::bad_descriptor;
-      return 0;
-    }
-
-    // Wait for socket to become ready.
-    socket_ops::poll_read(impl.socket_, ec);
-
-    return 0;
-  }
-
-  template <typename MutableBufferSequence, typename Handler>
-  class receive_op : public operation
-  {
-  public:
-    receive_op(int protocol_type, weak_cancel_token_type cancel_token,
-        const MutableBufferSequence& buffers, Handler handler)
-      : operation(&receive_op::do_complete),
-        protocol_type_(protocol_type),
-        cancel_token_(cancel_token),
-        buffers_(buffers),
-        handler_(handler)
-    {
-    }
-
-    static void do_complete(io_service_impl* owner, operation* base,
-        asio::error_code ec, std::size_t bytes_transferred)
-    {
-      // Take ownership of the operation object.
-      receive_op* o(static_cast<receive_op*>(base));
-      typedef handler_alloc_traits<Handler, receive_op> alloc_traits;
-      handler_ptr<alloc_traits> ptr(o->handler_, o);
-
-      // Make the upcall if required.
-      if (owner)
-      {
-#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
-        // Check whether buffers are still valid.
-        buffer_sequence_adapter<asio::mutable_buffer,
-            MutableBufferSequence>::validate(o->buffers_);
-#endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING)
-
-        // Map non-portable errors to their portable counterparts.
-        if (ec.value() == ERROR_NETNAME_DELETED)
-        {
-          if (o->cancel_token_.expired())
-            ec = asio::error::operation_aborted;
-          else
-            ec = asio::error::connection_reset;
-        }
-        else if (ec.value() == ERROR_PORT_UNREACHABLE)
-        {
-          ec = asio::error::connection_refused;
-        }
-
-        // Check for connection closed.
-        else if (!ec && bytes_transferred == 0
-            && o->protocol_type_ == SOCK_STREAM
-            && !buffer_sequence_adapter<asio::mutable_buffer,
-                MutableBufferSequence>::all_empty(o->buffers_)
-            && !boost::is_same<MutableBufferSequence, null_buffers>::value)
-        {
-          ec = asio::error::eof;
-        }
-
-        // Make a copy of the handler so that the memory can be deallocated
-        // before the upcall is made. Even if we're not about to make an
-        // upcall, a sub-object of the handler may be the true owner of the
-        // memory associated with the handler. Consequently, a local copy of
-        // the handler is required to ensure that any owning sub-object remains
-        // valid until after we have deallocated the memory here.
-        detail::binder2<Handler, asio::error_code, std::size_t>
-          handler(o->handler_, ec, bytes_transferred);
-        ptr.reset();
-        asio::detail::fenced_block b;
-        asio_handler_invoke_helpers::invoke(handler, handler);
-      }
-    }
-
-  private:
-    int protocol_type_;
-    weak_cancel_token_type cancel_token_;
-    MutableBufferSequence buffers_;
-    Handler handler_;
-  };
-
-  // Start an asynchronous receive. The buffer for the data being received
-  // must be valid for the lifetime of the asynchronous operation.
-  template <typename MutableBufferSequence, typename Handler>
-  void async_receive(implementation_type& impl,
-      const MutableBufferSequence& buffers,
-      socket_base::message_flags flags, Handler handler)
+      const endpoint_type&, socket_base::message_flags, Handler handler)
   {
     // Allocate and construct an operation to wrap the handler.
-    typedef receive_op<MutableBufferSequence, Handler> value_type;
-    typedef handler_alloc_traits<Handler, value_type> alloc_traits;
-    raw_handler_ptr<alloc_traits> raw_ptr(handler);
-    int protocol_type = impl.protocol_.type();
-    handler_ptr<alloc_traits> ptr(raw_ptr, protocol_type,
-        impl.cancel_token_, buffers, handler);
-
-    buffer_sequence_adapter<asio::mutable_buffer,
-        MutableBufferSequence> bufs(buffers);
+    typedef win_iocp_null_buffers_op<Handler> op;
+    typename op::ptr p = { boost::addressof(handler),
+      asio_handler_alloc_helpers::allocate(
+        sizeof(op), handler), 0 };
+    p.p = new (p.v) op(impl.cancel_token_, handler);
 
-    start_receive_op(impl, bufs.buffers(), bufs.count(), flags,
-        protocol_type == SOCK_STREAM && bufs.all_empty(), ptr.get());
-    ptr.release();
-  }
-
-  // Wait until data can be received without blocking.
-  template <typename Handler>
-  void async_receive(implementation_type& impl, const null_buffers& buffers,
-      socket_base::message_flags flags, Handler handler)
-  {
-    if (impl.protocol_.type() == SOCK_STREAM)
-    {
-      // For stream sockets on Windows, we may issue a 0-byte overlapped
-      // WSARecv to wait until there is data available on the socket.
-
-      // Allocate and construct an operation to wrap the handler.
-      typedef receive_op<null_buffers, Handler> value_type;
-      typedef handler_alloc_traits<Handler, value_type> alloc_traits;
-      raw_handler_ptr<alloc_traits> raw_ptr(handler);
-      int protocol_type = impl.protocol_.type();
-      handler_ptr<alloc_traits> ptr(raw_ptr, protocol_type,
-          impl.cancel_token_, buffers, handler);
-
-      ::WSABUF buf = { 0, 0 };
-      start_receive_op(impl, &buf, 1, flags, false, ptr.get());
-      ptr.release();
-    }
-    else
-    {
-      // Allocate and construct an operation to wrap the handler.
-      typedef null_buffers_op<Handler> value_type;
-      typedef handler_alloc_traits<Handler, value_type> alloc_traits;
-      raw_handler_ptr<alloc_traits> raw_ptr(handler);
-      handler_ptr<alloc_traits> ptr(raw_ptr, handler);
-
-      start_reactor_op(impl,
-          (flags & socket_base::message_out_of_band)
-            ? reactor::except_op : reactor::read_op,
-          ptr.get());
-      ptr.release();
-    }
+    start_reactor_op(impl, reactor::write_op, p.p);
+    p.v = p.p = 0;
   }
 
   // Receive a datagram with the endpoint of the sender. Returns the number of
@@ -1155,41 +299,18 @@ public:
       endpoint_type& sender_endpoint, socket_base::message_flags flags,
       asio::error_code& ec)
   {
-    if (!is_open(impl))
-    {
-      ec = asio::error::bad_descriptor;
-      return 0;
-    }
-
     buffer_sequence_adapter<asio::mutable_buffer,
         MutableBufferSequence> bufs(buffers);
 
-    // Receive some data.
-    DWORD bytes_transferred = 0;
-    DWORD recv_flags = flags;
-    int endpoint_size = static_cast<int>(sender_endpoint.capacity());
-    int result = ::WSARecvFrom(impl.socket_, bufs.buffers(),
-        bufs.count(), &bytes_transferred, &recv_flags,
-        sender_endpoint.data(), &endpoint_size, 0, 0);
-    if (result != 0)
-    {
-      DWORD last_error = ::WSAGetLastError();
-      if (last_error == ERROR_PORT_UNREACHABLE)
-        last_error = WSAECONNREFUSED;
-      ec = asio::error_code(last_error,
-          asio::error::get_system_category());
-      return 0;
-    }
-    if (bytes_transferred == 0 && impl.protocol_.type() == SOCK_STREAM)
-    {
-      ec = asio::error::eof;
-      return 0;
-    }
+    std::size_t addr_len = sender_endpoint.capacity();
+    std::size_t bytes_recvd = socket_ops::sync_recvfrom(
+        impl.socket_, impl.state_, bufs.buffers(), bufs.count(),
+        flags, sender_endpoint.data(), &addr_len, ec);
 
-    sender_endpoint.resize(static_cast<std::size_t>(endpoint_size));
+    if (!ec)
+      sender_endpoint.resize(addr_len);
 
-    ec = asio::error_code();
-    return bytes_transferred;
+    return bytes_recvd;
   }
 
   // Wait until data can be received without blocking.
@@ -1197,12 +318,6 @@ public:
       const null_buffers&, endpoint_type& sender_endpoint,
       socket_base::message_flags, asio::error_code& ec)
   {
-    if (!is_open(impl))
-    {
-      ec = asio::error::bad_descriptor;
-      return 0;
-    }
-
     // Wait for socket to become ready.
     socket_ops::poll_read(impl.socket_, ec);
 
@@ -1212,75 +327,6 @@ public:
     return 0;
   }
 
-  template <typename MutableBufferSequence, typename Handler>
-  class receive_from_op : public operation
-  {
-  public:
-    receive_from_op(int protocol_type, endpoint_type& endpoint,
-        const MutableBufferSequence& buffers, Handler handler)
-      : operation(&receive_from_op::do_complete),
-        protocol_type_(protocol_type),
-        endpoint_(endpoint),
-        endpoint_size_(static_cast<int>(endpoint.capacity())),
-        buffers_(buffers),
-        handler_(handler)
-    {
-    }
-
-    int& endpoint_size()
-    {
-      return endpoint_size_;
-    }
-
-    static void do_complete(io_service_impl* owner, operation* base,
-        asio::error_code ec, std::size_t bytes_transferred)
-    {
-      // Take ownership of the operation object.
-      receive_from_op* o(static_cast<receive_from_op*>(base));
-      typedef handler_alloc_traits<Handler, receive_from_op> alloc_traits;
-      handler_ptr<alloc_traits> ptr(o->handler_, o);
-
-      // Make the upcall if required.
-      if (owner)
-      {
-#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
-        // Check whether buffers are still valid.
-        buffer_sequence_adapter<asio::mutable_buffer,
-            MutableBufferSequence>::validate(o->buffers_);
-#endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING)
-
-        // Map non-portable errors to their portable counterparts.
-        if (ec.value() == ERROR_PORT_UNREACHABLE)
-        {
-          ec = asio::error::connection_refused;
-        }
-
-        // Record the size of the endpoint returned by the operation.
-        o->endpoint_.resize(o->endpoint_size_);
-
-        // Make a copy of the handler so that the memory can be deallocated
-        // before the upcall is made. Even if we're not about to make an
-        // upcall, a sub-object of the handler may be the true owner of the
-        // memory associated with the handler. Consequently, a local copy of
-        // the handler is required to ensure that any owning sub-object remains
-        // valid until after we have deallocated the memory here.
-        detail::binder2<Handler, asio::error_code, std::size_t>
-          handler(o->handler_, ec, bytes_transferred);
-        ptr.reset();
-        asio::detail::fenced_block b;
-        asio_handler_invoke_helpers::invoke(handler, handler);
-      }
-    }
-
-  private:
-    int protocol_type_;
-    endpoint_type& endpoint_;
-    int endpoint_size_;
-    weak_cancel_token_type cancel_token_;
-    MutableBufferSequence buffers_;
-    Handler handler_;
-  };
-
   // Start an asynchronous receive. The buffer for the data being received and
   // the sender_endpoint object must both be valid for the lifetime of the
   // asynchronous operation.
@@ -1290,19 +336,19 @@ public:
       socket_base::message_flags flags, Handler handler)
   {
     // Allocate and construct an operation to wrap the handler.
-    typedef receive_from_op<MutableBufferSequence, Handler> value_type;
-    typedef handler_alloc_traits<Handler, value_type> alloc_traits;
-    raw_handler_ptr<alloc_traits> raw_ptr(handler);
-    int protocol_type = impl.protocol_.type();
-    handler_ptr<alloc_traits> ptr(raw_ptr,
-        protocol_type, sender_endp, buffers, handler);
+    typedef win_iocp_socket_recvfrom_op<
+      MutableBufferSequence, endpoint_type, Handler> op;
+    typename op::ptr p = { boost::addressof(handler),
+      asio_handler_alloc_helpers::allocate(
+        sizeof(op), handler), 0 };
+    p.p = new (p.v) op(sender_endp, impl.cancel_token_, buffers, handler);
 
     buffer_sequence_adapter<asio::mutable_buffer,
         MutableBufferSequence> bufs(buffers);
 
     start_receive_from_op(impl, bufs.buffers(), bufs.count(),
-        sender_endp, flags, &ptr.get()->endpoint_size(), ptr.get());
-    ptr.release();
+        sender_endp.data(), flags, &p.p->endpoint_size(), p.p);
+    p.v = p.p = 0;
   }
 
   // Wait until data can be received without blocking.
@@ -1312,19 +358,17 @@ public:
       socket_base::message_flags flags, Handler handler)
   {
     // Allocate and construct an operation to wrap the handler.
-    typedef null_buffers_op<Handler> value_type;
-    typedef handler_alloc_traits<Handler, value_type> alloc_traits;
-    raw_handler_ptr<alloc_traits> raw_ptr(handler);
-    handler_ptr<alloc_traits> ptr(raw_ptr, handler);
+    typedef win_iocp_null_buffers_op<Handler> op;
+    typename op::ptr p = { boost::addressof(handler),
+      asio_handler_alloc_helpers::allocate(
+        sizeof(op), handler), 0 };
+    p.p = new (p.v) op(impl.cancel_token_, handler);
 
     // Reset endpoint since it can be given no sensible value at this time.
     sender_endpoint = endpoint_type();
 
-    start_reactor_op(impl,
-        (flags & socket_base::message_out_of_band)
-          ? reactor::except_op : reactor::read_op,
-        ptr.get());
-    ptr.release();
+    start_null_buffers_receive_op(impl, flags, p.p);
+    p.v = p.p = 0;
   }
 
   // Accept a new connection.
@@ -1332,12 +376,6 @@ public:
   asio::error_code accept(implementation_type& impl, Socket& peer,
       endpoint_type* peer_endpoint, asio::error_code& ec)
   {
-    if (!is_open(impl))
-    {
-      ec = asio::error::bad_descriptor;
-      return ec;
-    }
-
     // We cannot accept a socket that is already open.
     if (peer.is_open())
     {
@@ -1345,222 +383,22 @@ public:
       return ec;
     }
 
-    for (;;)
-    {
-      socket_holder new_socket;
-      std::size_t addr_len = 0;
-      if (peer_endpoint)
-      {
-        addr_len = peer_endpoint->capacity();
-        new_socket.reset(socket_ops::accept(impl.socket_,
-              peer_endpoint->data(), &addr_len, ec));
-      }
-      else
-      {
-        new_socket.reset(socket_ops::accept(impl.socket_, 0, 0, ec));
-      }
-
-      if (ec)
-      {
-        if (ec == asio::error::connection_aborted
-            && !(impl.flags_ & implementation_type::enable_connection_aborted))
-        {
-          // Retry accept operation.
-          continue;
-        }
-        else
-        {
-          return ec;
-        }
-      }
+    std::size_t addr_len = peer_endpoint ? peer_endpoint->capacity() : 0;
+    socket_holder new_socket(socket_ops::sync_accept(impl.socket_,
+          impl.state_, peer_endpoint ? peer_endpoint->data() : 0,
+          peer_endpoint ? &addr_len : 0, ec));
 
+    // On success, assign new connection to peer socket object.
+    if (new_socket.get() >= 0)
+    {
       if (peer_endpoint)
         peer_endpoint->resize(addr_len);
-
-      peer.assign(impl.protocol_, new_socket.get(), ec);
-      if (!ec)
+      if (!peer.assign(impl.protocol_, new_socket.get(), ec))
         new_socket.release();
-      return ec;
-    }
-  }
-
-  template <typename Socket, typename Handler>
-  class accept_op : public operation
-  {
-  public:
-    accept_op(win_iocp_io_service& iocp_service, socket_type socket,
-        Socket& peer, const protocol_type& protocol,
-        endpoint_type* peer_endpoint, bool enable_connection_aborted,
-        Handler handler)
-      : operation(&accept_op::do_complete),
-        iocp_service_(iocp_service),
-        socket_(socket),
-        peer_(peer),
-        protocol_(protocol),
-        peer_endpoint_(peer_endpoint),
-        enable_connection_aborted_(enable_connection_aborted),
-        handler_(handler)
-    {
     }
 
-    socket_holder& new_socket()
-    {
-      return new_socket_;
-    }
-
-    void* output_buffer()
-    {
-      return output_buffer_;
-    }
-
-    DWORD address_length()
-    {
-      return sizeof(sockaddr_storage_type) + 16;
-    }
-
-    static void do_complete(io_service_impl* owner, operation* base,
-        asio::error_code ec, std::size_t /*bytes_transferred*/)
-    {
-      // Take ownership of the handler object.
-      accept_op* o(static_cast<accept_op*>(base));
-      typedef handler_alloc_traits<Handler, accept_op> alloc_traits;
-      handler_ptr<alloc_traits> ptr(o->handler_, o);
-
-      // Make the upcall if required.
-      if (owner)
-      {
-        // Map Windows error ERROR_NETNAME_DELETED to connection_aborted.
-        if (ec.value() == ERROR_NETNAME_DELETED)
-        {
-          ec = asio::error::connection_aborted;
-        }
-
-        // Restart the accept operation if we got the connection_aborted error
-        // and the enable_connection_aborted socket option is not set.
-        if (ec == asio::error::connection_aborted
-            && !o->enable_connection_aborted_)
-        {
-          // Reset OVERLAPPED structure.
-          o->reset();
-
-          // Create a new socket for the next connection, since the AcceptEx
-          // call fails with WSAEINVAL if we try to reuse the same socket.
-          o->new_socket_.reset();
-          o->new_socket_.reset(socket_ops::socket(o->protocol_.family(),
-                o->protocol_.type(), o->protocol_.protocol(), ec));
-          if (o->new_socket_.get() != invalid_socket)
-          {
-            // Accept a connection.
-            DWORD bytes_read = 0;
-            BOOL result = ::AcceptEx(o->socket_, o->new_socket_.get(),
-                o->output_buffer(), 0, o->address_length(),
-                o->address_length(), &bytes_read, o);
-            DWORD last_error = ::WSAGetLastError();
-            ec = asio::error_code(last_error,
-                asio::error::get_system_category());
-
-            // Check if the operation completed immediately.
-            if (!result && last_error != WSA_IO_PENDING)
-            {
-              if (last_error == ERROR_NETNAME_DELETED
-                  || last_error == WSAECONNABORTED)
-              {
-                // Post this handler so that operation will be restarted again.
-                o->iocp_service_.work_started();
-                o->iocp_service_.on_completion(o, ec);
-                ptr.release();
-                return;
-              }
-              else
-              {
-                // Operation already complete. Continue with rest of this
-                // handler.
-              }
-            }
-            else
-            {
-              // Asynchronous operation has been successfully restarted.
-              o->iocp_service_.work_started();
-              o->iocp_service_.on_pending(o);
-              ptr.release();
-              return;
-            }
-          }
-        }
-
-        // Get the address of the peer.
-        endpoint_type peer_endpoint;
-        if (!ec)
-        {
-          LPSOCKADDR local_addr = 0;
-          int local_addr_length = 0;
-          LPSOCKADDR remote_addr = 0;
-          int remote_addr_length = 0;
-          GetAcceptExSockaddrs(o->output_buffer(), 0, o->address_length(),
-              o->address_length(), &local_addr, &local_addr_length,
-              &remote_addr, &remote_addr_length);
-          if (static_cast<std::size_t>(remote_addr_length)
-              > peer_endpoint.capacity())
-          {
-            ec = asio::error::invalid_argument;
-          }
-          else
-          {
-            using namespace std; // For memcpy.
-            memcpy(peer_endpoint.data(), remote_addr, remote_addr_length);
-            peer_endpoint.resize(static_cast<std::size_t>(remote_addr_length));
-          }
-        }
-
-        // Need to set the SO_UPDATE_ACCEPT_CONTEXT option so that getsockname
-        // and getpeername will work on the accepted socket.
-        if (!ec)
-        {
-          SOCKET update_ctx_param = o->socket_;
-          socket_ops::setsockopt(o->new_socket_.get(),
-                SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT,
-                &update_ctx_param, sizeof(SOCKET), ec);
-        }
-
-        // If the socket was successfully accepted, transfer ownership of the
-        // socket to the peer object.
-        if (!ec)
-        {
-          o->peer_.assign(o->protocol_,
-              native_type(o->new_socket_.get(), peer_endpoint), ec);
-          if (!ec)
-            o->new_socket_.release();
-        }
-
-        // Pass endpoint back to caller.
-        if (o->peer_endpoint_)
-          *o->peer_endpoint_ = peer_endpoint;
-
-        // Make a copy of the handler so that the memory can be deallocated
-        // before the upcall is made. Even if we're not about to make an
-        // upcall, a sub-object of the handler may be the true owner of the
-        // memory associated with the handler. Consequently, a local copy of
-        // the handler is required to ensure that any owning sub-object remains
-        // valid until after we have deallocated the memory here.
-        detail::binder1<Handler, asio::error_code>
-          handler(o->handler_, ec);
-        ptr.reset();
-        asio::detail::fenced_block b;
-        asio_handler_invoke_helpers::invoke(handler, handler);
-      }
-    }
-
-  private:
-    win_iocp_io_service& iocp_service_;
-    socket_type socket_;
-    socket_holder new_socket_;
-    Socket& peer_;
-    protocol_type protocol_;
-    endpoint_type* peer_endpoint_;
-    unsigned char output_buffer_[(sizeof(sockaddr_storage_type) + 16) * 2];
-    bool enable_connection_aborted_;
-    Handler handler_;
-  };
+    return ec;
+  }
 
   // Start an asynchronous accept. The peer and peer_endpoint objects
   // must be valid until the accept's handler is invoked.
@@ -1569,442 +407,54 @@ public:
       endpoint_type* peer_endpoint, Handler handler)
   {
     // Allocate and construct an operation to wrap the handler.
-    typedef accept_op<Socket, Handler> value_type;
-    typedef handler_alloc_traits<Handler, value_type> alloc_traits;
-    raw_handler_ptr<alloc_traits> raw_ptr(handler);
+    typedef win_iocp_socket_accept_op<Socket, protocol_type, Handler> op;
+    typename op::ptr p = { boost::addressof(handler),
+      asio_handler_alloc_helpers::allocate(
+        sizeof(op), handler), 0 };
     bool enable_connection_aborted =
-      (impl.flags_ & implementation_type::enable_connection_aborted);
-    handler_ptr<alloc_traits> ptr(raw_ptr, iocp_service_, impl.socket_, peer,
-        impl.protocol_, peer_endpoint, enable_connection_aborted, handler);
+      (impl.state_ & socket_ops::enable_connection_aborted) != 0;
+    p.p = new (p.v) op(*this, impl.socket_, peer, impl.protocol_,
+        peer_endpoint, enable_connection_aborted, handler);
 
-    start_accept_op(impl, peer.is_open(), ptr.get()->new_socket(),
-        ptr.get()->output_buffer(), ptr.get()->address_length(), ptr.get());
-    ptr.release();
+    start_accept_op(impl, peer.is_open(), p.p->new_socket(),
+        impl.protocol_.family(), impl.protocol_.type(),
+        impl.protocol_.protocol(), p.p->output_buffer(),
+        p.p->address_length(), p.p);
+    p.v = p.p = 0;
   }
 
   // Connect the socket to the specified endpoint.
   asio::error_code connect(implementation_type& impl,
       const endpoint_type& peer_endpoint, asio::error_code& ec)
   {
-    if (!is_open(impl))
-    {
-      ec = asio::error::bad_descriptor;
-      return ec;
-    }
-
-    // Perform the connect operation.
-    socket_ops::connect(impl.socket_,
+    socket_ops::sync_connect(impl.socket_,
         peer_endpoint.data(), peer_endpoint.size(), ec);
     return ec;
   }
 
-  class connect_op_base : public reactor_op
-  {
-  public:
-    connect_op_base(socket_type socket, func_type complete_func)
-      : reactor_op(&connect_op_base::do_perform, complete_func),
-        socket_(socket)
-    {
-    }
-
-    static bool do_perform(reactor_op* base)
-    {
-      connect_op_base* o(static_cast<connect_op_base*>(base));
-
-      // Get the error code from the connect operation.
-      int connect_error = 0;
-      size_t connect_error_len = sizeof(connect_error);
-      if (socket_ops::getsockopt(o->socket_, SOL_SOCKET, SO_ERROR,
-            &connect_error, &connect_error_len, o->ec_) == socket_error_retval)
-        return true;
-
-      // The connection failed so the handler will be posted with an error code.
-      if (connect_error)
-      {
-        o->ec_ = asio::error_code(connect_error,
-            asio::error::get_system_category());
-      }
-
-      return true;
-    }
-
-  private:
-    socket_type socket_;
-  };
-
-  template <typename Handler>
-  class connect_op : public connect_op_base
-  {
-  public:
-    connect_op(socket_type socket, Handler handler)
-      : connect_op_base(socket, &connect_op::do_complete),
-        handler_(handler)
-    {
-    }
-
-    static void do_complete(io_service_impl* owner, operation* base,
-        asio::error_code /*ec*/, std::size_t /*bytes_transferred*/)
-    {
-      // Take ownership of the handler object.
-      connect_op* o(static_cast<connect_op*>(base));
-      typedef handler_alloc_traits<Handler, connect_op> alloc_traits;
-      handler_ptr<alloc_traits> ptr(o->handler_, o);
-
-      // Make the upcall if required.
-      if (owner)
-      {
-        // Make a copy of the handler so that the memory can be deallocated
-        // before the upcall is made. Even if we're not about to make an
-        // upcall, a sub-object of the handler may be the true owner of the
-        // memory associated with the handler. Consequently, a local copy of
-        // the handler is required to ensure that any owning sub-object remains
-        // valid until after we have deallocated the memory here.
-        detail::binder1<Handler, asio::error_code>
-          handler(o->handler_, o->ec_);
-        ptr.reset();
-        asio::detail::fenced_block b;
-        asio_handler_invoke_helpers::invoke(handler, handler);
-      }
-    }
-
-  private:
-    Handler handler_;
-  };
-
   // Start an asynchronous connect.
   template <typename Handler>
   void async_connect(implementation_type& impl,
       const endpoint_type& peer_endpoint, Handler handler)
   {
     // Allocate and construct an operation to wrap the handler.
-    typedef connect_op<Handler> value_type;
-    typedef handler_alloc_traits<Handler, value_type> alloc_traits;
-    raw_handler_ptr<alloc_traits> raw_ptr(handler);
-    handler_ptr<alloc_traits> ptr(raw_ptr, impl.socket_, handler);
-
-    start_connect_op(impl, ptr.get(), peer_endpoint);
-    ptr.release();
-  }
-
-private:
-  // Helper function to start an asynchronous send operation.
-  void start_send_op(implementation_type& impl, WSABUF* buffers,
-      std::size_t buffer_count, socket_base::message_flags flags,
-      bool noop, operation* op)
-  {
-    update_cancellation_thread_id(impl);
-    iocp_service_.work_started();
-
-    if (noop)
-      iocp_service_.on_completion(op);
-    else if (!is_open(impl))
-      iocp_service_.on_completion(op, asio::error::bad_descriptor);
-    else
-    {
-      DWORD bytes_transferred = 0;
-      int result = ::WSASend(impl.socket_, buffers,
-          buffer_count, &bytes_transferred, flags, op, 0);
-      DWORD last_error = ::WSAGetLastError();
-      if (last_error == ERROR_PORT_UNREACHABLE)
-        last_error = WSAECONNREFUSED;
-      if (result != 0 && last_error != WSA_IO_PENDING)
-        iocp_service_.on_completion(op, last_error, bytes_transferred);
-      else
-        iocp_service_.on_pending(op);
-    }
-  }
-
-  // Helper function to start an asynchronous send_to operation.
-  void start_send_to_op(implementation_type& impl, WSABUF* buffers,
-      std::size_t buffer_count, const endpoint_type& destination,
-      socket_base::message_flags flags, operation* op)
-  {
-    update_cancellation_thread_id(impl);
-    iocp_service_.work_started();
+    typedef reactive_socket_connect_op<Handler> op;
+    typename op::ptr p = { boost::addressof(handler),
+      asio_handler_alloc_helpers::allocate(
+        sizeof(op), handler), 0 };
+    p.p = new (p.v) op(impl.socket_, handler);
 
-    if (!is_open(impl))
-      iocp_service_.on_completion(op, asio::error::bad_descriptor);
-    else
-    {
-      DWORD bytes_transferred = 0;
-      int result = ::WSASendTo(impl.socket_, buffers, buffer_count,
-          &bytes_transferred, flags, destination.data(),
-          static_cast<int>(destination.size()), op, 0);
-      DWORD last_error = ::WSAGetLastError();
-      if (last_error == ERROR_PORT_UNREACHABLE)
-        last_error = WSAECONNREFUSED;
-      if (result != 0 && last_error != WSA_IO_PENDING)
-        iocp_service_.on_completion(op, last_error, bytes_transferred);
-      else
-        iocp_service_.on_pending(op);
-    }
+    start_connect_op(impl, p.p, peer_endpoint.data(),
+        static_cast<int>(peer_endpoint.size()));
+    p.v = p.p = 0;
   }
-
-  // Helper function to start an asynchronous receive operation.
-  void start_receive_op(implementation_type& impl, WSABUF* buffers,
-      std::size_t buffer_count, socket_base::message_flags flags,
-      bool noop, operation* op)
-  {
-    update_cancellation_thread_id(impl);
-    iocp_service_.work_started();
-
-    if (noop)
-      iocp_service_.on_completion(op);
-    else if (!is_open(impl))
-      iocp_service_.on_completion(op, asio::error::bad_descriptor);
-    else
-    {
-      DWORD bytes_transferred = 0;
-      DWORD recv_flags = flags;
-      int result = ::WSARecv(impl.socket_, buffers, buffer_count,
-          &bytes_transferred, &recv_flags, op, 0);
-      DWORD last_error = ::WSAGetLastError();
-      if (last_error == ERROR_NETNAME_DELETED)
-        last_error = WSAECONNRESET;
-      else if (last_error == ERROR_PORT_UNREACHABLE)
-        last_error = WSAECONNREFUSED;
-      if (result != 0 && last_error != WSA_IO_PENDING)
-        iocp_service_.on_completion(op, last_error, bytes_transferred);
-      else
-        iocp_service_.on_pending(op);
-    }
-  }
-
-  // Helper function to start an asynchronous receive_from operation.
-  void start_receive_from_op(implementation_type& impl, WSABUF* buffers,
-      std::size_t buffer_count, endpoint_type& sender_endpoint,
-      socket_base::message_flags flags, int* endpoint_size, operation* op)
-  {
-    update_cancellation_thread_id(impl);
-    iocp_service_.work_started();
-
-    if (!is_open(impl))
-      iocp_service_.on_completion(op, asio::error::bad_descriptor);
-    else
-    {
-      DWORD bytes_transferred = 0;
-      DWORD recv_flags = flags;
-      int result = ::WSARecvFrom(impl.socket_, buffers,
-          buffer_count, &bytes_transferred, &recv_flags,
-          sender_endpoint.data(), endpoint_size, op, 0);
-      DWORD last_error = ::WSAGetLastError();
-      if (last_error == ERROR_PORT_UNREACHABLE)
-        last_error = WSAECONNREFUSED;
-      if (result != 0 && last_error != WSA_IO_PENDING)
-        iocp_service_.on_completion(op, last_error, bytes_transferred);
-      else
-        iocp_service_.on_pending(op);
-    }
-  }
-
-  // Helper function to start an asynchronous receive_from operation.
-  void start_accept_op(implementation_type& impl,
-      bool peer_is_open, socket_holder& new_socket,
-      void* output_buffer, DWORD address_length, operation* op)
-  {
-    update_cancellation_thread_id(impl);
-    iocp_service_.work_started();
-
-    if (!is_open(impl))
-      iocp_service_.on_completion(op, asio::error::bad_descriptor);
-    else if (peer_is_open)
-      iocp_service_.on_completion(op, asio::error::already_open);
-    else
-    {
-      asio::error_code ec;
-      new_socket.reset(socket_ops::socket(impl.protocol_.family(),
-            impl.protocol_.type(), impl.protocol_.protocol(), ec));
-      if (new_socket.get() == invalid_socket)
-        iocp_service_.on_completion(op, ec);
-      else
-      {
-        DWORD bytes_read = 0;
-        BOOL result = ::AcceptEx(impl.socket_, new_socket.get(), output_buffer,
-            0, address_length, address_length, &bytes_read, op);
-        DWORD last_error = ::WSAGetLastError();
-        if (!result && last_error != WSA_IO_PENDING)
-          iocp_service_.on_completion(op, last_error);
-        else
-          iocp_service_.on_pending(op);
-      }
-    }
-  }
-
-  // Start an asynchronous read or write operation using the the reactor.
-  void start_reactor_op(implementation_type& impl, int op_type, reactor_op* op)
-  {
-    reactor& r = get_reactor();
-    update_cancellation_thread_id(impl);
-
-    if (is_open(impl))
-    {
-      r.start_op(op_type, impl.socket_, impl.reactor_data_, op, false);
-      return;
-    }
-    else
-      op->ec_ = asio::error::bad_descriptor;
-
-    iocp_service_.post_immediate_completion(op);
-  }
-
-  // Start the asynchronous connect operation using the reactor.
-  void start_connect_op(implementation_type& impl,
-      reactor_op* op, const endpoint_type& peer_endpoint)
-  {
-    reactor& r = get_reactor();
-    update_cancellation_thread_id(impl);
-
-    if (is_open(impl))
-    {
-      ioctl_arg_type non_blocking = 1;
-      if (!socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, op->ec_))
-      {
-        if (socket_ops::connect(impl.socket_, peer_endpoint.data(),
-              peer_endpoint.size(), op->ec_) != 0)
-        {
-          if (!op->ec_
-              && !(impl.flags_ & implementation_type::user_set_non_blocking))
-          {
-            non_blocking = 0;
-            socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, op->ec_);
-          }
-
-          if (op->ec_ == asio::error::in_progress
-              || op->ec_ == asio::error::would_block)
-          {
-            op->ec_ = asio::error_code();
-            r.start_op(reactor::connect_op, impl.socket_,
-                impl.reactor_data_, op, true);
-            return;
-          }
-        }
-      }
-    }
-    else
-      op->ec_ = asio::error::bad_descriptor;
-
-    iocp_service_.post_immediate_completion(op);
-  }
-
-  // Helper function to close a socket when the associated object is being
-  // destroyed.
-  void close_for_destruction(implementation_type& impl)
-  {
-    if (is_open(impl))
-    {
-      // Check if the reactor was created, in which case we need to close the
-      // socket on the reactor as well to cancel any operations that might be
-      // running there.
-      reactor* r = static_cast<reactor*>(
-            interlocked_compare_exchange_pointer(
-              reinterpret_cast<void**>(&reactor_), 0, 0));
-      if (r)
-        r->close_descriptor(impl.socket_, impl.reactor_data_);
-
-      // The socket destructor must not block. If the user has changed the
-      // linger option to block in the foreground, we will change it back to the
-      // default so that the closure is performed in the background.
-      if (impl.flags_ & implementation_type::close_might_block)
-      {
-        ::linger opt;
-        opt.l_onoff = 0;
-        opt.l_linger = 0;
-        asio::error_code ignored_ec;
-        socket_ops::setsockopt(impl.socket_,
-            SOL_SOCKET, SO_LINGER, &opt, sizeof(opt), ignored_ec);
-      }
-
-      asio::error_code ignored_ec;
-      socket_ops::close(impl.socket_, ignored_ec);
-      impl.socket_ = invalid_socket;
-      impl.flags_ = 0;
-      impl.cancel_token_.reset();
-#if defined(ASIO_ENABLE_CANCELIO)
-      impl.safe_cancellation_thread_id_ = 0;
-#endif // defined(ASIO_ENABLE_CANCELIO)
-    }
-  }
-
-  // Update the ID of the thread from which cancellation is safe.
-  void update_cancellation_thread_id(implementation_type& impl)
-  {
-#if defined(ASIO_ENABLE_CANCELIO)
-    if (impl.safe_cancellation_thread_id_ == 0)
-      impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId();
-    else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId())
-      impl.safe_cancellation_thread_id_ = ~DWORD(0);
-#else // defined(ASIO_ENABLE_CANCELIO)
-    (void)impl;
-#endif // defined(ASIO_ENABLE_CANCELIO)
-  }
-
-  // Helper function to get the reactor. If no reactor has been created yet, a
-  // new one is obtained from the io_service and a pointer to it is cached in
-  // this service.
-  reactor& get_reactor()
-  {
-    reactor* r = static_cast<reactor*>(
-          interlocked_compare_exchange_pointer(
-            reinterpret_cast<void**>(&reactor_), 0, 0));
-    if (!r)
-    {
-      r = &(use_service<reactor>(io_service_));
-      interlocked_exchange_pointer(reinterpret_cast<void**>(&reactor_), r);
-    }
-    return *r;
-  }
-
-  // Helper function to emulate InterlockedCompareExchangePointer functionality
-  // for:
-  // - very old Platform SDKs; and
-  // - platform SDKs where MSVC's /Wp64 option causes spurious warnings.
-  void* interlocked_compare_exchange_pointer(void** dest, void* exch, void* cmp)
-  {
-#if defined(_M_IX86)
-    return reinterpret_cast<void*>(InterlockedCompareExchange(
-          reinterpret_cast<PLONG>(dest), reinterpret_cast<LONG>(exch),
-          reinterpret_cast<LONG>(cmp)));
-#else
-    return InterlockedCompareExchangePointer(dest, exch, cmp);
-#endif
-  }
-
-  // Helper function to emulate InterlockedExchangePointer functionality for:
-  // - very old Platform SDKs; and
-  // - platform SDKs where MSVC's /Wp64 option causes spurious warnings.
-  void* interlocked_exchange_pointer(void** dest, void* val)
-  {
-#if defined(_M_IX86)
-    return reinterpret_cast<void*>(InterlockedExchange(
-          reinterpret_cast<PLONG>(dest), reinterpret_cast<LONG>(val)));
-#else
-    return InterlockedExchangePointer(dest, val);
-#endif
-  }
-
-  // The io_service used to obtain the reactor, if required.
-  asio::io_service& io_service_;
-
-  // The IOCP service used for running asynchronous operations and dispatching
-  // handlers.
-  win_iocp_io_service& iocp_service_;
-
-  // The reactor used for performing connect operations. This object is created
-  // only if needed.
-  reactor* reactor_;
-
-  // Mutex to protect access to the linked list of implementations. 
-  asio::detail::mutex mutex_;
-
-  // The head of a linked list of all implementations.
-  implementation_type* impl_list_;
 };
 
 } // namespace detail
 } // namespace asio
 
-#endif // defined(ASIO_HAS_IOCP)
-
 #include "asio/detail/pop_options.hpp"
 
+#endif // defined(ASIO_HAS_IOCP)
+
 #endif // ASIO_DETAIL_WIN_IOCP_SOCKET_SERVICE_HPP
diff --git a/ext/asio/asio/detail/win_iocp_socket_service_base.hpp b/ext/asio/asio/detail/win_iocp_socket_service_base.hpp
new file mode 100644
index 0000000..62010b3
--- /dev/null
+++ b/ext/asio/asio/detail/win_iocp_socket_service_base.hpp
@@ -0,0 +1,385 @@
+//
+// detail/win_iocp_socket_service_base.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_DETAIL_WIN_IOCP_SOCKET_SERVICE_BASE_HPP
+#define ASIO_DETAIL_WIN_IOCP_SOCKET_SERVICE_BASE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(ASIO_HAS_IOCP)
+
+#include <boost/type_traits/is_same.hpp>
+#include <boost/utility/addressof.hpp>
+#include "asio/error.hpp"
+#include "asio/io_service.hpp"
+#include "asio/socket_base.hpp"
+#include "asio/detail/bind_handler.hpp"
+#include "asio/detail/buffer_sequence_adapter.hpp"
+#include "asio/detail/fenced_block.hpp"
+#include "asio/detail/handler_alloc_helpers.hpp"
+#include "asio/detail/handler_invoke_helpers.hpp"
+#include "asio/detail/mutex.hpp"
+#include "asio/detail/operation.hpp"
+#include "asio/detail/reactor.hpp"
+#include "asio/detail/reactor_op.hpp"
+#include "asio/detail/socket_holder.hpp"
+#include "asio/detail/socket_ops.hpp"
+#include "asio/detail/socket_types.hpp"
+#include "asio/detail/win_iocp_io_service.hpp"
+#include "asio/detail/win_iocp_null_buffers_op.hpp"
+#include "asio/detail/win_iocp_socket_send_op.hpp"
+#include "asio/detail/win_iocp_socket_recv_op.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+class win_iocp_socket_service_base
+{
+public:
+  // The implementation type of the socket.
+  struct base_implementation_type
+  {
+    // The native socket representation.
+    socket_type socket_;
+
+    // The current state of the socket.
+    socket_ops::state_type state_;
+
+    // We use a shared pointer as a cancellation token here to work around the
+    // broken Windows support for cancellation. MSDN says that when you call
+    // closesocket any outstanding WSARecv or WSASend operations will complete
+    // with the error ERROR_OPERATION_ABORTED. In practice they complete with
+    // ERROR_NETNAME_DELETED, which means you can't tell the difference between
+    // a local cancellation and the socket being hard-closed by the peer.
+    socket_ops::shared_cancel_token_type cancel_token_;
+
+    // Per-descriptor data used by the reactor.
+    reactor::per_descriptor_data reactor_data_;
+
+#if defined(ASIO_ENABLE_CANCELIO)
+    // The ID of the thread from which it is safe to cancel asynchronous
+    // operations. 0 means no asynchronous operations have been started yet.
+    // ~0 means asynchronous operations have been started from more than one
+    // thread, and cancellation is not supported for the socket.
+    DWORD safe_cancellation_thread_id_;
+#endif // defined(ASIO_ENABLE_CANCELIO)
+
+    // Pointers to adjacent socket implementations in linked list.
+    base_implementation_type* next_;
+    base_implementation_type* prev_;
+  };
+
+  // Constructor.
+  ASIO_DECL win_iocp_socket_service_base(
+      asio::io_service& io_service);
+
+  // Destroy all user-defined handler objects owned by the service.
+  ASIO_DECL void shutdown_service();
+
+  // Construct a new socket implementation.
+  ASIO_DECL void construct(base_implementation_type& impl);
+
+  // Destroy a socket implementation.
+  ASIO_DECL void destroy(base_implementation_type& impl);
+
+  // Determine whether the socket is open.
+  bool is_open(const base_implementation_type& impl) const
+  {
+    return impl.socket_ != invalid_socket;
+  }
+
+  // Destroy a socket implementation.
+  ASIO_DECL asio::error_code close(
+      base_implementation_type& impl, asio::error_code& ec);
+
+  // Cancel all operations associated with the socket.
+  ASIO_DECL asio::error_code cancel(
+      base_implementation_type& impl, asio::error_code& ec);
+
+  // Determine whether the socket is at the out-of-band data mark.
+  bool at_mark(const base_implementation_type& impl,
+      asio::error_code& ec) const
+  {
+    return socket_ops::sockatmark(impl.socket_, ec);
+  }
+
+  // Determine the number of bytes available for reading.
+  std::size_t available(const base_implementation_type& impl,
+      asio::error_code& ec) const
+  {
+    return socket_ops::available(impl.socket_, ec);
+  }
+
+  // Place the socket into the state where it will listen for new connections.
+  asio::error_code listen(base_implementation_type& impl,
+      int backlog, asio::error_code& ec)
+  {
+    socket_ops::listen(impl.socket_, backlog, ec);
+    return ec;
+  }
+
+  // Perform an IO control command on the socket.
+  template <typename IO_Control_Command>
+  asio::error_code io_control(base_implementation_type& impl,
+      IO_Control_Command& command, asio::error_code& ec)
+  {
+    socket_ops::ioctl(impl.socket_, impl.state_, command.name(),
+        static_cast<ioctl_arg_type*>(command.data()), ec);
+    return ec;
+  }
+
+  /// Disable sends or receives on the socket.
+  asio::error_code shutdown(base_implementation_type& impl,
+      socket_base::shutdown_type what, asio::error_code& ec)
+  {
+    socket_ops::shutdown(impl.socket_, what, ec);
+    return ec;
+  }
+
+  // Send the given data to the peer. Returns the number of bytes sent.
+  template <typename ConstBufferSequence>
+  size_t send(base_implementation_type& impl,
+      const ConstBufferSequence& buffers,
+      socket_base::message_flags flags, asio::error_code& ec)
+  {
+    buffer_sequence_adapter<asio::const_buffer,
+        ConstBufferSequence> bufs(buffers);
+
+    return socket_ops::sync_send(impl.socket_, impl.state_,
+        bufs.buffers(), bufs.count(), flags, bufs.all_empty(), ec);
+  }
+
+  // Wait until data can be sent without blocking.
+  size_t send(base_implementation_type& impl, const null_buffers&,
+      socket_base::message_flags, asio::error_code& ec)
+  {
+    // Wait for socket to become ready.
+    socket_ops::poll_write(impl.socket_, ec);
+
+    return 0;
+  }
+
+  // Start an asynchronous send. The data being sent must be valid for the
+  // lifetime of the asynchronous operation.
+  template <typename ConstBufferSequence, typename Handler>
+  void async_send(base_implementation_type& impl,
+      const ConstBufferSequence& buffers,
+      socket_base::message_flags flags, Handler handler)
+  {
+    // Allocate and construct an operation to wrap the handler.
+    typedef win_iocp_socket_send_op<ConstBufferSequence, Handler> op;
+    typename op::ptr p = { boost::addressof(handler),
+      asio_handler_alloc_helpers::allocate(
+        sizeof(op), handler), 0 };
+    p.p = new (p.v) op(impl.cancel_token_, buffers, handler);
+
+    buffer_sequence_adapter<asio::const_buffer,
+        ConstBufferSequence> bufs(buffers);
+
+    start_send_op(impl, bufs.buffers(), bufs.count(), flags,
+        (impl.state_ & socket_ops::stream_oriented) != 0 && bufs.all_empty(),
+        p.p);
+    p.v = p.p = 0;
+  }
+
+  // Start an asynchronous wait until data can be sent without blocking.
+  template <typename Handler>
+  void async_send(base_implementation_type& impl, const null_buffers&,
+      socket_base::message_flags, Handler handler)
+  {
+    // Allocate and construct an operation to wrap the handler.
+    typedef win_iocp_null_buffers_op<Handler> op;
+    typename op::ptr p = { boost::addressof(handler),
+      asio_handler_alloc_helpers::allocate(
+        sizeof(op), handler), 0 };
+    p.p = new (p.v) op(impl.cancel_token_, handler);
+
+    start_reactor_op(impl, reactor::write_op, p.p);
+    p.v = p.p = 0;
+  }
+
+  // Receive some data from the peer. Returns the number of bytes received.
+  template <typename MutableBufferSequence>
+  size_t receive(base_implementation_type& impl,
+      const MutableBufferSequence& buffers,
+      socket_base::message_flags flags, asio::error_code& ec)
+  {
+    buffer_sequence_adapter<asio::mutable_buffer,
+        MutableBufferSequence> bufs(buffers);
+
+    return socket_ops::sync_recv(impl.socket_, impl.state_,
+        bufs.buffers(), bufs.count(), flags, bufs.all_empty(), ec);
+  }
+
+  // Wait until data can be received without blocking.
+  size_t receive(base_implementation_type& impl, const null_buffers&,
+      socket_base::message_flags, asio::error_code& ec)
+  {
+    // Wait for socket to become ready.
+    socket_ops::poll_read(impl.socket_, ec);
+
+    return 0;
+  }
+
+  // Start an asynchronous receive. The buffer for the data being received
+  // must be valid for the lifetime of the asynchronous operation.
+  template <typename MutableBufferSequence, typename Handler>
+  void async_receive(base_implementation_type& impl,
+      const MutableBufferSequence& buffers,
+      socket_base::message_flags flags, Handler handler)
+  {
+    // Allocate and construct an operation to wrap the handler.
+    typedef win_iocp_socket_recv_op<MutableBufferSequence, Handler> op;
+    typename op::ptr p = { boost::addressof(handler),
+      asio_handler_alloc_helpers::allocate(
+        sizeof(op), handler), 0 };
+    p.p = new (p.v) op(impl.state_, impl.cancel_token_, buffers, handler);
+
+    buffer_sequence_adapter<asio::mutable_buffer,
+        MutableBufferSequence> bufs(buffers);
+
+    start_receive_op(impl, bufs.buffers(), bufs.count(), flags,
+        (impl.state_ & socket_ops::stream_oriented) != 0 && bufs.all_empty(),
+        p.p);
+    p.v = p.p = 0;
+  }
+
+  // Wait until data can be received without blocking.
+  template <typename Handler>
+  void async_receive(base_implementation_type& impl, const null_buffers&,
+      socket_base::message_flags flags, Handler handler)
+  {
+    // Allocate and construct an operation to wrap the handler.
+    typedef win_iocp_null_buffers_op<Handler> op;
+    typename op::ptr p = { boost::addressof(handler),
+      asio_handler_alloc_helpers::allocate(
+        sizeof(op), handler), 0 };
+    p.p = new (p.v) op(impl.cancel_token_, handler);
+
+    start_null_buffers_receive_op(impl, flags, p.p);
+    p.v = p.p = 0;
+  }
+
+  // Helper function to restart an asynchronous accept operation.
+  ASIO_DECL void restart_accept_op(socket_type s,
+      socket_holder& new_socket, int family, int type, int protocol,
+      void* output_buffer, DWORD address_length, operation* op);
+
+protected:
+  // Open a new socket implementation.
+  ASIO_DECL asio::error_code do_open(
+      base_implementation_type& impl, int family, int type,
+      int protocol, asio::error_code& ec);
+
+  // Assign a native socket to a socket implementation.
+  ASIO_DECL asio::error_code do_assign(
+      base_implementation_type& impl, int type,
+      socket_type native_socket, asio::error_code& ec);
+
+  // Helper function to start an asynchronous send operation.
+  ASIO_DECL void start_send_op(base_implementation_type& impl,
+      WSABUF* buffers, std::size_t buffer_count,
+      socket_base::message_flags flags, bool noop, operation* op);
+
+  // Helper function to start an asynchronous send_to operation.
+  ASIO_DECL void start_send_to_op(base_implementation_type& impl,
+      WSABUF* buffers, std::size_t buffer_count,
+      const socket_addr_type* addr, int addrlen,
+      socket_base::message_flags flags, operation* op);
+
+  // Helper function to start an asynchronous receive operation.
+  ASIO_DECL void start_receive_op(base_implementation_type& impl,
+      WSABUF* buffers, std::size_t buffer_count,
+      socket_base::message_flags flags, bool noop, operation* op);
+
+  // Helper function to start an asynchronous null_buffers receive operation.
+  ASIO_DECL void start_null_buffers_receive_op(
+      base_implementation_type& impl,
+      socket_base::message_flags flags, reactor_op* op);
+
+  // Helper function to start an asynchronous receive_from operation.
+  ASIO_DECL void start_receive_from_op(base_implementation_type& impl,
+      WSABUF* buffers, std::size_t buffer_count, socket_addr_type* addr,
+      socket_base::message_flags flags, int* addrlen, operation* op);
+
+  // Helper function to start an asynchronous accept operation.
+  ASIO_DECL void start_accept_op(base_implementation_type& impl,
+      bool peer_is_open, socket_holder& new_socket, int family, int type,
+      int protocol, void* output_buffer, DWORD address_length, operation* op);
+
+  // Start an asynchronous read or write operation using the the reactor.
+  ASIO_DECL void start_reactor_op(base_implementation_type& impl,
+      int op_type, reactor_op* op);
+
+  // Start the asynchronous connect operation using the reactor.
+  ASIO_DECL void start_connect_op(base_implementation_type& impl,
+      reactor_op* op, const socket_addr_type* addr, std::size_t addrlen);
+
+  // Helper function to close a socket when the associated object is being
+  // destroyed.
+  ASIO_DECL void close_for_destruction(base_implementation_type& impl);
+
+  // Update the ID of the thread from which cancellation is safe.
+  ASIO_DECL void update_cancellation_thread_id(
+      base_implementation_type& impl);
+
+  // Helper function to get the reactor. If no reactor has been created yet, a
+  // new one is obtained from the io_service and a pointer to it is cached in
+  // this service.
+  ASIO_DECL reactor& get_reactor();
+
+  // Helper function to emulate InterlockedCompareExchangePointer functionality
+  // for:
+  // - very old Platform SDKs; and
+  // - platform SDKs where MSVC's /Wp64 option causes spurious warnings.
+  ASIO_DECL void* interlocked_compare_exchange_pointer(
+      void** dest, void* exch, void* cmp);
+
+  // Helper function to emulate InterlockedExchangePointer functionality for:
+  // - very old Platform SDKs; and
+  // - platform SDKs where MSVC's /Wp64 option causes spurious warnings.
+  ASIO_DECL void* interlocked_exchange_pointer(void** dest, void* val);
+
+  // The io_service used to obtain the reactor, if required.
+  asio::io_service& io_service_;
+
+  // The IOCP service used for running asynchronous operations and dispatching
+  // handlers.
+  win_iocp_io_service& iocp_service_;
+
+  // The reactor used for performing connect operations. This object is created
+  // only if needed.
+  reactor* reactor_;
+
+  // Mutex to protect access to the linked list of implementations. 
+  asio::detail::mutex mutex_;
+
+  // The head of a linked list of all implementations.
+  base_implementation_type* impl_list_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/detail/impl/win_iocp_socket_service_base.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
+#endif // defined(ASIO_HAS_IOCP)
+
+#endif // ASIO_DETAIL_WIN_IOCP_SOCKET_SERVICE_BASE_HPP
diff --git a/ext/asio/asio/detail/win_mutex.hpp b/ext/asio/asio/detail/win_mutex.hpp
index 1280a4e..59ad697 100644
--- a/ext/asio/asio/detail/win_mutex.hpp
+++ b/ext/asio/asio/detail/win_mutex.hpp
@@ -1,8 +1,8 @@
 //
-// win_mutex.hpp
-// ~~~~~~~~~~~~~
+// detail/win_mutex.hpp
+// ~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,23 +15,15 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
+#include "asio/detail/config.hpp"
 
 #if defined(BOOST_WINDOWS)
 
-#include "asio/error.hpp"
-#include "asio/system_error.hpp"
 #include "asio/detail/noncopyable.hpp"
-#include "asio/detail/socket_types.hpp"
 #include "asio/detail/scoped_lock.hpp"
+#include "asio/detail/socket_types.hpp"
 
 #include "asio/detail/push_options.hpp"
-#include <boost/throw_exception.hpp>
-#include "asio/detail/pop_options.hpp"
 
 namespace asio {
 namespace detail {
@@ -43,18 +35,7 @@ public:
   typedef asio::detail::scoped_lock<win_mutex> scoped_lock;
 
   // Constructor.
-  win_mutex()
-  {
-    int error = do_init();
-    if (error != 0)
-    {
-      asio::system_error e(
-          asio::error_code(error,
-            asio::error::get_system_category()),
-          "mutex");
-      boost::throw_exception(e);
-    }
-  }
+  ASIO_DECL win_mutex();
 
   // Destructor.
   ~win_mutex()
@@ -78,35 +59,7 @@ private:
   // Initialisation must be performed in a separate function to the constructor
   // since the compiler does not support the use of structured exceptions and
   // C++ exceptions in the same function.
-  int do_init()
-  {
-#if defined(__MINGW32__)
-    // Not sure if MinGW supports structured exception handling, so for now
-    // we'll just call the Windows API and hope.
-# if defined(UNDER_CE)
-    ::InitializeCriticalSection(&crit_section_);
-# else
-    ::InitializeCriticalSectionAndSpinCount(&crit_section_, 0x80000000);
-# endif
-    return 0;
-#else
-    __try
-    {
-# if defined(UNDER_CE)
-      ::InitializeCriticalSection(&crit_section_);
-# else
-      ::InitializeCriticalSectionAndSpinCount(&crit_section_, 0x80000000);
-# endif
-    }
-    __except(GetExceptionCode() == STATUS_NO_MEMORY
-        ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
-    {
-      return ERROR_OUTOFMEMORY;
-    }
-
-    return 0;
-#endif
-  }
+  ASIO_DECL int do_init();
 
   ::CRITICAL_SECTION crit_section_;
 };
@@ -114,8 +67,12 @@ private:
 } // namespace detail
 } // namespace asio
 
-#endif // defined(BOOST_WINDOWS)
-
 #include "asio/detail/pop_options.hpp"
 
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/detail/impl/win_mutex.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
+#endif // defined(BOOST_WINDOWS)
+
 #endif // ASIO_DETAIL_WIN_MUTEX_HPP
diff --git a/ext/asio/asio/detail/win_thread.hpp b/ext/asio/asio/detail/win_thread.hpp
index 9bf0665..e73d1a4 100644
--- a/ext/asio/asio/detail/win_thread.hpp
+++ b/ext/asio/asio/detail/win_thread.hpp
@@ -1,8 +1,8 @@
 //
-// win_thread.hpp
-// ~~~~~~~~~~~~~~
+// detail/win_thread.hpp
+// ~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,34 +15,24 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
+#include "asio/detail/config.hpp"
 
 #if defined(BOOST_WINDOWS) && !defined(UNDER_CE)
 
-#include "asio/error.hpp"
-#include "asio/system_error.hpp"
 #include "asio/detail/noncopyable.hpp"
 #include "asio/detail/socket_types.hpp"
 
 #include "asio/detail/push_options.hpp"
-#include <boost/throw_exception.hpp>
-#include <memory>
-#include <process.h>
-#include "asio/detail/pop_options.hpp"
 
 namespace asio {
 namespace detail {
 
-unsigned int __stdcall win_thread_function(void* arg);
+ASIO_DECL unsigned int __stdcall win_thread_function(void* arg);
 
 #if defined(WINVER) && (WINVER < 0x0500)
-void __stdcall apc_function(ULONG data);
+ASIO_DECL void __stdcall apc_function(ULONG data);
 #else
-void __stdcall apc_function(ULONG_PTR data);
+ASIO_DECL void __stdcall apc_function(ULONG_PTR data);
 #endif
 
 template <typename T>
@@ -73,92 +63,26 @@ class win_thread
 public:
   // Constructor.
   template <typename Function>
-  win_thread(Function f)
-    : exit_event_(0)
+  win_thread(Function f, unsigned int stack_size = 0)
+    : thread_(0),
+      exit_event_(0)
   {
-    std::auto_ptr<func_base> arg(new func<Function>(f));
-
-    ::HANDLE entry_event = 0;
-    arg->entry_event_ = entry_event = ::CreateEvent(0, true, false, 0);
-    if (!entry_event)
-    {
-      DWORD last_error = ::GetLastError();
-      asio::system_error e(
-          asio::error_code(last_error,
-            asio::error::get_system_category()),
-          "thread.entry_event");
-      boost::throw_exception(e);
-    }
-
-    arg->exit_event_ = exit_event_ = ::CreateEvent(0, true, false, 0);
-    if (!exit_event_)
-    {
-      DWORD last_error = ::GetLastError();
-      ::CloseHandle(entry_event);
-      asio::system_error e(
-          asio::error_code(last_error,
-            asio::error::get_system_category()),
-          "thread.exit_event");
-      boost::throw_exception(e);
-    }
-
-    unsigned int thread_id = 0;
-    thread_ = reinterpret_cast<HANDLE>(::_beginthreadex(0, 0,
-          win_thread_function, arg.get(), 0, &thread_id));
-    if (!thread_)
-    {
-      DWORD last_error = ::GetLastError();
-      if (entry_event)
-        ::CloseHandle(entry_event);
-      if (exit_event_)
-        ::CloseHandle(exit_event_);
-      asio::system_error e(
-          asio::error_code(last_error,
-            asio::error::get_system_category()),
-          "thread");
-      boost::throw_exception(e);
-    }
-    arg.release();
-
-    if (entry_event)
-    {
-      ::WaitForSingleObject(entry_event, INFINITE);
-      ::CloseHandle(entry_event);
-    }
+    start_thread(new func<Function>(f), stack_size);
   }
 
   // Destructor.
-  ~win_thread()
-  {
-    ::CloseHandle(thread_);
-
-    // The exit_event_ handle is deliberately allowed to leak here since it
-    // is an error for the owner of an internal thread not to join() it.
-  }
+  ASIO_DECL ~win_thread();
 
   // Wait for the thread to exit.
-  void join()
-  {
-    ::WaitForSingleObject(exit_event_, INFINITE);
-    ::CloseHandle(exit_event_);
-    if (terminate_threads())
-    {
-      ::TerminateThread(thread_, 0);
-    }
-    else
-    {
-      ::QueueUserAPC(apc_function, thread_, 0);
-      ::WaitForSingleObject(thread_, INFINITE);
-    }
-  }
+  ASIO_DECL void join();
 
 private:
-  friend unsigned int __stdcall win_thread_function(void* arg);
+  friend ASIO_DECL unsigned int __stdcall win_thread_function(void* arg);
 
 #if defined(WINVER) && (WINVER < 0x0500)
-  friend void __stdcall apc_function(ULONG);
+  friend ASIO_DECL void __stdcall apc_function(ULONG);
 #else
-  friend void __stdcall apc_function(ULONG_PTR);
+  friend ASIO_DECL void __stdcall apc_function(ULONG_PTR);
 #endif
 
   class func_base
@@ -170,6 +94,12 @@ private:
     ::HANDLE exit_event_;
   };
 
+  struct auto_func_base_ptr
+  {
+    func_base* ptr;
+    ~auto_func_base_ptr() { delete ptr; }
+  };
+
   template <typename Function>
   class func
     : public func_base
@@ -189,44 +119,21 @@ private:
     Function f_;
   };
 
+  ASIO_DECL void start_thread(func_base* arg, unsigned int stack_size);
+
   ::HANDLE thread_;
   ::HANDLE exit_event_;
 };
 
-inline unsigned int __stdcall win_thread_function(void* arg)
-{
-  std::auto_ptr<win_thread::func_base> func(
-      static_cast<win_thread::func_base*>(arg));
-
-  ::SetEvent(func->entry_event_);
-
-  func->run();
-
-  // Signal that the thread has finished its work, but rather than returning go
-  // to sleep to put the thread into a well known state. If the thread is being
-  // joined during global object destruction then it may be killed using
-  // TerminateThread (to avoid a deadlock in DllMain). Otherwise, the SleepEx
-  // call will be interrupted using QueueUserAPC and the thread will shut down
-  // cleanly.
-  HANDLE exit_event = func->exit_event_;
-  func.reset();
-  ::SetEvent(exit_event);
-  ::SleepEx(INFINITE, TRUE);
-
-  return 0;
-}
-
-#if defined(WINVER) && (WINVER < 0x0500)
-inline void __stdcall apc_function(ULONG) {}
-#else
-inline void __stdcall apc_function(ULONG_PTR) {}
-#endif
-
 } // namespace detail
 } // namespace asio
 
-#endif // defined(BOOST_WINDOWS) && !defined(UNDER_CE)
-
 #include "asio/detail/pop_options.hpp"
 
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/detail/impl/win_thread.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
+#endif // defined(BOOST_WINDOWS) && !defined(UNDER_CE)
+
 #endif // ASIO_DETAIL_WIN_THREAD_HPP
diff --git a/ext/asio/asio/detail/win_tss_ptr.hpp b/ext/asio/asio/detail/win_tss_ptr.hpp
index 5a4ed33..fb055f6 100644
--- a/ext/asio/asio/detail/win_tss_ptr.hpp
+++ b/ext/asio/asio/detail/win_tss_ptr.hpp
@@ -1,8 +1,8 @@
 //
-// win_tss_ptr.hpp
-// ~~~~~~~~~~~~~~~
+// detail/win_tss_ptr.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,50 +15,30 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
+#include "asio/detail/config.hpp"
 
 #if defined(BOOST_WINDOWS)
 
-#include "asio/error.hpp"
-#include "asio/system_error.hpp"
 #include "asio/detail/noncopyable.hpp"
 #include "asio/detail/socket_types.hpp"
 
 #include "asio/detail/push_options.hpp"
-#include <boost/throw_exception.hpp>
-#include "asio/detail/pop_options.hpp"
 
 namespace asio {
 namespace detail {
 
+// Helper function to create thread-specific storage.
+ASIO_DECL DWORD win_tss_ptr_create();
+
 template <typename T>
 class win_tss_ptr
   : private noncopyable
 {
 public:
-#if defined(UNDER_CE)
-  enum { out_of_indexes = 0xFFFFFFFF };
-#else
-  enum { out_of_indexes = TLS_OUT_OF_INDEXES };
-#endif
-
   // Constructor.
   win_tss_ptr()
+    : tss_key_(win_tss_ptr_create())
   {
-    tss_key_ = ::TlsAlloc();
-    if (tss_key_ == out_of_indexes)
-    {
-      DWORD last_error = ::GetLastError();
-      asio::system_error e(
-          asio::error_code(last_error,
-            asio::error::get_system_category()),
-          "tss");
-      boost::throw_exception(e);
-    }
   }
 
   // Destructor.
@@ -88,8 +68,12 @@ private:
 } // namespace detail
 } // namespace asio
 
-#endif // defined(BOOST_WINDOWS)
-
 #include "asio/detail/pop_options.hpp"
 
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/detail/impl/win_tss_ptr.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
+#endif // defined(BOOST_WINDOWS)
+
 #endif // ASIO_DETAIL_WIN_TSS_PTR_HPP
diff --git a/ext/asio/asio/detail/wince_thread.hpp b/ext/asio/asio/detail/wince_thread.hpp
index 0b6de48..1dc9990 100644
--- a/ext/asio/asio/detail/wince_thread.hpp
+++ b/ext/asio/asio/detail/wince_thread.hpp
@@ -1,8 +1,8 @@
 //
-// wince_thread.hpp
-// ~~~~~~~~~~~~~~~~
+// detail/wince_thread.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,23 +15,17 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
+#include "asio/detail/config.hpp"
 
 #if defined(BOOST_WINDOWS) && defined(UNDER_CE)
 
-#include "asio/error.hpp"
-#include "asio/system_error.hpp"
+#include <memory>
 #include "asio/detail/noncopyable.hpp"
 #include "asio/detail/socket_types.hpp"
+#include "asio/detail/throw_error.hpp"
+#include "asio/error.hpp"
 
 #include "asio/detail/push_options.hpp"
-#include <boost/throw_exception.hpp>
-#include <memory>
-#include "asio/detail/pop_options.hpp"
 
 namespace asio {
 namespace detail {
@@ -53,11 +47,9 @@ public:
     if (!thread_)
     {
       DWORD last_error = ::GetLastError();
-      asio::system_error e(
-          asio::error_code(last_error,
-            asio::error::get_system_category()),
-          "thread");
-      boost::throw_exception(e);
+      asio::error_code ec(last_error,
+          asio::error::get_system_category());
+      asio::detail::throw_error(ec, "thread");
     }
     arg.release();
   }
@@ -117,8 +109,8 @@ inline DWORD WINAPI wince_thread_function(LPVOID arg)
 } // namespace detail
 } // namespace asio
 
-#endif // defined(BOOST_WINDOWS) && defined(UNDER_CE)
-
 #include "asio/detail/pop_options.hpp"
 
+#endif // defined(BOOST_WINDOWS) && defined(UNDER_CE)
+
 #endif // ASIO_DETAIL_WINCE_THREAD_HPP
diff --git a/ext/asio/asio/detail/winsock_init.hpp b/ext/asio/asio/detail/winsock_init.hpp
index ae5c4bf..a410859 100644
--- a/ext/asio/asio/detail/winsock_init.hpp
+++ b/ext/asio/asio/detail/winsock_init.hpp
@@ -1,8 +1,8 @@
 //
-// winsock_init.hpp
-// ~~~~~~~~~~~~~~~~
+// detail/winsock_init.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,106 +15,76 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
+#include "asio/detail/config.hpp"
 
 #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
 
 #include "asio/detail/push_options.hpp"
-#include <boost/shared_ptr.hpp>
-#include <boost/throw_exception.hpp>
-#include "asio/detail/pop_options.hpp"
-
-#include "asio/error.hpp"
-#include "asio/system_error.hpp"
-#include "asio/detail/noncopyable.hpp"
-#include "asio/detail/socket_types.hpp"
 
 namespace asio {
 namespace detail {
 
-template <int Major = 2, int Minor = 0>
-class winsock_init
-  : private noncopyable
+class winsock_init_base
 {
-private:
-  // Structure to perform the actual initialisation.
-  struct do_init
+protected:
+  // Structure to track result of initialisation and number of uses. POD is used
+  // to ensure that the values are zero-initialised prior to any code being run.
+  struct data
   {
-    do_init()
-    {
-      WSADATA wsa_data;
-      result_ = ::WSAStartup(MAKEWORD(Major, Minor), &wsa_data);
-    }
-
-    ~do_init()
-    {
-      ::WSACleanup();
-    }
-
-    int result() const
-    {
-      return result_;
-    }
-
-    // Helper function to manage a do_init singleton. The static instance of the
-    // winsock_init object ensures that this function is always called before
-    // main, and therefore before any other threads can get started. The do_init
-    // instance must be static in this function to ensure that it gets
-    // initialised before any other global objects try to use it.
-    static boost::shared_ptr<do_init> instance()
-    {
-      static boost::shared_ptr<do_init> init(new do_init);
-      return init;
-    }
-
-  private:
-    int result_;
+    long init_count_;
+    long result_;
   };
 
+  ASIO_DECL static void startup(data& d,
+      unsigned char major, unsigned char minor);
+
+  ASIO_DECL static void cleanup(data& d);
+
+  ASIO_DECL static void throw_on_error(data& d);
+};
+
+template <int Major = 2, int Minor = 0>
+class winsock_init : private winsock_init_base
+{
 public:
-  // Constructor.
-  winsock_init()
-    : ref_(do_init::instance())
+  winsock_init(bool allow_throw = true)
+  {
+    startup(data_, Major, Minor);
+    if (allow_throw)
+      throw_on_error(data_);
+  }
+
+  winsock_init(const winsock_init&)
   {
-    // Check whether winsock was successfully initialised. This check is not
-    // performed for the global instance since there will be nobody around to
-    // catch the exception.
-    if (this != &instance_ && ref_->result() != 0)
-    {
-      asio::system_error e(
-          asio::error_code(ref_->result(),
-            asio::error::get_system_category()),
-          "winsock");
-      boost::throw_exception(e);
-    }
+    startup(data_, Major, Minor);
+    throw_on_error(data_);
   }
 
-  // Destructor.
   ~winsock_init()
   {
+    cleanup(data_);
   }
 
 private:
-  // Instance to force initialisation of winsock at global scope.
-  static winsock_init instance_;
-
-  // Reference to singleton do_init object to ensure that winsock does not get
-  // cleaned up until the last user has finished with it.
-  boost::shared_ptr<do_init> ref_;
+  static data data_;
 };
 
 template <int Major, int Minor>
-winsock_init<Major, Minor> winsock_init<Major, Minor>::instance_;
+winsock_init_base::data winsock_init<Major, Minor>::data_;
+
+// Static variable to ensure that winsock is initialised before main, and
+// therefore before any other threads can get started.
+static const winsock_init<>& winsock_init_instance = winsock_init<>(false);
 
 } // namespace detail
 } // namespace asio
 
-#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-
 #include "asio/detail/pop_options.hpp"
 
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/detail/impl/winsock_init.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+
 #endif // ASIO_DETAIL_WINSOCK_INIT_HPP
diff --git a/ext/asio/asio/detail/wrapped_handler.hpp b/ext/asio/asio/detail/wrapped_handler.hpp
index e40a7f1..bcebf6e 100644
--- a/ext/asio/asio/detail/wrapped_handler.hpp
+++ b/ext/asio/asio/detail/wrapped_handler.hpp
@@ -1,8 +1,8 @@
 //
-// wrapped_handler.hpp
-// ~~~~~~~~~~~~~~~~~~~
+// detail/wrapped_handler.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,16 +15,12 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <boost/type_traits/add_reference.hpp>
-#include "asio/detail/pop_options.hpp"
-
 #include "asio/detail/bind_handler.hpp"
 #include "asio/detail/handler_alloc_helpers.hpp"
 #include "asio/detail/handler_invoke_helpers.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 namespace detail {
 
@@ -34,9 +30,7 @@ class wrapped_handler
 public:
   typedef void result_type;
 
-  wrapped_handler(
-      typename boost::add_reference<Dispatcher>::type dispatcher,
-      Handler handler)
+  wrapped_handler(Dispatcher dispatcher, Handler handler)
     : dispatcher_(dispatcher),
       handler_(handler)
   {
diff --git a/ext/asio/asio/error.hpp b/ext/asio/asio/error.hpp
index 73caac6..138b5d7 100644
--- a/ext/asio/asio/error.hpp
+++ b/ext/asio/asio/error.hpp
@@ -2,7 +2,7 @@
 // error.hpp
 // ~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,15 +15,13 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <cerrno>
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
-
-#include "asio/error_code.hpp"
-#include "asio/detail/socket_types.hpp"
+#include "asio/detail/config.hpp"
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+# include <winerror.h>
+#else
+# include <cerrno>
+# include <netdb.h>
+#endif
 
 #if defined(GENERATING_DOCUMENTATION)
 /// INTERNAL ONLY.
@@ -50,6 +48,8 @@
 # define ASIO_WIN_OR_POSIX(e_win, e_posix) e_posix
 #endif
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 namespace error {
 
@@ -212,7 +212,21 @@ enum ssl_errors
 {
 };
 
-// boostify: error category definitions go here.
+// boostify: error category definitions start here.
+
+} // namespace error
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#include "asio/error_code.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace error {
+
+// boostify: error category definitions end here.
 
 inline asio::error_code make_error_code(basic_errors e)
 {
@@ -247,14 +261,16 @@ inline asio::error_code make_error_code(ssl_errors e)
 } // namespace error
 } // namespace asio
 
+#include "asio/detail/pop_options.hpp"
+
 #undef ASIO_NATIVE_ERROR
 #undef ASIO_SOCKET_ERROR
 #undef ASIO_NETDB_ERROR
 #undef ASIO_GETADDRINFO_ERROR
 #undef ASIO_WIN_OR_POSIX
 
-#include "asio/impl/error_code.ipp"
-
-#include "asio/detail/pop_options.hpp"
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/impl/error.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
 
 #endif // ASIO_ERROR_HPP
diff --git a/ext/asio/asio/error_code.hpp b/ext/asio/asio/error_code.hpp
index 6657f3f..1af449b 100644
--- a/ext/asio/asio/error_code.hpp
+++ b/ext/asio/asio/error_code.hpp
@@ -2,7 +2,7 @@
 // error_code.hpp
 // ~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,12 +15,8 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
+#include "asio/detail/config.hpp"
 #include <string>
-#include "asio/detail/pop_options.hpp"
 
 #if defined(GENERATING_DOCUMENTATION)
 # define ASIO_WIN_OR_POSIX(e_win, e_posix) implementation_defined
@@ -30,6 +26,8 @@
 # define ASIO_WIN_OR_POSIX(e_win, e_posix) e_posix
 #endif
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 
 namespace error
@@ -106,7 +104,7 @@ public:
   }
 
   /// Get the message associated with the error.
-  std::string message() const;
+  ASIO_DECL std::string message() const;
 
   struct unspecified_bool_type_t
   {
@@ -114,14 +112,12 @@ public:
 
   typedef void (*unspecified_bool_type)(unspecified_bool_type_t);
 
-  static void unspecified_bool_true(unspecified_bool_type_t)
-  {
-  }
+  static void unspecified_bool_true(unspecified_bool_type_t) {}
 
   /// Operator returns non-null if there is a non-success error code.
   operator unspecified_bool_type() const
   {
-    if (value_ == 0)
+    if (!value_)
       return 0;
     else
       return &error_code::unspecified_bool_true;
@@ -130,7 +126,7 @@ public:
   /// Operator to test if the error represents success.
   bool operator!() const
   {
-    return value_ == 0;
+    return !value_;
   }
 
   /// Equality operator to compare two error objects.
@@ -155,10 +151,12 @@ private:
 
 } // namespace asio
 
-#undef ASIO_WIN_OR_POSIX
+#include "asio/detail/pop_options.hpp"
 
-#include "asio/error.hpp"
+#undef ASIO_WIN_OR_POSIX
 
-#include "asio/detail/pop_options.hpp"
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/impl/error_code.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
 
 #endif // ASIO_ERROR_CODE_HPP
diff --git a/ext/asio/asio/handler_alloc_hook.hpp b/ext/asio/asio/handler_alloc_hook.hpp
index 87783cd..dd930b6 100644
--- a/ext/asio/asio/handler_alloc_hook.hpp
+++ b/ext/asio/asio/handler_alloc_hook.hpp
@@ -2,7 +2,7 @@
 // handler_alloc_hook.hpp
 // ~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,12 +15,10 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
+#include <cstddef>
 
 #include "asio/detail/push_options.hpp"
-#include <cstddef>
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
 
 namespace asio {
 
diff --git a/ext/asio/asio/handler_invoke_hook.hpp b/ext/asio/asio/handler_invoke_hook.hpp
index b3d7e45..ef22359 100644
--- a/ext/asio/asio/handler_invoke_hook.hpp
+++ b/ext/asio/asio/handler_invoke_hook.hpp
@@ -2,7 +2,7 @@
 // handler_invoke_hook.hpp
 // ~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,6 +15,8 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
+#include "asio/detail/config.hpp"
+
 #include "asio/detail/push_options.hpp"
 
 namespace asio {
diff --git a/ext/asio/asio/impl/error.ipp b/ext/asio/asio/impl/error.ipp
new file mode 100644
index 0000000..54388b3
--- /dev/null
+++ b/ext/asio/asio/impl/error.ipp
@@ -0,0 +1,33 @@
+//
+// impl/error.ipp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_IMPL_ERROR_IPP
+#define ASIO_IMPL_ERROR_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+#include "asio/error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace error {
+
+// boostify: error category function definitions go here.
+
+} // namespace error
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_IMPL_ERROR_IPP
diff --git a/ext/asio/asio/impl/error_code.ipp b/ext/asio/asio/impl/error_code.ipp
index 614925d..ed37a17 100644
--- a/ext/asio/asio/impl/error_code.ipp
+++ b/ext/asio/asio/impl/error_code.ipp
@@ -1,50 +1,55 @@
 //
-// error_code.ipp
-// ~~~~~~~~~~~~~~
+// impl/error_code.ipp
+// ~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 //
 
-#ifndef ASIO_ERROR_CODE_IPP
-#define ASIO_ERROR_CODE_IPP
+#ifndef ASIO_IMPL_ERROR_CODE_IPP
+#define ASIO_IMPL_ERROR_CODE_IPP
 
 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include <cerrno>
-#include <cstring>
-#include "asio/detail/pop_options.hpp"
-
-#include "asio/error.hpp"
+#include "asio/detail/config.hpp"
 #include "asio/detail/local_free_on_block_exit.hpp"
 #include "asio/detail/socket_types.hpp"
+#include "asio/error.hpp"
+#include "asio/error_code.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 
-inline std::string error_code::message() const
+std::string error_code::message() const
 {
-  if (*this == error::already_open)
-    return "Already open.";
-  if (*this == error::not_found)
-    return "Not found.";
-  if (*this == error::fd_set_failure)
-    return "The descriptor does not fit into the select call's fd_set.";
+  if (category_ == error::get_misc_category())
+  {
+    if (value_ == error::already_open)
+      return "Already open.";
+    if (value_ == error::not_found)
+      return "Not found.";
+    if (value_ == error::fd_set_failure)
+      return "The descriptor does not fit into the select call's fd_set.";
+    if (value_ == error::not_found)
+      return "Element not found.";
+#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+    if (value_ == error::eof)
+      return "End of file.";
+#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+  }
   if (category_ == error::get_ssl_category())
     return "SSL error.";
 #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
   value_type value = value_;
-  if (category() != error::get_system_category() && *this != error::eof)
-    return "asio error";
-  if (*this == error::eof)
+  if (category_ == error::get_misc_category() && value_ == error::eof)
     value = ERROR_HANDLE_EOF;
+  else if (category_ != error::get_system_category())
+    return "asio error";
   char* msg = 0;
   DWORD length = ::FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER
       | FORMAT_MESSAGE_FROM_SYSTEM
@@ -60,29 +65,31 @@ inline std::string error_code::message() const
   else
     return "asio error";
 #else // defined(BOOST_WINDOWS)
-  if (*this == error::eof)
-    return "End of file.";
-  if (*this == error::host_not_found)
-    return "Host not found (authoritative).";
-  if (*this == error::host_not_found_try_again)
-    return "Host not found (non-authoritative), try again later.";
-  if (*this == error::no_recovery)
-    return "A non-recoverable error occurred during database lookup.";
-  if (*this == error::no_data)
-    return "The query is valid, but it does not have associated data.";
-  if (*this == error::not_found)
-    return "Element not found.";
+  if (category_ == error::get_netdb_category())
+  {
+    if (value_ == error::host_not_found)
+      return "Host not found (authoritative).";
+    if (value_ == error::host_not_found_try_again)
+      return "Host not found (non-authoritative), try again later.";
+    if (value_ == error::no_recovery)
+      return "A non-recoverable error occurred during database lookup.";
+    if (value_ == error::no_data)
+      return "The query is valid, but it does not have associated data.";
+  }
+  if (category_ == error::get_addrinfo_category())
+  {
+    if (value_ == error::service_not_found)
+      return "Service not found.";
+    if (value_ == error::socket_type_not_supported)
+      return "Socket type not supported.";
+  }
+  if (category_ != error::get_system_category())
+    return "asio error";
 #if !defined(__sun)
-  if (*this == error::operation_aborted)
+  if (value_ == error::operation_aborted)
     return "Operation aborted.";
 #endif // !defined(__sun)
-  if (*this == error::service_not_found)
-    return "Service not found.";
-  if (*this == error::socket_type_not_supported)
-    return "Socket type not supported.";
-  if (category() != error::get_system_category())
-    return "asio error";
-#if defined(__sun) || defined(__QNX__)
+#if defined(__sun) || defined(__QNX__) || defined(__SYMBIAN32__)
   using namespace std;
   return strerror(value_);
 #elif defined(__MACH__) && defined(__APPLE__) \
@@ -102,4 +109,4 @@ inline std::string error_code::message() const
 
 #include "asio/detail/pop_options.hpp"
 
-#endif // ASIO_ERROR_CODE_IPP
+#endif // ASIO_IMPL_ERROR_CODE_IPP
diff --git a/ext/asio/asio/impl/io_service.hpp b/ext/asio/asio/impl/io_service.hpp
new file mode 100644
index 0000000..f0c1730
--- /dev/null
+++ b/ext/asio/asio/impl/io_service.hpp
@@ -0,0 +1,132 @@
+//
+// impl/io_service.hpp
+// ~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_IMPL_IO_SERVICE_HPP
+#define ASIO_IMPL_IO_SERVICE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/service_registry.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+
+template <typename Service>
+inline Service& use_service(io_service& ios)
+{
+  // Check that Service meets the necessary type requirements.
+  (void)static_cast<io_service::service*>(static_cast<Service*>(0));
+  (void)static_cast<const io_service::id*>(&Service::id);
+
+  return ios.service_registry_->template use_service<Service>();
+}
+
+template <typename Service>
+inline void add_service(io_service& ios, Service* svc)
+{
+  // Check that Service meets the necessary type requirements.
+  (void)static_cast<io_service::service*>(static_cast<Service*>(0));
+  (void)static_cast<const io_service::id*>(&Service::id);
+
+  ios.service_registry_->template add_service<Service>(svc);
+}
+
+template <typename Service>
+inline bool has_service(io_service& ios)
+{
+  // Check that Service meets the necessary type requirements.
+  (void)static_cast<io_service::service*>(static_cast<Service*>(0));
+  (void)static_cast<const io_service::id*>(&Service::id);
+
+  return ios.service_registry_->template has_service<Service>();
+}
+
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#if defined(ASIO_HAS_IOCP)
+# include "asio/detail/win_iocp_io_service.hpp"
+#else
+# include "asio/detail/task_io_service.hpp"
+#endif
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+
+template <typename Handler>
+inline void io_service::dispatch(Handler handler)
+{
+  impl_.dispatch(handler);
+}
+
+template <typename Handler>
+inline void io_service::post(Handler handler)
+{
+  impl_.post(handler);
+}
+
+template <typename Handler>
+#if defined(GENERATING_DOCUMENTATION)
+unspecified
+#else
+inline detail::wrapped_handler<io_service&, Handler>
+#endif
+io_service::wrap(Handler handler)
+{
+  return detail::wrapped_handler<io_service&, Handler>(*this, handler);
+}
+
+inline io_service::work::work(asio::io_service& io_service)
+  : io_service_(io_service)
+{
+  io_service_.impl_.work_started();
+}
+
+inline io_service::work::work(const work& other)
+  : io_service_(other.io_service_)
+{
+  io_service_.impl_.work_started();
+}
+
+inline io_service::work::~work()
+{
+  io_service_.impl_.work_finished();
+}
+
+inline asio::io_service& io_service::work::io_service()
+{
+  return io_service_;
+}
+
+inline asio::io_service& io_service::work::get_io_service()
+{
+  return io_service_;
+}
+
+inline asio::io_service& io_service::service::io_service()
+{
+  return owner_;
+}
+
+inline asio::io_service& io_service::service::get_io_service()
+{
+  return owner_;
+}
+
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_IMPL_IO_SERVICE_HPP
diff --git a/ext/asio/asio/impl/io_service.ipp b/ext/asio/asio/impl/io_service.ipp
index c3fed3b..eb19b8f 100644
--- a/ext/asio/asio/impl/io_service.ipp
+++ b/ext/asio/asio/impl/io_service.ipp
@@ -1,26 +1,23 @@
 //
-// io_service.ipp
-// ~~~~~~~~~~~~~~
+// impl/io_service.ipp
+// ~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 //
 
-#ifndef ASIO_IO_SERVICE_IPP
-#define ASIO_IO_SERVICE_IPP
+#ifndef ASIO_IMPL_IO_SERVICE_IPP
+#define ASIO_IMPL_IO_SERVICE_IPP
 
 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 #include <boost/limits.hpp>
-#include "asio/detail/pop_options.hpp"
-
+#include "asio/io_service.hpp"
 #include "asio/detail/service_registry.hpp"
 #include "asio/detail/throw_error.hpp"
 
@@ -28,31 +25,32 @@
 # include "asio/detail/win_iocp_io_service.hpp"
 #else
 # include "asio/detail/task_io_service.hpp"
-# include "asio/detail/reactor.hpp"
 #endif
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 
-inline io_service::io_service()
+io_service::io_service()
   : service_registry_(new asio::detail::service_registry(*this)),
     impl_(service_registry_->use_service<impl_type>())
 {
   impl_.init((std::numeric_limits<std::size_t>::max)());
 }
 
-inline io_service::io_service(std::size_t concurrency_hint)
+io_service::io_service(std::size_t concurrency_hint)
   : service_registry_(new asio::detail::service_registry(*this)),
     impl_(service_registry_->use_service<impl_type>())
 {
   impl_.init(concurrency_hint);
 }
 
-inline io_service::~io_service()
+io_service::~io_service()
 {
   delete service_registry_;
 }
 
-inline std::size_t io_service::run()
+std::size_t io_service::run()
 {
   asio::error_code ec;
   std::size_t s = impl_.run(ec);
@@ -60,12 +58,12 @@ inline std::size_t io_service::run()
   return s;
 }
 
-inline std::size_t io_service::run(asio::error_code& ec)
+std::size_t io_service::run(asio::error_code& ec)
 {
   return impl_.run(ec);
 }
 
-inline std::size_t io_service::run_one()
+std::size_t io_service::run_one()
 {
   asio::error_code ec;
   std::size_t s = impl_.run_one(ec);
@@ -73,12 +71,12 @@ inline std::size_t io_service::run_one()
   return s;
 }
 
-inline std::size_t io_service::run_one(asio::error_code& ec)
+std::size_t io_service::run_one(asio::error_code& ec)
 {
   return impl_.run_one(ec);
 }
 
-inline std::size_t io_service::poll()
+std::size_t io_service::poll()
 {
   asio::error_code ec;
   std::size_t s = impl_.poll(ec);
@@ -86,12 +84,12 @@ inline std::size_t io_service::poll()
   return s;
 }
 
-inline std::size_t io_service::poll(asio::error_code& ec)
+std::size_t io_service::poll(asio::error_code& ec)
 {
   return impl_.poll(ec);
 }
 
-inline std::size_t io_service::poll_one()
+std::size_t io_service::poll_one()
 {
   asio::error_code ec;
   std::size_t s = impl_.poll_one(ec);
@@ -99,126 +97,43 @@ inline std::size_t io_service::poll_one()
   return s;
 }
 
-inline std::size_t io_service::poll_one(asio::error_code& ec)
+std::size_t io_service::poll_one(asio::error_code& ec)
 {
   return impl_.poll_one(ec);
 }
 
-inline void io_service::stop()
+void io_service::stop()
 {
   impl_.stop();
 }
 
-inline void io_service::reset()
+void io_service::reset()
 {
   impl_.reset();
 }
 
-template <typename Handler>
-inline void io_service::dispatch(Handler handler)
-{
-  impl_.dispatch(handler);
-}
-
-template <typename Handler>
-inline void io_service::post(Handler handler)
-{
-  impl_.post(handler);
-}
-
-template <typename Handler>
-#if defined(GENERATING_DOCUMENTATION)
-unspecified
-#else
-inline detail::wrapped_handler<io_service&, Handler>
-#endif
-io_service::wrap(Handler handler)
-{
-  return detail::wrapped_handler<io_service&, Handler>(*this, handler);
-}
-
-inline io_service::work::work(asio::io_service& io_service)
-  : io_service_(io_service)
-{
-  io_service_.impl_.work_started();
-}
-
-inline io_service::work::work(const work& other)
-  : io_service_(other.io_service_)
-{
-  io_service_.impl_.work_started();
-}
-
-inline io_service::work::~work()
-{
-  io_service_.impl_.work_finished();
-}
-
-inline asio::io_service& io_service::work::io_service()
-{
-  return io_service_;
-}
-
-inline asio::io_service& io_service::work::get_io_service()
-{
-  return io_service_;
-}
-
-inline io_service::service::service(asio::io_service& owner)
+io_service::service::service(asio::io_service& owner)
   : owner_(owner),
     next_(0)
 {
 }
 
-inline io_service::service::~service()
-{
-}
-
-inline asio::io_service& io_service::service::io_service()
-{
-  return owner_;
-}
-
-inline asio::io_service& io_service::service::get_io_service()
+io_service::service::~service()
 {
-  return owner_;
 }
 
-template <typename Service>
-inline Service& use_service(io_service& ios)
+service_already_exists::service_already_exists()
+  : std::logic_error("Service already exists.")
 {
-  // Check that Service meets the necessary type requirements.
-  (void)static_cast<io_service::service*>(static_cast<Service*>(0));
-  (void)static_cast<const io_service::id*>(&Service::id);
-
-  return ios.service_registry_->template use_service<Service>();
 }
 
-template <typename Service>
-void add_service(io_service& ios, Service* svc)
+invalid_service_owner::invalid_service_owner()
+  : std::logic_error("Invalid service owner.")
 {
-  // Check that Service meets the necessary type requirements.
-  (void)static_cast<io_service::service*>(static_cast<Service*>(0));
-  (void)static_cast<const io_service::id*>(&Service::id);
-
-  if (&ios != &svc->io_service())
-    boost::throw_exception(invalid_service_owner());
-  if (!ios.service_registry_->template add_service<Service>(svc))
-    boost::throw_exception(service_already_exists());
-}
-
-template <typename Service>
-bool has_service(io_service& ios)
-{
-  // Check that Service meets the necessary type requirements.
-  (void)static_cast<io_service::service*>(static_cast<Service*>(0));
-  (void)static_cast<const io_service::id*>(&Service::id);
-
-  return ios.service_registry_->template has_service<Service>();
 }
 
 } // namespace asio
 
 #include "asio/detail/pop_options.hpp"
 
-#endif // ASIO_IO_SERVICE_IPP
+#endif // ASIO_IMPL_IO_SERVICE_IPP
diff --git a/ext/asio/asio/impl/read.hpp b/ext/asio/asio/impl/read.hpp
new file mode 100644
index 0000000..bd5d7b5
--- /dev/null
+++ b/ext/asio/asio/impl/read.hpp
@@ -0,0 +1,386 @@
+//
+// impl/read.hpp
+// ~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_IMPL_READ_HPP
+#define ASIO_IMPL_READ_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <algorithm>
+#include "asio/buffer.hpp"
+#include "asio/completion_condition.hpp"
+#include "asio/detail/base_from_completion_cond.hpp"
+#include "asio/detail/bind_handler.hpp"
+#include "asio/detail/consuming_buffers.hpp"
+#include "asio/detail/handler_alloc_helpers.hpp"
+#include "asio/detail/handler_invoke_helpers.hpp"
+#include "asio/detail/throw_error.hpp"
+#include "asio/error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+
+template <typename SyncReadStream, typename MutableBufferSequence,
+    typename CompletionCondition>
+std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
+    CompletionCondition completion_condition, asio::error_code& ec)
+{
+  ec = asio::error_code();
+  asio::detail::consuming_buffers<
+    mutable_buffer, MutableBufferSequence> tmp(buffers);
+  std::size_t total_transferred = 0;
+  tmp.prepare(detail::adapt_completion_condition_result(
+        completion_condition(ec, total_transferred)));
+  while (tmp.begin() != tmp.end())
+  {
+    std::size_t bytes_transferred = s.read_some(tmp, ec);
+    tmp.consume(bytes_transferred);
+    total_transferred += bytes_transferred;
+    tmp.prepare(detail::adapt_completion_condition_result(
+          completion_condition(ec, total_transferred)));
+  }
+  return total_transferred;
+}
+
+template <typename SyncReadStream, typename MutableBufferSequence>
+inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers)
+{
+  asio::error_code ec;
+  std::size_t bytes_transferred = read(s, buffers, transfer_all(), ec);
+  asio::detail::throw_error(ec);
+  return bytes_transferred;
+}
+
+template <typename SyncReadStream, typename MutableBufferSequence,
+    typename CompletionCondition>
+inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
+    CompletionCondition completion_condition)
+{
+  asio::error_code ec;
+  std::size_t bytes_transferred = read(s, buffers, completion_condition, ec);
+  asio::detail::throw_error(ec);
+  return bytes_transferred;
+}
+
+#if !defined(BOOST_NO_IOSTREAM)
+
+template <typename SyncReadStream, typename Allocator,
+    typename CompletionCondition>
+std::size_t read(SyncReadStream& s,
+    asio::basic_streambuf<Allocator>& b,
+    CompletionCondition completion_condition, asio::error_code& ec)
+{
+  ec = asio::error_code();
+  std::size_t total_transferred = 0;
+  std::size_t max_size = detail::adapt_completion_condition_result(
+        completion_condition(ec, total_transferred));
+  std::size_t bytes_available = read_size_helper(b, max_size);
+  while (bytes_available > 0)
+  {
+    std::size_t bytes_transferred = s.read_some(b.prepare(bytes_available), ec);
+    b.commit(bytes_transferred);
+    total_transferred += bytes_transferred;
+    max_size = detail::adapt_completion_condition_result(
+          completion_condition(ec, total_transferred));
+    bytes_available = read_size_helper(b, max_size);
+  }
+  return total_transferred;
+}
+
+template <typename SyncReadStream, typename Allocator>
+inline std::size_t read(SyncReadStream& s,
+    asio::basic_streambuf<Allocator>& b)
+{
+  asio::error_code ec;
+  std::size_t bytes_transferred = read(s, b, transfer_all(), ec);
+  asio::detail::throw_error(ec);
+  return bytes_transferred;
+}
+
+template <typename SyncReadStream, typename Allocator,
+    typename CompletionCondition>
+inline std::size_t read(SyncReadStream& s,
+    asio::basic_streambuf<Allocator>& b,
+    CompletionCondition completion_condition)
+{
+  asio::error_code ec;
+  std::size_t bytes_transferred = read(s, b, completion_condition, ec);
+  asio::detail::throw_error(ec);
+  return bytes_transferred;
+}
+
+#endif // !defined(BOOST_NO_IOSTREAM)
+
+namespace detail
+{
+  template <typename AsyncReadStream, typename MutableBufferSequence,
+      typename CompletionCondition, typename ReadHandler>
+  class read_op
+    : detail::base_from_completion_cond<CompletionCondition>
+  {
+  public:
+    read_op(AsyncReadStream& stream, const MutableBufferSequence& buffers,
+        CompletionCondition completion_condition, ReadHandler handler)
+      : detail::base_from_completion_cond<
+          CompletionCondition>(completion_condition),
+        stream_(stream),
+        buffers_(buffers),
+        total_transferred_(0),
+        handler_(handler)
+    {
+    }
+
+    void operator()(const asio::error_code& ec,
+        std::size_t bytes_transferred, int start = 0)
+    {
+      switch (start)
+      {
+        case 1:
+        buffers_.prepare(this->check_for_completion(ec, total_transferred_));
+        for (;;)
+        {
+          stream_.async_read_some(buffers_, *this);
+          return; default:
+          total_transferred_ += bytes_transferred;
+          buffers_.consume(bytes_transferred);
+          buffers_.prepare(this->check_for_completion(ec, total_transferred_));
+          if ((!ec && bytes_transferred == 0)
+              || buffers_.begin() == buffers_.end())
+            break;
+        }
+
+        handler_(ec, static_cast<const std::size_t&>(total_transferred_));
+      }
+    }
+
+  //private:
+    AsyncReadStream& stream_;
+    asio::detail::consuming_buffers<
+      mutable_buffer, MutableBufferSequence> buffers_;
+    std::size_t total_transferred_;
+    ReadHandler handler_;
+  };
+
+  template <typename AsyncReadStream,
+      typename CompletionCondition, typename ReadHandler>
+  class read_op<AsyncReadStream, asio::mutable_buffers_1,
+      CompletionCondition, ReadHandler>
+    : detail::base_from_completion_cond<CompletionCondition>
+  {
+  public:
+    read_op(AsyncReadStream& stream,
+        const asio::mutable_buffers_1& buffers,
+        CompletionCondition completion_condition,
+        ReadHandler handler)
+      : detail::base_from_completion_cond<
+          CompletionCondition>(completion_condition),
+        stream_(stream),
+        buffer_(buffers),
+        total_transferred_(0),
+        handler_(handler)
+    {
+    }
+
+    void operator()(const asio::error_code& ec,
+        std::size_t bytes_transferred, int start = 0)
+    {
+      std::size_t n = 0;
+      switch (start)
+      {
+        case 1:
+        n = this->check_for_completion(ec, total_transferred_);
+        for (;;)
+        {
+          stream_.async_read_some(asio::buffer(
+                buffer_ + total_transferred_, n), *this);
+          return; default:
+          total_transferred_ += bytes_transferred;
+          if ((!ec && bytes_transferred == 0)
+              || (n = this->check_for_completion(ec, total_transferred_)) == 0
+              || total_transferred_ == asio::buffer_size(buffer_))
+            break;
+        }
+
+        handler_(ec, static_cast<const std::size_t&>(total_transferred_));
+      }
+    }
+
+  //private:
+    AsyncReadStream& stream_;
+    asio::mutable_buffer buffer_;
+    std::size_t total_transferred_;
+    ReadHandler handler_;
+  };
+
+  template <typename AsyncReadStream, typename MutableBufferSequence,
+      typename CompletionCondition, typename ReadHandler>
+  inline void* asio_handler_allocate(std::size_t size,
+      read_op<AsyncReadStream, MutableBufferSequence,
+        CompletionCondition, ReadHandler>* this_handler)
+  {
+    return asio_handler_alloc_helpers::allocate(
+        size, this_handler->handler_);
+  }
+
+  template <typename AsyncReadStream, typename MutableBufferSequence,
+      typename CompletionCondition, typename ReadHandler>
+  inline void asio_handler_deallocate(void* pointer, std::size_t size,
+      read_op<AsyncReadStream, MutableBufferSequence,
+        CompletionCondition, ReadHandler>* this_handler)
+  {
+    asio_handler_alloc_helpers::deallocate(
+        pointer, size, this_handler->handler_);
+  }
+
+  template <typename Function, typename AsyncReadStream,
+      typename MutableBufferSequence, typename CompletionCondition,
+      typename ReadHandler>
+  inline void asio_handler_invoke(const Function& function,
+      read_op<AsyncReadStream, MutableBufferSequence,
+        CompletionCondition, ReadHandler>* this_handler)
+  {
+    asio_handler_invoke_helpers::invoke(
+        function, this_handler->handler_);
+  }
+} // namespace detail
+
+template <typename AsyncReadStream, typename MutableBufferSequence,
+    typename CompletionCondition, typename ReadHandler>
+inline void async_read(AsyncReadStream& s, const MutableBufferSequence& buffers,
+    CompletionCondition completion_condition, ReadHandler handler)
+{
+  detail::read_op<AsyncReadStream, MutableBufferSequence,
+    CompletionCondition, ReadHandler>(
+      s, buffers, completion_condition, handler)(
+        asio::error_code(), 0, 1);
+}
+
+template <typename AsyncReadStream, typename MutableBufferSequence,
+    typename ReadHandler>
+inline void async_read(AsyncReadStream& s, const MutableBufferSequence& buffers,
+    ReadHandler handler)
+{
+  async_read(s, buffers, transfer_all(), handler);
+}
+
+#if !defined(BOOST_NO_IOSTREAM)
+
+namespace detail
+{
+  template <typename AsyncReadStream, typename Allocator,
+      typename CompletionCondition, typename ReadHandler>
+  class read_streambuf_op
+    : detail::base_from_completion_cond<CompletionCondition>
+  {
+  public:
+    read_streambuf_op(AsyncReadStream& stream,
+        basic_streambuf<Allocator>& streambuf,
+        CompletionCondition completion_condition, ReadHandler handler)
+      : detail::base_from_completion_cond<
+          CompletionCondition>(completion_condition),
+        stream_(stream),
+        streambuf_(streambuf),
+        total_transferred_(0),
+        handler_(handler)
+    {
+    }
+
+    void operator()(const asio::error_code& ec,
+        std::size_t bytes_transferred, int start = 0)
+    {
+      std::size_t max_size, bytes_available;
+      switch (start)
+      {
+        case 1:
+        max_size = this->check_for_completion(ec, total_transferred_);
+        bytes_available = read_size_helper(streambuf_, max_size);
+        for (;;)
+        {
+          stream_.async_read_some(streambuf_.prepare(bytes_available), *this);
+          return; default:
+          total_transferred_ += bytes_transferred;
+          streambuf_.commit(bytes_transferred);
+          max_size = this->check_for_completion(ec, total_transferred_);
+          bytes_available = read_size_helper(streambuf_, max_size);
+          if ((!ec && bytes_transferred == 0) || bytes_available == 0)
+            break;
+        }
+
+        handler_(ec, static_cast<const std::size_t&>(total_transferred_));
+      }
+    }
+
+  //private:
+    AsyncReadStream& stream_;
+    asio::basic_streambuf<Allocator>& streambuf_;
+    std::size_t total_transferred_;
+    ReadHandler handler_;
+  };
+
+  template <typename AsyncReadStream, typename Allocator,
+      typename CompletionCondition, typename ReadHandler>
+  inline void* asio_handler_allocate(std::size_t size,
+      read_streambuf_op<AsyncReadStream, Allocator,
+        CompletionCondition, ReadHandler>* this_handler)
+  {
+    return asio_handler_alloc_helpers::allocate(
+        size, this_handler->handler_);
+  }
+
+  template <typename AsyncReadStream, typename Allocator,
+      typename CompletionCondition, typename ReadHandler>
+  inline void asio_handler_deallocate(void* pointer, std::size_t size,
+      read_streambuf_op<AsyncReadStream, Allocator,
+        CompletionCondition, ReadHandler>* this_handler)
+  {
+    asio_handler_alloc_helpers::deallocate(
+        pointer, size, this_handler->handler_);
+  }
+
+  template <typename Function, typename AsyncReadStream,
+      typename Allocator, typename CompletionCondition, typename ReadHandler>
+  inline void asio_handler_invoke(const Function& function,
+      read_streambuf_op<AsyncReadStream, Allocator,
+        CompletionCondition, ReadHandler>* this_handler)
+  {
+    asio_handler_invoke_helpers::invoke(
+        function, this_handler->handler_);
+  }
+} // namespace detail
+
+template <typename AsyncReadStream, typename Allocator,
+    typename CompletionCondition, typename ReadHandler>
+inline void async_read(AsyncReadStream& s,
+    asio::basic_streambuf<Allocator>& b,
+    CompletionCondition completion_condition, ReadHandler handler)
+{
+  detail::read_streambuf_op<AsyncReadStream,
+    Allocator, CompletionCondition, ReadHandler>(
+      s, b, completion_condition, handler)(
+        asio::error_code(), 0, 1);
+}
+
+template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+inline void async_read(AsyncReadStream& s,
+    asio::basic_streambuf<Allocator>& b, ReadHandler handler)
+{
+  async_read(s, b, transfer_all(), handler);
+}
+
+#endif // !defined(BOOST_NO_IOSTREAM)
+
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_IMPL_READ_HPP
diff --git a/ext/asio/asio/impl/read_at.hpp b/ext/asio/asio/impl/read_at.hpp
new file mode 100644
index 0000000..da57fe3
--- /dev/null
+++ b/ext/asio/asio/impl/read_at.hpp
@@ -0,0 +1,410 @@
+//
+// impl/read_at.hpp
+// ~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_IMPL_READ_AT_HPP
+#define ASIO_IMPL_READ_AT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <algorithm>
+#include "asio/buffer.hpp"
+#include "asio/completion_condition.hpp"
+#include "asio/detail/base_from_completion_cond.hpp"
+#include "asio/detail/bind_handler.hpp"
+#include "asio/detail/consuming_buffers.hpp"
+#include "asio/detail/handler_alloc_helpers.hpp"
+#include "asio/detail/handler_invoke_helpers.hpp"
+#include "asio/detail/throw_error.hpp"
+#include "asio/error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+
+template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence,
+    typename CompletionCondition>
+std::size_t read_at(SyncRandomAccessReadDevice& d,
+    boost::uint64_t offset, const MutableBufferSequence& buffers,
+    CompletionCondition completion_condition, asio::error_code& ec)
+{
+  ec = asio::error_code();
+  asio::detail::consuming_buffers<
+    mutable_buffer, MutableBufferSequence> tmp(buffers);
+  std::size_t total_transferred = 0;
+  tmp.prepare(detail::adapt_completion_condition_result(
+        completion_condition(ec, total_transferred)));
+  while (tmp.begin() != tmp.end())
+  {
+    std::size_t bytes_transferred = d.read_some_at(
+        offset + total_transferred, tmp, ec);
+    tmp.consume(bytes_transferred);
+    total_transferred += bytes_transferred;
+    tmp.prepare(detail::adapt_completion_condition_result(
+          completion_condition(ec, total_transferred)));
+  }
+  return total_transferred;
+}
+
+template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence>
+inline std::size_t read_at(SyncRandomAccessReadDevice& d,
+    boost::uint64_t offset, const MutableBufferSequence& buffers)
+{
+  asio::error_code ec;
+  std::size_t bytes_transferred = read_at(
+      d, offset, buffers, transfer_all(), ec);
+  asio::detail::throw_error(ec);
+  return bytes_transferred;
+}
+
+template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence,
+    typename CompletionCondition>
+inline std::size_t read_at(SyncRandomAccessReadDevice& d,
+    boost::uint64_t offset, const MutableBufferSequence& buffers,
+    CompletionCondition completion_condition)
+{
+  asio::error_code ec;
+  std::size_t bytes_transferred = read_at(
+      d, offset, buffers, completion_condition, ec);
+  asio::detail::throw_error(ec);
+  return bytes_transferred;
+}
+
+#if !defined(BOOST_NO_IOSTREAM)
+
+template <typename SyncRandomAccessReadDevice, typename Allocator,
+    typename CompletionCondition>
+std::size_t read_at(SyncRandomAccessReadDevice& d,
+    boost::uint64_t offset, asio::basic_streambuf<Allocator>& b,
+    CompletionCondition completion_condition, asio::error_code& ec)
+{
+  ec = asio::error_code();
+  std::size_t total_transferred = 0;
+  std::size_t max_size = detail::adapt_completion_condition_result(
+        completion_condition(ec, total_transferred));
+  std::size_t bytes_available = read_size_helper(b, max_size);
+  while (bytes_available > 0)
+  {
+    std::size_t bytes_transferred = d.read_some_at(
+        offset + total_transferred, b.prepare(bytes_available), ec);
+    b.commit(bytes_transferred);
+    total_transferred += bytes_transferred;
+    max_size = detail::adapt_completion_condition_result(
+          completion_condition(ec, total_transferred));
+    bytes_available = read_size_helper(b, max_size);
+  }
+  return total_transferred;
+}
+
+template <typename SyncRandomAccessReadDevice, typename Allocator>
+inline std::size_t read_at(SyncRandomAccessReadDevice& d,
+    boost::uint64_t offset, asio::basic_streambuf<Allocator>& b)
+{
+  asio::error_code ec;
+  std::size_t bytes_transferred = read_at(
+      d, offset, b, transfer_all(), ec);
+  asio::detail::throw_error(ec);
+  return bytes_transferred;
+}
+
+template <typename SyncRandomAccessReadDevice, typename Allocator,
+    typename CompletionCondition>
+inline std::size_t read_at(SyncRandomAccessReadDevice& d,
+    boost::uint64_t offset, asio::basic_streambuf<Allocator>& b,
+    CompletionCondition completion_condition)
+{
+  asio::error_code ec;
+  std::size_t bytes_transferred = read_at(
+      d, offset, b, completion_condition, ec);
+  asio::detail::throw_error(ec);
+  return bytes_transferred;
+}
+
+#endif // !defined(BOOST_NO_IOSTREAM)
+
+namespace detail
+{
+  template <typename AsyncRandomAccessReadDevice,
+      typename MutableBufferSequence, typename CompletionCondition,
+      typename ReadHandler>
+  class read_at_op
+    : detail::base_from_completion_cond<CompletionCondition>
+  {
+  public:
+    read_at_op(AsyncRandomAccessReadDevice& device,
+        boost::uint64_t offset, const MutableBufferSequence& buffers,
+        CompletionCondition completion_condition, ReadHandler handler)
+      : detail::base_from_completion_cond<
+          CompletionCondition>(completion_condition),
+        device_(device),
+        offset_(offset),
+        buffers_(buffers),
+        total_transferred_(0),
+        handler_(handler)
+    {
+    }
+
+    void operator()(const asio::error_code& ec,
+        std::size_t bytes_transferred, int start = 0)
+    {
+      switch (start)
+      {
+        case 1:
+        buffers_.prepare(this->check_for_completion(ec, total_transferred_));
+        for (;;)
+        {
+          device_.async_read_some_at(
+              offset_ + total_transferred_, buffers_, *this);
+          return; default:
+          total_transferred_ += bytes_transferred;
+          buffers_.consume(bytes_transferred);
+          buffers_.prepare(this->check_for_completion(ec, total_transferred_));
+          if ((!ec && bytes_transferred == 0)
+              || buffers_.begin() == buffers_.end())
+            break;
+        }
+
+        handler_(ec, static_cast<const std::size_t&>(total_transferred_));
+      }
+    }
+
+  //private:
+    AsyncRandomAccessReadDevice& device_;
+    boost::uint64_t offset_;
+    asio::detail::consuming_buffers<
+      mutable_buffer, MutableBufferSequence> buffers_;
+    std::size_t total_transferred_;
+    ReadHandler handler_;
+  };
+
+  template <typename AsyncRandomAccessReadDevice,
+      typename CompletionCondition, typename ReadHandler>
+  class read_at_op<AsyncRandomAccessReadDevice,
+      asio::mutable_buffers_1, CompletionCondition, ReadHandler>
+    : detail::base_from_completion_cond<CompletionCondition>
+  {
+  public:
+    read_at_op(AsyncRandomAccessReadDevice& device,
+        boost::uint64_t offset, const asio::mutable_buffers_1& buffers,
+        CompletionCondition completion_condition, ReadHandler handler)
+      : detail::base_from_completion_cond<
+          CompletionCondition>(completion_condition),
+        device_(device),
+        offset_(offset),
+        buffer_(buffers),
+        total_transferred_(0),
+        handler_(handler)
+    {
+    }
+
+    void operator()(const asio::error_code& ec,
+        std::size_t bytes_transferred, int start = 0)
+    {
+      std::size_t n = 0;
+      switch (start)
+      {
+        case 1:
+        n = this->check_for_completion(ec, total_transferred_);
+        for (;;)
+        {
+          device_.async_read_some_at(offset_ + total_transferred_,
+              asio::buffer(buffer_ + total_transferred_, n), *this);
+          return; default:
+          total_transferred_ += bytes_transferred;
+          if ((!ec && bytes_transferred == 0)
+              || (n = this->check_for_completion(ec, total_transferred_)) == 0
+              || total_transferred_ == asio::buffer_size(buffer_))
+            break;
+        }
+
+        handler_(ec, static_cast<const std::size_t&>(total_transferred_));
+      }
+    }
+
+  //private:
+    AsyncRandomAccessReadDevice& device_;
+    boost::uint64_t offset_;
+    asio::mutable_buffer buffer_;
+    std::size_t total_transferred_;
+    ReadHandler handler_;
+  };
+
+  template <typename AsyncRandomAccessReadDevice,
+      typename MutableBufferSequence, typename CompletionCondition,
+      typename ReadHandler>
+  inline void* asio_handler_allocate(std::size_t size,
+      read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
+        CompletionCondition, ReadHandler>* this_handler)
+  {
+    return asio_handler_alloc_helpers::allocate(
+        size, this_handler->handler_);
+  }
+
+  template <typename AsyncRandomAccessReadDevice,
+      typename MutableBufferSequence, typename CompletionCondition,
+      typename ReadHandler>
+  inline void asio_handler_deallocate(void* pointer, std::size_t size,
+      read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
+        CompletionCondition, ReadHandler>* this_handler)
+  {
+    asio_handler_alloc_helpers::deallocate(
+        pointer, size, this_handler->handler_);
+  }
+
+  template <typename Function, typename AsyncRandomAccessReadDevice,
+      typename MutableBufferSequence, typename CompletionCondition,
+      typename ReadHandler>
+  inline void asio_handler_invoke(const Function& function,
+      read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
+        CompletionCondition, ReadHandler>* this_handler)
+  {
+    asio_handler_invoke_helpers::invoke(
+        function, this_handler->handler_);
+  }
+} // namespace detail
+
+template <typename AsyncRandomAccessReadDevice, typename MutableBufferSequence,
+    typename CompletionCondition, typename ReadHandler>
+inline void async_read_at(AsyncRandomAccessReadDevice& d,
+    boost::uint64_t offset, const MutableBufferSequence& buffers,
+    CompletionCondition completion_condition, ReadHandler handler)
+{
+  detail::read_at_op<AsyncRandomAccessReadDevice,
+    MutableBufferSequence, CompletionCondition, ReadHandler>(
+      d, offset, buffers, completion_condition, handler)(
+        asio::error_code(), 0, 1);
+}
+
+template <typename AsyncRandomAccessReadDevice, typename MutableBufferSequence,
+    typename ReadHandler>
+inline void async_read_at(AsyncRandomAccessReadDevice& d,
+    boost::uint64_t offset, const MutableBufferSequence& buffers,
+    ReadHandler handler)
+{
+  async_read_at(d, offset, buffers, transfer_all(), handler);
+}
+
+#if !defined(BOOST_NO_IOSTREAM)
+
+namespace detail
+{
+  template <typename AsyncRandomAccessReadDevice, typename Allocator,
+      typename CompletionCondition, typename ReadHandler>
+  class read_at_streambuf_op
+    : detail::base_from_completion_cond<CompletionCondition>
+  {
+  public:
+    read_at_streambuf_op(AsyncRandomAccessReadDevice& device,
+        boost::uint64_t offset, basic_streambuf<Allocator>& streambuf,
+        CompletionCondition completion_condition, ReadHandler handler)
+      : detail::base_from_completion_cond<
+          CompletionCondition>(completion_condition),
+        device_(device),
+        offset_(offset),
+        streambuf_(streambuf),
+        total_transferred_(0),
+        handler_(handler)
+    {
+    }
+
+    void operator()(const asio::error_code& ec,
+        std::size_t bytes_transferred, int start = 0)
+    {
+      std::size_t max_size, bytes_available;
+      switch (start)
+      {
+        case 1:
+        max_size = this->check_for_completion(ec, total_transferred_);
+        bytes_available = read_size_helper(streambuf_, max_size);
+        for (;;)
+        {
+          device_.async_read_some_at(offset_ + total_transferred_,
+              streambuf_.prepare(bytes_available), *this);
+          return; default:
+          total_transferred_ += bytes_transferred;
+          streambuf_.commit(bytes_transferred);
+          max_size = this->check_for_completion(ec, total_transferred_);
+          bytes_available = read_size_helper(streambuf_, max_size);
+          if ((!ec && bytes_transferred == 0) || bytes_available == 0)
+            break;
+        }
+
+        handler_(ec, static_cast<const std::size_t&>(total_transferred_));
+      }
+    }
+
+  //private:
+    AsyncRandomAccessReadDevice& device_;
+    boost::uint64_t offset_;
+    asio::basic_streambuf<Allocator>& streambuf_;
+    std::size_t total_transferred_;
+    ReadHandler handler_;
+  };
+
+  template <typename AsyncRandomAccessReadDevice, typename Allocator,
+      typename CompletionCondition, typename ReadHandler>
+  inline void* asio_handler_allocate(std::size_t size,
+      read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
+        CompletionCondition, ReadHandler>* this_handler)
+  {
+    return asio_handler_alloc_helpers::allocate(
+        size, this_handler->handler_);
+  }
+
+  template <typename AsyncRandomAccessReadDevice, typename Allocator,
+      typename CompletionCondition, typename ReadHandler>
+  inline void asio_handler_deallocate(void* pointer, std::size_t size,
+      read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
+        CompletionCondition, ReadHandler>* this_handler)
+  {
+    asio_handler_alloc_helpers::deallocate(
+        pointer, size, this_handler->handler_);
+  }
+
+  template <typename Function, typename AsyncRandomAccessReadDevice,
+      typename Allocator, typename CompletionCondition, typename ReadHandler>
+  inline void asio_handler_invoke(const Function& function,
+      read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
+        CompletionCondition, ReadHandler>* this_handler)
+  {
+    asio_handler_invoke_helpers::invoke(
+        function, this_handler->handler_);
+  }
+} // namespace detail
+
+template <typename AsyncRandomAccessReadDevice, typename Allocator,
+    typename CompletionCondition, typename ReadHandler>
+inline void async_read_at(AsyncRandomAccessReadDevice& d,
+    boost::uint64_t offset, asio::basic_streambuf<Allocator>& b,
+    CompletionCondition completion_condition, ReadHandler handler)
+{
+  detail::read_at_streambuf_op<AsyncRandomAccessReadDevice,
+    Allocator, CompletionCondition, ReadHandler>(
+      d, offset, b, completion_condition, handler)(
+        asio::error_code(), 0, 1);
+}
+
+template <typename AsyncRandomAccessReadDevice, typename Allocator,
+    typename ReadHandler>
+inline void async_read_at(AsyncRandomAccessReadDevice& d,
+    boost::uint64_t offset, asio::basic_streambuf<Allocator>& b,
+    ReadHandler handler)
+{
+  async_read_at(d, offset, b, transfer_all(), handler);
+}
+
+#endif // !defined(BOOST_NO_IOSTREAM)
+
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_IMPL_READ_AT_HPP
diff --git a/ext/asio/asio/impl/read_until.hpp b/ext/asio/asio/impl/read_until.hpp
new file mode 100644
index 0000000..ceacca7
--- /dev/null
+++ b/ext/asio/asio/impl/read_until.hpp
@@ -0,0 +1,902 @@
+//
+// impl/read_until.hpp
+// ~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_IMPL_READ_UNTIL_HPP
+#define ASIO_IMPL_READ_UNTIL_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <algorithm>
+#include <string>
+#include <vector>
+#include <utility>
+#include <boost/limits.hpp>
+#include "asio/buffer.hpp"
+#include "asio/buffers_iterator.hpp"
+#include "asio/detail/bind_handler.hpp"
+#include "asio/detail/handler_alloc_helpers.hpp"
+#include "asio/detail/handler_invoke_helpers.hpp"
+#include "asio/detail/throw_error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+
+template <typename SyncReadStream, typename Allocator>
+inline std::size_t read_until(SyncReadStream& s,
+    asio::basic_streambuf<Allocator>& b, char delim)
+{
+  asio::error_code ec;
+  std::size_t bytes_transferred = read_until(s, b, delim, ec);
+  asio::detail::throw_error(ec);
+  return bytes_transferred;
+}
+
+template <typename SyncReadStream, typename Allocator>
+std::size_t read_until(SyncReadStream& s,
+    asio::basic_streambuf<Allocator>& b, char delim,
+    asio::error_code& ec)
+{
+  std::size_t search_position = 0;
+  for (;;)
+  {
+    // Determine the range of the data to be searched.
+    typedef typename asio::basic_streambuf<
+      Allocator>::const_buffers_type const_buffers_type;
+    typedef asio::buffers_iterator<const_buffers_type> iterator;
+    const_buffers_type buffers = b.data();
+    iterator begin = iterator::begin(buffers);
+    iterator start = begin + search_position;
+    iterator end = iterator::end(buffers);
+
+    // Look for a match.
+    iterator iter = std::find(start, end, delim);
+    if (iter != end)
+    {
+      // Found a match. We're done.
+      ec = asio::error_code();
+      return iter - begin + 1;
+    }
+    else
+    {
+      // No match. Next search can start with the new data.
+      search_position = end - begin;
+    }
+
+    // Check if buffer is full.
+    if (b.size() == b.max_size())
+    {
+      ec = error::not_found;
+      return 0;
+    }
+
+    // Need more data.
+    std::size_t bytes_to_read = read_size_helper(b, 65536);
+    b.commit(s.read_some(b.prepare(bytes_to_read), ec));
+    if (ec)
+      return 0;
+  }
+}
+
+template <typename SyncReadStream, typename Allocator>
+inline std::size_t read_until(SyncReadStream& s,
+    asio::basic_streambuf<Allocator>& b, const std::string& delim)
+{
+  asio::error_code ec;
+  std::size_t bytes_transferred = read_until(s, b, delim, ec);
+  asio::detail::throw_error(ec);
+  return bytes_transferred;
+}
+
+namespace detail
+{
+  // Algorithm that finds a subsequence of equal values in a sequence. Returns
+  // (iterator,true) if a full match was found, in which case the iterator
+  // points to the beginning of the match. Returns (iterator,false) if a
+  // partial match was found at the end of the first sequence, in which case
+  // the iterator points to the beginning of the partial match. Returns
+  // (last1,false) if no full or partial match was found.
+  template <typename Iterator1, typename Iterator2>
+  std::pair<Iterator1, bool> partial_search(
+      Iterator1 first1, Iterator1 last1, Iterator2 first2, Iterator2 last2)
+  {
+    for (Iterator1 iter1 = first1; iter1 != last1; ++iter1)
+    {
+      Iterator1 test_iter1 = iter1;
+      Iterator2 test_iter2 = first2;
+      for (;; ++test_iter1, ++test_iter2)
+      {
+        if (test_iter2 == last2)
+          return std::make_pair(iter1, true);
+        if (test_iter1 == last1)
+        {
+          if (test_iter2 != first2)
+            return std::make_pair(iter1, false);
+          else
+            break;
+        }
+        if (*test_iter1 != *test_iter2)
+          break;
+      }
+    }
+    return std::make_pair(last1, false);
+  }
+} // namespace detail
+
+template <typename SyncReadStream, typename Allocator>
+std::size_t read_until(SyncReadStream& s,
+    asio::basic_streambuf<Allocator>& b, const std::string& delim,
+    asio::error_code& ec)
+{
+  std::size_t search_position = 0;
+  for (;;)
+  {
+    // Determine the range of the data to be searched.
+    typedef typename asio::basic_streambuf<
+      Allocator>::const_buffers_type const_buffers_type;
+    typedef asio::buffers_iterator<const_buffers_type> iterator;
+    const_buffers_type buffers = b.data();
+    iterator begin = iterator::begin(buffers);
+    iterator start = begin + search_position;
+    iterator end = iterator::end(buffers);
+
+    // Look for a match.
+    std::pair<iterator, bool> result = detail::partial_search(
+        start, end, delim.begin(), delim.end());
+    if (result.first != end)
+    {
+      if (result.second)
+      {
+        // Full match. We're done.
+        ec = asio::error_code();
+        return result.first - begin + delim.length();
+      }
+      else
+      {
+        // Partial match. Next search needs to start from beginning of match.
+        search_position = result.first - begin;
+      }
+    }
+    else
+    {
+      // No match. Next search can start with the new data.
+      search_position = end - begin;
+    }
+
+    // Check if buffer is full.
+    if (b.size() == b.max_size())
+    {
+      ec = error::not_found;
+      return 0;
+    }
+
+    // Need more data.
+    std::size_t bytes_to_read = read_size_helper(b, 65536);
+    b.commit(s.read_some(b.prepare(bytes_to_read), ec));
+    if (ec)
+      return 0;
+  }
+}
+
+template <typename SyncReadStream, typename Allocator>
+inline std::size_t read_until(SyncReadStream& s,
+    asio::basic_streambuf<Allocator>& b, const boost::regex& expr)
+{
+  asio::error_code ec;
+  std::size_t bytes_transferred = read_until(s, b, expr, ec);
+  asio::detail::throw_error(ec);
+  return bytes_transferred;
+}
+
+template <typename SyncReadStream, typename Allocator>
+std::size_t read_until(SyncReadStream& s,
+    asio::basic_streambuf<Allocator>& b, const boost::regex& expr,
+    asio::error_code& ec)
+{
+  std::size_t search_position = 0;
+  for (;;)
+  {
+    // Determine the range of the data to be searched.
+    typedef typename asio::basic_streambuf<
+      Allocator>::const_buffers_type const_buffers_type;
+    typedef asio::buffers_iterator<const_buffers_type> iterator;
+    const_buffers_type buffers = b.data();
+    iterator begin = iterator::begin(buffers);
+    iterator start = begin + search_position;
+    iterator end = iterator::end(buffers);
+
+    // Look for a match.
+    boost::match_results<iterator,
+      typename std::vector<boost::sub_match<iterator> >::allocator_type>
+        match_results;
+    if (regex_search(start, end, match_results, expr,
+          boost::match_default | boost::match_partial))
+    {
+      if (match_results[0].matched)
+      {
+        // Full match. We're done.
+        ec = asio::error_code();
+        return match_results[0].second - begin;
+      }
+      else
+      {
+        // Partial match. Next search needs to start from beginning of match.
+        search_position = match_results[0].first - begin;
+      }
+    }
+    else
+    {
+      // No match. Next search can start with the new data.
+      search_position = end - begin;
+    }
+
+    // Check if buffer is full.
+    if (b.size() == b.max_size())
+    {
+      ec = error::not_found;
+      return 0;
+    }
+
+    // Need more data.
+    std::size_t bytes_to_read = read_size_helper(b, 65536);
+    b.commit(s.read_some(b.prepare(bytes_to_read), ec));
+    if (ec)
+      return 0;
+  }
+}
+
+template <typename SyncReadStream, typename Allocator, typename MatchCondition>
+std::size_t read_until(SyncReadStream& s,
+    asio::basic_streambuf<Allocator>& b,
+    MatchCondition match_condition, asio::error_code& ec,
+    typename boost::enable_if<is_match_condition<MatchCondition> >::type*)
+{
+  std::size_t search_position = 0;
+  for (;;)
+  {
+    // Determine the range of the data to be searched.
+    typedef typename asio::basic_streambuf<
+      Allocator>::const_buffers_type const_buffers_type;
+    typedef asio::buffers_iterator<const_buffers_type> iterator;
+    const_buffers_type buffers = b.data();
+    iterator begin = iterator::begin(buffers);
+    iterator start = begin + search_position;
+    iterator end = iterator::end(buffers);
+
+    // Look for a match.
+    std::pair<iterator, bool> result = match_condition(start, end);
+    if (result.second)
+    {
+      // Full match. We're done.
+      ec = asio::error_code();
+      return result.first - begin;
+    }
+    else if (result.first != end)
+    {
+      // Partial match. Next search needs to start from beginning of match.
+      search_position = result.first - begin;
+    }
+    else
+    {
+      // No match. Next search can start with the new data.
+      search_position = end - begin;
+    }
+
+    // Check if buffer is full.
+    if (b.size() == b.max_size())
+    {
+      ec = error::not_found;
+      return 0;
+    }
+
+    // Need more data.
+    std::size_t bytes_to_read = read_size_helper(b, 65536);
+    b.commit(s.read_some(b.prepare(bytes_to_read), ec));
+    if (ec)
+      return 0;
+  }
+}
+
+template <typename SyncReadStream, typename Allocator, typename MatchCondition>
+inline std::size_t read_until(SyncReadStream& s,
+    asio::basic_streambuf<Allocator>& b, MatchCondition match_condition,
+    typename boost::enable_if<is_match_condition<MatchCondition> >::type*)
+{
+  asio::error_code ec;
+  std::size_t bytes_transferred = read_until(s, b, match_condition, ec);
+  asio::detail::throw_error(ec);
+  return bytes_transferred;
+}
+
+namespace detail
+{
+  template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+  class read_until_delim_op
+  {
+  public:
+    read_until_delim_op(AsyncReadStream& stream,
+        asio::basic_streambuf<Allocator>& streambuf,
+        char delim, ReadHandler handler)
+      : stream_(stream),
+        streambuf_(streambuf),
+        delim_(delim),
+        search_position_(0),
+        handler_(handler)
+    {
+    }
+
+    void operator()(const asio::error_code& ec,
+        std::size_t bytes_transferred, int start = 0)
+    {
+      const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
+      std::size_t bytes_to_read;
+      switch (start)
+      {
+      case 1:
+        for (;;)
+        {
+          {
+            // Determine the range of the data to be searched.
+            typedef typename asio::basic_streambuf<
+              Allocator>::const_buffers_type const_buffers_type;
+            typedef asio::buffers_iterator<const_buffers_type> iterator;
+            const_buffers_type buffers = streambuf_.data();
+            iterator begin = iterator::begin(buffers);
+            iterator start = begin + search_position_;
+            iterator end = iterator::end(buffers);
+
+            // Look for a match.
+            iterator iter = std::find(start, end, delim_);
+            if (iter != end)
+            {
+              // Found a match. We're done.
+              search_position_ = iter - begin + 1;
+              bytes_to_read = 0;
+            }
+
+            // No match yet. Check if buffer is full.
+            else if (streambuf_.size() == streambuf_.max_size())
+            {
+              search_position_ = not_found;
+              bytes_to_read = 0;
+            }
+
+            // Need to read some more data.
+            else
+            {
+              // Next search can start with the new data.
+              search_position_ = end - begin;
+              bytes_to_read = read_size_helper(streambuf_, 65536);
+            }
+          }
+
+          // Check if we're done.
+          if (!start && bytes_to_read == 0)
+            break;
+
+          // Start a new asynchronous read operation to obtain more data.
+          stream_.async_read_some(streambuf_.prepare(bytes_to_read), *this);
+          return; default:
+          streambuf_.commit(bytes_transferred);
+          if (ec || bytes_transferred == 0)
+            break;
+        }
+
+        const asio::error_code result_ec =
+          (search_position_ == not_found)
+          ? error::not_found : ec;
+
+        const std::size_t result_n =
+          (ec || search_position_ == not_found)
+          ? 0 : search_position_;
+
+        handler_(result_ec, result_n);
+      }
+    }
+
+  //private:
+    AsyncReadStream& stream_;
+    asio::basic_streambuf<Allocator>& streambuf_;
+    char delim_;
+    std::size_t search_position_;
+    ReadHandler handler_;
+  };
+
+  template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+  inline void* asio_handler_allocate(std::size_t size,
+      read_until_delim_op<AsyncReadStream,
+        Allocator, ReadHandler>* this_handler)
+  {
+    return asio_handler_alloc_helpers::allocate(
+        size, this_handler->handler_);
+  }
+
+  template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+  inline void asio_handler_deallocate(void* pointer, std::size_t size,
+      read_until_delim_op<AsyncReadStream,
+        Allocator, ReadHandler>* this_handler)
+  {
+    asio_handler_alloc_helpers::deallocate(
+        pointer, size, this_handler->handler_);
+  }
+
+  template <typename Function, typename AsyncReadStream, typename Allocator,
+      typename ReadHandler>
+  inline void asio_handler_invoke(const Function& function,
+      read_until_delim_op<AsyncReadStream,
+        Allocator, ReadHandler>* this_handler)
+  {
+    asio_handler_invoke_helpers::invoke(
+        function, this_handler->handler_);
+  }
+} // namespace detail
+
+template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+void async_read_until(AsyncReadStream& s,
+    asio::basic_streambuf<Allocator>& b, char delim, ReadHandler handler)
+{
+  detail::read_until_delim_op<
+    AsyncReadStream, Allocator, ReadHandler>(
+      s, b, delim, handler)(
+        asio::error_code(), 0, 1);
+}
+
+namespace detail
+{
+  template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+  class read_until_delim_string_op
+  {
+  public:
+    read_until_delim_string_op(AsyncReadStream& stream,
+        asio::basic_streambuf<Allocator>& streambuf,
+        const std::string& delim, ReadHandler handler)
+      : stream_(stream),
+        streambuf_(streambuf),
+        delim_(delim),
+        search_position_(0),
+        handler_(handler)
+    {
+    }
+
+    void operator()(const asio::error_code& ec,
+        std::size_t bytes_transferred, int start = 0)
+    {
+      const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
+      std::size_t bytes_to_read;
+      switch (start)
+      {
+      case 1:
+        for (;;)
+        {
+          {
+            // Determine the range of the data to be searched.
+            typedef typename asio::basic_streambuf<
+              Allocator>::const_buffers_type const_buffers_type;
+            typedef asio::buffers_iterator<const_buffers_type> iterator;
+            const_buffers_type buffers = streambuf_.data();
+            iterator begin = iterator::begin(buffers);
+            iterator start = begin + search_position_;
+            iterator end = iterator::end(buffers);
+
+            // Look for a match.
+            std::pair<iterator, bool> result = detail::partial_search(
+                start, end, delim_.begin(), delim_.end());
+            if (result.first != end && result.second)
+            {
+              // Full match. We're done.
+              search_position_ = result.first - begin + delim_.length();
+              bytes_to_read = 0;
+            }
+
+            // No match yet. Check if buffer is full.
+            else if (streambuf_.size() == streambuf_.max_size())
+            {
+              search_position_ = not_found;
+              bytes_to_read = 0;
+            }
+
+            // Need to read some more data.
+            else
+            {
+              if (result.first != end)
+              {
+                // Partial match. Next search needs to start from beginning of
+                // match.
+                search_position_ = result.first - begin;
+              }
+              else
+              {
+                // Next search can start with the new data.
+                search_position_ = end - begin;
+              }
+
+              bytes_to_read = read_size_helper(streambuf_, 65536);
+            }
+          }
+
+          // Check if we're done.
+          if (!start && bytes_to_read == 0)
+            break;
+
+          // Start a new asynchronous read operation to obtain more data.
+          stream_.async_read_some(streambuf_.prepare(bytes_to_read), *this);
+          return; default:
+          streambuf_.commit(bytes_transferred);
+          if (ec || bytes_transferred == 0)
+            break;
+        }
+
+        const asio::error_code result_ec =
+          (search_position_ == not_found)
+          ? error::not_found : ec;
+
+        const std::size_t result_n =
+          (ec || search_position_ == not_found)
+          ? 0 : search_position_;
+
+        handler_(result_ec, result_n);
+      }
+    }
+
+  //private:
+    AsyncReadStream& stream_;
+    asio::basic_streambuf<Allocator>& streambuf_;
+    std::string delim_;
+    std::size_t search_position_;
+    ReadHandler handler_;
+  };
+
+  template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+  inline void* asio_handler_allocate(std::size_t size,
+      read_until_delim_string_op<AsyncReadStream,
+        Allocator, ReadHandler>* this_handler)
+  {
+    return asio_handler_alloc_helpers::allocate(
+        size, this_handler->handler_);
+  }
+
+  template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+  inline void asio_handler_deallocate(void* pointer, std::size_t size,
+      read_until_delim_string_op<AsyncReadStream,
+        Allocator, ReadHandler>* this_handler)
+  {
+    asio_handler_alloc_helpers::deallocate(
+        pointer, size, this_handler->handler_);
+  }
+
+  template <typename Function, typename AsyncReadStream,
+      typename Allocator, typename ReadHandler>
+  inline void asio_handler_invoke(const Function& function,
+      read_until_delim_string_op<AsyncReadStream,
+        Allocator, ReadHandler>* this_handler)
+  {
+    asio_handler_invoke_helpers::invoke(
+        function, this_handler->handler_);
+  }
+} // namespace detail
+
+template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+void async_read_until(AsyncReadStream& s,
+    asio::basic_streambuf<Allocator>& b, const std::string& delim,
+    ReadHandler handler)
+{
+  detail::read_until_delim_string_op<
+    AsyncReadStream, Allocator, ReadHandler>(
+      s, b, delim, handler)(
+        asio::error_code(), 0, 1);
+}
+
+namespace detail
+{
+  template <typename AsyncReadStream, typename Allocator,
+      typename RegEx, typename ReadHandler>
+  class read_until_expr_op
+  {
+  public:
+    read_until_expr_op(AsyncReadStream& stream,
+        asio::basic_streambuf<Allocator>& streambuf,
+        const boost::regex& expr, ReadHandler handler)
+      : stream_(stream),
+        streambuf_(streambuf),
+        expr_(expr),
+        search_position_(0),
+        handler_(handler)
+    {
+    }
+
+    void operator()(const asio::error_code& ec,
+        std::size_t bytes_transferred, int start = 0)
+    {
+      const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
+      std::size_t bytes_to_read;
+      switch (start)
+      {
+      case 1:
+        for (;;)
+        {
+          {
+            // Determine the range of the data to be searched.
+            typedef typename asio::basic_streambuf<
+              Allocator>::const_buffers_type const_buffers_type;
+            typedef asio::buffers_iterator<const_buffers_type> iterator;
+            const_buffers_type buffers = streambuf_.data();
+            iterator begin = iterator::begin(buffers);
+            iterator start = begin + search_position_;
+            iterator end = iterator::end(buffers);
+
+            // Look for a match.
+            boost::match_results<iterator,
+              typename std::vector<boost::sub_match<iterator> >::allocator_type>
+                match_results;
+            bool match = regex_search(start, end, match_results, expr_,
+                boost::match_default | boost::match_partial);
+            if (match && match_results[0].matched)
+            {
+              // Full match. We're done.
+              search_position_ = match_results[0].second - begin;
+              bytes_to_read = 0;
+            }
+
+            // No match yet. Check if buffer is full.
+            else if (streambuf_.size() == streambuf_.max_size())
+            {
+              search_position_ = not_found;
+              bytes_to_read = 0;
+            }
+
+            // Need to read some more data.
+            else
+            {
+              if (match)
+              {
+                // Partial match. Next search needs to start from beginning of
+                // match.
+                search_position_ = match_results[0].first - begin;
+              }
+              else
+              {
+                // Next search can start with the new data.
+                search_position_ = end - begin;
+              }
+
+              bytes_to_read = read_size_helper(streambuf_, 65536);
+            }
+          }
+
+          // Check if we're done.
+          if (!start && bytes_to_read == 0)
+            break;
+
+          // Start a new asynchronous read operation to obtain more data.
+          stream_.async_read_some(streambuf_.prepare(bytes_to_read), *this);
+          return; default:
+          streambuf_.commit(bytes_transferred);
+          if (ec || bytes_transferred == 0)
+            break;
+        }
+
+        const asio::error_code result_ec =
+          (search_position_ == not_found)
+          ? error::not_found : ec;
+
+        const std::size_t result_n =
+          (ec || search_position_ == not_found)
+          ? 0 : search_position_;
+
+        handler_(result_ec, result_n);
+      }
+    }
+
+  //private:
+    AsyncReadStream& stream_;
+    asio::basic_streambuf<Allocator>& streambuf_;
+    RegEx expr_;
+    std::size_t search_position_;
+    ReadHandler handler_;
+  };
+
+  template <typename AsyncReadStream, typename Allocator,
+      typename RegEx, typename ReadHandler>
+  inline void* asio_handler_allocate(std::size_t size,
+      read_until_expr_op<AsyncReadStream,
+        Allocator, RegEx, ReadHandler>* this_handler)
+  {
+    return asio_handler_alloc_helpers::allocate(
+        size, this_handler->handler_);
+  }
+
+  template <typename AsyncReadStream, typename Allocator,
+      typename RegEx, typename ReadHandler>
+  inline void asio_handler_deallocate(void* pointer, std::size_t size,
+      read_until_expr_op<AsyncReadStream,
+        Allocator, RegEx, ReadHandler>* this_handler)
+  {
+    asio_handler_alloc_helpers::deallocate(
+        pointer, size, this_handler->handler_);
+  }
+
+  template <typename Function, typename AsyncReadStream, typename Allocator,
+      typename RegEx, typename ReadHandler>
+  inline void asio_handler_invoke(const Function& function,
+      read_until_expr_op<AsyncReadStream,
+        Allocator, RegEx, ReadHandler>* this_handler)
+  {
+    asio_handler_invoke_helpers::invoke(
+        function, this_handler->handler_);
+  }
+} // namespace detail
+
+template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+void async_read_until(AsyncReadStream& s,
+    asio::basic_streambuf<Allocator>& b, const boost::regex& expr,
+    ReadHandler handler)
+{
+  detail::read_until_expr_op<AsyncReadStream,
+    Allocator, boost::regex, ReadHandler>(
+      s, b, expr, handler)(
+        asio::error_code(), 0, 1);
+}
+
+namespace detail
+{
+  template <typename AsyncReadStream, typename Allocator,
+      typename MatchCondition, typename ReadHandler>
+  class read_until_match_op
+  {
+  public:
+    read_until_match_op(AsyncReadStream& stream,
+        asio::basic_streambuf<Allocator>& streambuf,
+        MatchCondition match_condition, ReadHandler handler)
+      : stream_(stream),
+        streambuf_(streambuf),
+        match_condition_(match_condition),
+        search_position_(0),
+        handler_(handler)
+    {
+    }
+
+    void operator()(const asio::error_code& ec,
+        std::size_t bytes_transferred, int start = 0)
+    {
+      const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
+      std::size_t bytes_to_read;
+      switch (start)
+      {
+      case 1:
+        for (;;)
+        {
+          {
+            // Determine the range of the data to be searched.
+            typedef typename asio::basic_streambuf<
+              Allocator>::const_buffers_type const_buffers_type;
+            typedef asio::buffers_iterator<const_buffers_type> iterator;
+            const_buffers_type buffers = streambuf_.data();
+            iterator begin = iterator::begin(buffers);
+            iterator start = begin + search_position_;
+            iterator end = iterator::end(buffers);
+
+            // Look for a match.
+            std::pair<iterator, bool> result = match_condition_(start, end);
+            if (result.second)
+            {
+              // Full match. We're done.
+              search_position_ = result.first - begin;
+              bytes_to_read = 0;
+            }
+
+            // No match yet. Check if buffer is full.
+            else if (streambuf_.size() == streambuf_.max_size())
+            {
+              search_position_ = not_found;
+              bytes_to_read = 0;
+            }
+
+            // Need to read some more data.
+            else
+            {
+              if (result.first != end)
+              {
+                // Partial match. Next search needs to start from beginning of
+                // match.
+                search_position_ = result.first - begin;
+              }
+              else
+              {
+                // Next search can start with the new data.
+                search_position_ = end - begin;
+              }
+
+              bytes_to_read = read_size_helper(streambuf_, 65536);
+            }
+          }
+
+          // Check if we're done.
+          if (!start && bytes_to_read == 0)
+            break;
+
+          // Start a new asynchronous read operation to obtain more data.
+          stream_.async_read_some(streambuf_.prepare(bytes_to_read), *this);
+          return; default:
+          streambuf_.commit(bytes_transferred);
+          if (ec || bytes_transferred == 0)
+            break;
+        }
+
+        const asio::error_code result_ec =
+          (search_position_ == not_found)
+          ? error::not_found : ec;
+
+        const std::size_t result_n =
+          (ec || search_position_ == not_found)
+          ? 0 : search_position_;
+
+        handler_(result_ec, result_n);
+      }
+    }
+
+  //private:
+    AsyncReadStream& stream_;
+    asio::basic_streambuf<Allocator>& streambuf_;
+    MatchCondition match_condition_;
+    std::size_t search_position_;
+    ReadHandler handler_;
+  };
+
+  template <typename AsyncReadStream, typename Allocator,
+      typename MatchCondition, typename ReadHandler>
+  inline void* asio_handler_allocate(std::size_t size,
+      read_until_match_op<AsyncReadStream,
+        Allocator, MatchCondition, ReadHandler>* this_handler)
+  {
+    return asio_handler_alloc_helpers::allocate(
+        size, this_handler->handler_);
+  }
+
+  template <typename AsyncReadStream, typename Allocator,
+      typename MatchCondition, typename ReadHandler>
+  inline void asio_handler_deallocate(void* pointer, std::size_t size,
+      read_until_match_op<AsyncReadStream,
+        Allocator, MatchCondition, ReadHandler>* this_handler)
+  {
+    asio_handler_alloc_helpers::deallocate(
+        pointer, size, this_handler->handler_);
+  }
+
+  template <typename Function, typename AsyncReadStream, typename Allocator,
+      typename MatchCondition, typename ReadHandler>
+  inline void asio_handler_invoke(const Function& function,
+      read_until_match_op<AsyncReadStream,
+        Allocator, MatchCondition, ReadHandler>* this_handler)
+  {
+    asio_handler_invoke_helpers::invoke(
+        function, this_handler->handler_);
+  }
+} // namespace detail
+
+template <typename AsyncReadStream, typename Allocator,
+    typename MatchCondition, typename ReadHandler>
+void async_read_until(AsyncReadStream& s,
+    asio::basic_streambuf<Allocator>& b,
+    MatchCondition match_condition, ReadHandler handler,
+    typename boost::enable_if<is_match_condition<MatchCondition> >::type*)
+{
+  detail::read_until_match_op<
+    AsyncReadStream, Allocator, MatchCondition, ReadHandler>(
+      s, b, match_condition, handler)(
+        asio::error_code(), 0, 1);
+}
+
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_IMPL_READ_UNTIL_HPP
diff --git a/ext/asio/asio/impl/serial_port_base.hpp b/ext/asio/asio/impl/serial_port_base.hpp
new file mode 100644
index 0000000..758e652
--- /dev/null
+++ b/ext/asio/asio/impl/serial_port_base.hpp
@@ -0,0 +1,59 @@
+//
+// impl/serial_port_base.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2008 Rep Invariant Systems, Inc. (info at repinvariant.com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_IMPL_SERIAL_PORT_BASE_HPP
+#define ASIO_IMPL_SERIAL_PORT_BASE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+
+inline serial_port_base::baud_rate::baud_rate(unsigned int rate)
+  : value_(rate)
+{
+}
+
+inline unsigned int serial_port_base::baud_rate::value() const
+{
+  return value_;
+}
+
+inline serial_port_base::flow_control::type
+serial_port_base::flow_control::value() const
+{
+  return value_;
+}
+
+inline serial_port_base::parity::type serial_port_base::parity::value() const
+{
+  return value_;
+}
+
+inline serial_port_base::stop_bits::type
+serial_port_base::stop_bits::value() const
+{
+  return value_;
+}
+
+inline unsigned int serial_port_base::character_size::value() const
+{
+  return value_;
+}
+
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_IMPL_SERIAL_PORT_BASE_HPP
diff --git a/ext/asio/asio/impl/serial_port_base.ipp b/ext/asio/asio/impl/serial_port_base.ipp
index 64ab6a4..4d3204d 100644
--- a/ext/asio/asio/impl/serial_port_base.ipp
+++ b/ext/asio/asio/impl/serial_port_base.ipp
@@ -1,40 +1,43 @@
 //
-// serial_port_base.ipp
-// ~~~~~~~~~~~~~~~~~~~~
+// impl/serial_port_base.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 // Copyright (c) 2008 Rep Invariant Systems, Inc. (info at repinvariant.com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 //
 
-#ifndef ASIO_SERIAL_PORT_BASE_IPP
-#define ASIO_SERIAL_PORT_BASE_IPP
+#ifndef ASIO_IMPL_SERIAL_PORT_BASE_IPP
+#define ASIO_IMPL_SERIAL_PORT_BASE_IPP
 
 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 
-#include "asio/detail/push_options.hpp"
+#if defined(ASIO_HAS_SERIAL_PORT)
+
+#include <stdexcept>
 #include <boost/throw_exception.hpp>
-#include "asio/detail/pop_options.hpp"
+#include "asio/error.hpp"
+#include "asio/serial_port_base.hpp"
 
-namespace asio {
+#if defined(GENERATING_DOCUMENTATION)
+# define ASIO_OPTION_STORAGE implementation_defined
+#elif defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+# define ASIO_OPTION_STORAGE DCB
+#else
+# define ASIO_OPTION_STORAGE termios
+#endif
 
-inline serial_port_base::baud_rate::baud_rate(unsigned int rate)
-  : value_(rate)
-{
-}
+#include "asio/detail/push_options.hpp"
 
-inline unsigned int serial_port_base::baud_rate::value() const
-{
-  return value_;
-}
+namespace asio {
 
-inline asio::error_code serial_port_base::baud_rate::store(
+asio::error_code serial_port_base::baud_rate::store(
     ASIO_OPTION_STORAGE& storage, asio::error_code& ec) const
 {
 #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
@@ -122,7 +125,7 @@ inline asio::error_code serial_port_base::baud_rate::store(
   return ec;
 }
 
-inline asio::error_code serial_port_base::baud_rate::load(
+asio::error_code serial_port_base::baud_rate::load(
     const ASIO_OPTION_STORAGE& storage, asio::error_code& ec)
 {
 #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
@@ -204,7 +207,7 @@ inline asio::error_code serial_port_base::baud_rate::load(
   return ec;
 }
 
-inline serial_port_base::flow_control::flow_control(
+serial_port_base::flow_control::flow_control(
     serial_port_base::flow_control::type t)
   : value_(t)
 {
@@ -215,13 +218,7 @@ inline serial_port_base::flow_control::flow_control(
   }
 }
 
-inline serial_port_base::flow_control::type
-serial_port_base::flow_control::value() const
-{
-  return value_;
-}
-
-inline asio::error_code serial_port_base::flow_control::store(
+asio::error_code serial_port_base::flow_control::store(
     ASIO_OPTION_STORAGE& storage, asio::error_code& ec) const
 {
 #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
@@ -255,12 +252,16 @@ inline asio::error_code serial_port_base::flow_control::store(
     storage.c_iflag &= ~(IXOFF | IXON);
 # if defined(_BSD_SOURCE)
     storage.c_cflag &= ~CRTSCTS;
+# elif defined(__QNXNTO__)
+    storage.c_cflag &= ~(IHFLOW | OHFLOW);
 # endif
     break;
   case software:
     storage.c_iflag |= IXOFF | IXON;
 # if defined(_BSD_SOURCE)
     storage.c_cflag &= ~CRTSCTS;
+# elif defined(__QNXNTO__)
+    storage.c_cflag &= ~(IHFLOW | OHFLOW);
 # endif
     break;
   case hardware:
@@ -268,6 +269,10 @@ inline asio::error_code serial_port_base::flow_control::store(
     storage.c_iflag &= ~(IXOFF | IXON);
     storage.c_cflag |= CRTSCTS;
     break;
+# elif defined(__QNXNTO__)
+    storage.c_iflag &= ~(IXOFF | IXON);
+    storage.c_cflag |= (IHFLOW | OHFLOW);
+    break;
 # else
     ec = asio::error::operation_not_supported;
     return ec;
@@ -280,7 +285,7 @@ inline asio::error_code serial_port_base::flow_control::store(
   return ec;
 }
 
-inline asio::error_code serial_port_base::flow_control::load(
+asio::error_code serial_port_base::flow_control::load(
     const ASIO_OPTION_STORAGE& storage, asio::error_code& ec)
 {
 #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
@@ -306,6 +311,11 @@ inline asio::error_code serial_port_base::flow_control::load(
   {
     value_ = hardware;
   }
+# elif defined(__QNXNTO__)
+  else if (storage.c_cflag & IHFLOW && storage.c_cflag & OHFLOW)
+  {
+    value_ = hardware;
+  }
 # endif
   else
   {
@@ -316,7 +326,7 @@ inline asio::error_code serial_port_base::flow_control::load(
   return ec;
 }
 
-inline serial_port_base::parity::parity(serial_port_base::parity::type t)
+serial_port_base::parity::parity(serial_port_base::parity::type t)
   : value_(t)
 {
   if (t != none && t != odd && t != even)
@@ -326,12 +336,7 @@ inline serial_port_base::parity::parity(serial_port_base::parity::type t)
   }
 }
 
-inline serial_port_base::parity::type serial_port_base::parity::value() const
-{
-  return value_;
-}
-
-inline asio::error_code serial_port_base::parity::store(
+asio::error_code serial_port_base::parity::store(
     ASIO_OPTION_STORAGE& storage, asio::error_code& ec) const
 {
 #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
@@ -378,7 +383,7 @@ inline asio::error_code serial_port_base::parity::store(
   return ec;
 }
 
-inline asio::error_code serial_port_base::parity::load(
+asio::error_code serial_port_base::parity::load(
     const ASIO_OPTION_STORAGE& storage, asio::error_code& ec)
 {
 #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
@@ -415,7 +420,7 @@ inline asio::error_code serial_port_base::parity::load(
   return ec;
 }
 
-inline serial_port_base::stop_bits::stop_bits(
+serial_port_base::stop_bits::stop_bits(
     serial_port_base::stop_bits::type t)
   : value_(t)
 {
@@ -426,13 +431,7 @@ inline serial_port_base::stop_bits::stop_bits(
   }
 }
 
-inline serial_port_base::stop_bits::type
-serial_port_base::stop_bits::value() const
-{
-  return value_;
-}
-
-inline asio::error_code serial_port_base::stop_bits::store(
+asio::error_code serial_port_base::stop_bits::store(
     ASIO_OPTION_STORAGE& storage, asio::error_code& ec) const
 {
 #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
@@ -468,7 +467,7 @@ inline asio::error_code serial_port_base::stop_bits::store(
   return ec;
 }
 
-inline asio::error_code serial_port_base::stop_bits::load(
+asio::error_code serial_port_base::stop_bits::load(
     const ASIO_OPTION_STORAGE& storage, asio::error_code& ec)
 {
 #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
@@ -495,7 +494,7 @@ inline asio::error_code serial_port_base::stop_bits::load(
   return ec;
 }
 
-inline serial_port_base::character_size::character_size(unsigned int t)
+serial_port_base::character_size::character_size(unsigned int t)
   : value_(t)
 {
   if (t < 5 || t > 8)
@@ -505,12 +504,7 @@ inline serial_port_base::character_size::character_size(unsigned int t)
   }
 }
 
-inline unsigned int serial_port_base::character_size::value() const
-{
-  return value_;
-}
-
-inline asio::error_code serial_port_base::character_size::store(
+asio::error_code serial_port_base::character_size::store(
     ASIO_OPTION_STORAGE& storage, asio::error_code& ec) const
 {
 #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
@@ -530,7 +524,7 @@ inline asio::error_code serial_port_base::character_size::store(
   return ec;
 }
 
-inline asio::error_code serial_port_base::character_size::load(
+asio::error_code serial_port_base::character_size::load(
     const ASIO_OPTION_STORAGE& storage, asio::error_code& ec)
 {
 #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
@@ -554,4 +548,8 @@ inline asio::error_code serial_port_base::character_size::load(
 
 #include "asio/detail/pop_options.hpp"
 
-#endif // ASIO_SERIAL_PORT_BASE_IPP
+#undef ASIO_OPTION_STORAGE
+
+#endif // defined(ASIO_HAS_SERIAL_PORT)
+
+#endif // ASIO_IMPL_SERIAL_PORT_BASE_IPP
diff --git a/ext/asio/asio/impl/src.cpp b/ext/asio/asio/impl/src.cpp
new file mode 100644
index 0000000..1dac400
--- /dev/null
+++ b/ext/asio/asio/impl/src.cpp
@@ -0,0 +1,25 @@
+//
+// impl/src.cpp
+// ~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#if defined(_MSC_VER) \
+  || defined(__BORLANDC__) \
+  || defined(__DMC__)
+# pragma message ( \
+    "This file is deprecated. " \
+    "Please #include <asio/impl/src.hpp> instead.")
+#elif defined(__GNUC__) \
+  || defined(__HP_aCC) \
+  || defined(__SUNPRO_CC) \
+  || defined(__IBMCPP__)
+# warning "This file is deprecated."
+# warning "Please #include <asio/impl/src.hpp> instead."
+#endif
+
+#include "asio/impl/src.hpp"
diff --git a/ext/asio/asio/impl/src.hpp b/ext/asio/asio/impl/src.hpp
new file mode 100644
index 0000000..b37eabd
--- /dev/null
+++ b/ext/asio/asio/impl/src.hpp
@@ -0,0 +1,65 @@
+//
+// impl/src.hpp
+// ~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_IMPL_SRC_HPP
+#define ASIO_IMPL_SRC_HPP
+
+#define ASIO_SOURCE
+
+#include "asio/detail/config.hpp"
+
+#if defined(ASIO_HEADER_ONLY)
+# error Do not compile Asio library source with ASIO_HEADER_ONLY defined
+#endif
+
+#include "asio/impl/error.ipp"
+#include "asio/impl/error_code.ipp"
+#include "asio/impl/io_service.ipp"
+#include "asio/impl/serial_port_base.ipp"
+#include "asio/detail/impl/descriptor_ops.ipp"
+#include "asio/detail/impl/dev_poll_reactor.ipp"
+#include "asio/detail/impl/epoll_reactor.ipp"
+#include "asio/detail/impl/eventfd_select_interrupter.ipp"
+#include "asio/detail/impl/kqueue_reactor.ipp"
+#include "asio/detail/impl/pipe_select_interrupter.ipp"
+#include "asio/detail/impl/posix_event.ipp"
+#include "asio/detail/impl/posix_mutex.ipp"
+#include "asio/detail/impl/posix_thread.ipp"
+#include "asio/detail/impl/posix_tss_ptr.ipp"
+#include "asio/detail/impl/reactive_descriptor_service.ipp"
+#include "asio/detail/impl/reactive_serial_port_service.ipp"
+#include "asio/detail/impl/reactive_socket_service_base.ipp"
+#include "asio/detail/impl/resolver_service_base.ipp"
+#include "asio/detail/impl/select_reactor.ipp"
+#include "asio/detail/impl/service_registry.ipp"
+#include "asio/detail/impl/socket_ops.ipp"
+#include "asio/detail/impl/socket_select_interrupter.ipp"
+#include "asio/detail/impl/strand_service.ipp"
+#include "asio/detail/impl/task_io_service.ipp"
+#include "asio/detail/impl/throw_error.ipp"
+#include "asio/detail/impl/timer_queue.ipp"
+#include "asio/detail/impl/timer_queue_set.ipp"
+#include "asio/detail/impl/win_iocp_handle_service.ipp"
+#include "asio/detail/impl/win_iocp_io_service.ipp"
+#include "asio/detail/impl/win_iocp_serial_port_service.ipp"
+#include "asio/detail/impl/win_iocp_socket_service_base.ipp"
+#include "asio/detail/impl/win_event.ipp"
+#include "asio/detail/impl/win_mutex.ipp"
+#include "asio/detail/impl/win_thread.ipp"
+#include "asio/detail/impl/win_tss_ptr.ipp"
+#include "asio/detail/impl/winsock_init.ipp"
+#include "asio/ip/impl/address.ipp"
+#include "asio/ip/impl/address_v4.ipp"
+#include "asio/ip/impl/address_v6.ipp"
+#include "asio/ip/impl/host_name.ipp"
+#include "asio/ip/detail/impl/endpoint.ipp"
+#include "asio/local/detail/impl/endpoint.ipp"
+
+#endif // ASIO_IMPL_SRC_HPP
diff --git a/ext/asio/asio/impl/write.hpp b/ext/asio/asio/impl/write.hpp
new file mode 100644
index 0000000..91cb65e
--- /dev/null
+++ b/ext/asio/asio/impl/write.hpp
@@ -0,0 +1,396 @@
+//
+// impl/write.hpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_IMPL_WRITE_HPP
+#define ASIO_IMPL_WRITE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/buffer.hpp"
+#include "asio/completion_condition.hpp"
+#include "asio/detail/base_from_completion_cond.hpp"
+#include "asio/detail/bind_handler.hpp"
+#include "asio/detail/consuming_buffers.hpp"
+#include "asio/detail/handler_alloc_helpers.hpp"
+#include "asio/detail/handler_invoke_helpers.hpp"
+#include "asio/detail/throw_error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+
+template <typename SyncWriteStream, typename ConstBufferSequence,
+    typename CompletionCondition>
+std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
+    CompletionCondition completion_condition, asio::error_code& ec)
+{
+  ec = asio::error_code();
+  asio::detail::consuming_buffers<
+    const_buffer, ConstBufferSequence> tmp(buffers);
+  std::size_t total_transferred = 0;
+  tmp.prepare(detail::adapt_completion_condition_result(
+        completion_condition(ec, total_transferred)));
+  while (tmp.begin() != tmp.end())
+  {
+    std::size_t bytes_transferred = s.write_some(tmp, ec);
+    tmp.consume(bytes_transferred);
+    total_transferred += bytes_transferred;
+    tmp.prepare(detail::adapt_completion_condition_result(
+          completion_condition(ec, total_transferred)));
+  }
+  return total_transferred;
+}
+
+template <typename SyncWriteStream, typename ConstBufferSequence>
+inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers)
+{
+  asio::error_code ec;
+  std::size_t bytes_transferred = write(s, buffers, transfer_all(), ec);
+  asio::detail::throw_error(ec);
+  return bytes_transferred;
+}
+
+template <typename SyncWriteStream, typename ConstBufferSequence,
+    typename CompletionCondition>
+inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
+    CompletionCondition completion_condition)
+{
+  asio::error_code ec;
+  std::size_t bytes_transferred = write(s, buffers, completion_condition, ec);
+  asio::detail::throw_error(ec);
+  return bytes_transferred;
+}
+
+#if !defined(BOOST_NO_IOSTREAM)
+
+template <typename SyncWriteStream, typename Allocator,
+    typename CompletionCondition>
+std::size_t write(SyncWriteStream& s,
+    asio::basic_streambuf<Allocator>& b,
+    CompletionCondition completion_condition, asio::error_code& ec)
+{
+  std::size_t bytes_transferred = write(s, b.data(), completion_condition, ec);
+  b.consume(bytes_transferred);
+  return bytes_transferred;
+}
+
+template <typename SyncWriteStream, typename Allocator>
+inline std::size_t write(SyncWriteStream& s,
+    asio::basic_streambuf<Allocator>& b)
+{
+  asio::error_code ec;
+  std::size_t bytes_transferred = write(s, b, transfer_all(), ec);
+  asio::detail::throw_error(ec);
+  return bytes_transferred;
+}
+
+template <typename SyncWriteStream, typename Allocator,
+    typename CompletionCondition>
+inline std::size_t write(SyncWriteStream& s,
+    asio::basic_streambuf<Allocator>& b,
+    CompletionCondition completion_condition)
+{
+  asio::error_code ec;
+  std::size_t bytes_transferred = write(s, b, completion_condition, ec);
+  asio::detail::throw_error(ec);
+  return bytes_transferred;
+}
+
+#endif // !defined(BOOST_NO_IOSTREAM)
+
+namespace detail
+{
+  template <typename AsyncWriteStream, typename ConstBufferSequence,
+      typename CompletionCondition, typename WriteHandler>
+  class write_op
+    : detail::base_from_completion_cond<CompletionCondition>
+  {
+  public:
+    write_op(AsyncWriteStream& stream, const ConstBufferSequence& buffers,
+        CompletionCondition completion_condition, WriteHandler handler)
+      : detail::base_from_completion_cond<
+          CompletionCondition>(completion_condition),
+        stream_(stream),
+        buffers_(buffers),
+        total_transferred_(0),
+        handler_(handler)
+    {
+    }
+
+    void operator()(const asio::error_code& ec,
+        std::size_t bytes_transferred, int start = 0)
+    {
+      switch (start)
+      {
+        case 1:
+        buffers_.prepare(this->check_for_completion(ec, total_transferred_));
+        for (;;)
+        {
+          stream_.async_write_some(buffers_, *this);
+          return; default:
+          total_transferred_ += bytes_transferred;
+          buffers_.consume(bytes_transferred);
+          buffers_.prepare(this->check_for_completion(ec, total_transferred_));
+          if ((!ec && bytes_transferred == 0)
+              || buffers_.begin() == buffers_.end())
+            break;
+        }
+
+        handler_(ec, static_cast<const std::size_t&>(total_transferred_));
+      }
+    }
+
+  //private:
+    AsyncWriteStream& stream_;
+    asio::detail::consuming_buffers<
+      const_buffer, ConstBufferSequence> buffers_;
+    std::size_t total_transferred_;
+    WriteHandler handler_;
+  };
+
+  template <typename AsyncWriteStream,
+      typename CompletionCondition, typename WriteHandler>
+  class write_op<AsyncWriteStream, asio::mutable_buffers_1,
+      CompletionCondition, WriteHandler>
+    : detail::base_from_completion_cond<CompletionCondition>
+  {
+  public:
+    write_op(AsyncWriteStream& stream,
+        const asio::mutable_buffers_1& buffers,
+        CompletionCondition completion_condition,
+        WriteHandler handler)
+      : detail::base_from_completion_cond<
+          CompletionCondition>(completion_condition),
+        stream_(stream),
+        buffer_(buffers),
+        total_transferred_(0),
+        handler_(handler)
+    {
+    }
+
+    void operator()(const asio::error_code& ec,
+        std::size_t bytes_transferred, int start = 0)
+    {
+      std::size_t n = 0;
+      switch (start)
+      {
+        case 1:
+        n = this->check_for_completion(ec, total_transferred_);
+        for (;;)
+        {
+          stream_.async_write_some(asio::buffer(
+                buffer_ + total_transferred_, n), *this);
+          return; default:
+          total_transferred_ += bytes_transferred;
+          if ((!ec && bytes_transferred == 0)
+              || (n = this->check_for_completion(ec, total_transferred_)) == 0
+              || total_transferred_ == asio::buffer_size(buffer_))
+            break;
+        }
+
+        handler_(ec, static_cast<const std::size_t&>(total_transferred_));
+      }
+    }
+
+  //private:
+    AsyncWriteStream& stream_;
+    asio::mutable_buffer buffer_;
+    std::size_t total_transferred_;
+    WriteHandler handler_;
+  };
+
+  template <typename AsyncWriteStream,
+      typename CompletionCondition, typename WriteHandler>
+  class write_op<AsyncWriteStream, asio::const_buffers_1,
+      CompletionCondition, WriteHandler>
+    : detail::base_from_completion_cond<CompletionCondition>
+  {
+  public:
+    write_op(AsyncWriteStream& stream,
+        const asio::const_buffers_1& buffers,
+        CompletionCondition completion_condition,
+        WriteHandler handler)
+      : detail::base_from_completion_cond<
+          CompletionCondition>(completion_condition),
+        stream_(stream),
+        buffer_(buffers),
+        total_transferred_(0),
+        handler_(handler)
+    {
+    }
+
+    void operator()(const asio::error_code& ec,
+        std::size_t bytes_transferred, int start = 0)
+    {
+      std::size_t n = 0;
+      switch (start)
+      {
+        case 1:
+        n = this->check_for_completion(ec, total_transferred_);
+        for (;;)
+        {
+          stream_.async_write_some(asio::buffer(
+                buffer_ + total_transferred_, n), *this);
+          return; default:
+          total_transferred_ += bytes_transferred;
+          if ((!ec && bytes_transferred == 0)
+              || (n = this->check_for_completion(ec, total_transferred_)) == 0
+              || total_transferred_ == asio::buffer_size(buffer_))
+            break;
+        }
+
+        handler_(ec, static_cast<const std::size_t&>(total_transferred_));
+      }
+    }
+
+  //private:
+    AsyncWriteStream& stream_;
+    asio::const_buffer buffer_;
+    std::size_t total_transferred_;
+    WriteHandler handler_;
+  };
+
+  template <typename AsyncWriteStream, typename ConstBufferSequence,
+      typename CompletionCondition, typename WriteHandler>
+  inline void* asio_handler_allocate(std::size_t size,
+      write_op<AsyncWriteStream, ConstBufferSequence,
+        CompletionCondition, WriteHandler>* this_handler)
+  {
+    return asio_handler_alloc_helpers::allocate(
+        size, this_handler->handler_);
+  }
+
+  template <typename AsyncWriteStream, typename ConstBufferSequence,
+      typename CompletionCondition, typename WriteHandler>
+  inline void asio_handler_deallocate(void* pointer, std::size_t size,
+      write_op<AsyncWriteStream, ConstBufferSequence,
+        CompletionCondition, WriteHandler>* this_handler)
+  {
+    asio_handler_alloc_helpers::deallocate(
+        pointer, size, this_handler->handler_);
+  }
+
+  template <typename Function, typename AsyncWriteStream,
+      typename ConstBufferSequence, typename CompletionCondition,
+      typename WriteHandler>
+  inline void asio_handler_invoke(const Function& function,
+      write_op<AsyncWriteStream, ConstBufferSequence,
+        CompletionCondition, WriteHandler>* this_handler)
+  {
+    asio_handler_invoke_helpers::invoke(
+        function, this_handler->handler_);
+  }
+} // namespace detail
+
+template <typename AsyncWriteStream, typename ConstBufferSequence,
+  typename CompletionCondition, typename WriteHandler>
+inline void async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers,
+    CompletionCondition completion_condition, WriteHandler handler)
+{
+  detail::write_op<AsyncWriteStream, ConstBufferSequence,
+    CompletionCondition, WriteHandler>(
+      s, buffers, completion_condition, handler)(
+        asio::error_code(), 0, 1);
+}
+
+template <typename AsyncWriteStream, typename ConstBufferSequence,
+    typename WriteHandler>
+inline void async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers,
+    WriteHandler handler)
+{
+  async_write(s, buffers, transfer_all(), handler);
+}
+
+#if !defined(BOOST_NO_IOSTREAM)
+
+namespace detail
+{
+  template <typename AsyncWriteStream, typename Allocator,
+      typename WriteHandler>
+  class write_streambuf_handler
+  {
+  public:
+    write_streambuf_handler(asio::basic_streambuf<Allocator>& streambuf,
+        WriteHandler handler)
+      : streambuf_(streambuf),
+        handler_(handler)
+    {
+    }
+
+    void operator()(const asio::error_code& ec,
+        const std::size_t bytes_transferred)
+    {
+      streambuf_.consume(bytes_transferred);
+      handler_(ec, bytes_transferred);
+    }
+
+  //private:
+    asio::basic_streambuf<Allocator>& streambuf_;
+    WriteHandler handler_;
+  };
+
+  template <typename AsyncWriteStream, typename Allocator,
+      typename WriteHandler>
+  inline void* asio_handler_allocate(std::size_t size,
+      write_streambuf_handler<AsyncWriteStream,
+        Allocator, WriteHandler>* this_handler)
+  {
+    return asio_handler_alloc_helpers::allocate(
+        size, this_handler->handler_);
+  }
+
+  template <typename AsyncWriteStream, typename Allocator,
+      typename WriteHandler>
+  inline void asio_handler_deallocate(void* pointer, std::size_t size,
+      write_streambuf_handler<AsyncWriteStream,
+        Allocator, WriteHandler>* this_handler)
+  {
+    asio_handler_alloc_helpers::deallocate(
+        pointer, size, this_handler->handler_);
+  }
+
+  template <typename Function, typename AsyncWriteStream, typename Allocator,
+      typename WriteHandler>
+  inline void asio_handler_invoke(const Function& function,
+      write_streambuf_handler<AsyncWriteStream,
+        Allocator, WriteHandler>* this_handler)
+  {
+    asio_handler_invoke_helpers::invoke(
+        function, this_handler->handler_);
+  }
+} // namespace detail
+
+template <typename AsyncWriteStream, typename Allocator,
+    typename CompletionCondition, typename WriteHandler>
+inline void async_write(AsyncWriteStream& s,
+    asio::basic_streambuf<Allocator>& b,
+    CompletionCondition completion_condition, WriteHandler handler)
+{
+  async_write(s, b.data(), completion_condition,
+      detail::write_streambuf_handler<
+        AsyncWriteStream, Allocator, WriteHandler>(b, handler));
+}
+
+template <typename AsyncWriteStream, typename Allocator, typename WriteHandler>
+inline void async_write(AsyncWriteStream& s,
+    asio::basic_streambuf<Allocator>& b, WriteHandler handler)
+{
+  async_write(s, b, transfer_all(), handler);
+}
+
+#endif // !defined(BOOST_NO_IOSTREAM)
+
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_IMPL_WRITE_HPP
diff --git a/ext/asio/asio/impl/write_at.hpp b/ext/asio/asio/impl/write_at.hpp
new file mode 100644
index 0000000..1de6800
--- /dev/null
+++ b/ext/asio/asio/impl/write_at.hpp
@@ -0,0 +1,417 @@
+//
+// impl/write_at.hpp
+// ~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_IMPL_WRITE_AT_HPP
+#define ASIO_IMPL_WRITE_AT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/buffer.hpp"
+#include "asio/completion_condition.hpp"
+#include "asio/detail/base_from_completion_cond.hpp"
+#include "asio/detail/bind_handler.hpp"
+#include "asio/detail/consuming_buffers.hpp"
+#include "asio/detail/handler_alloc_helpers.hpp"
+#include "asio/detail/handler_invoke_helpers.hpp"
+#include "asio/detail/throw_error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+
+template <typename SyncRandomAccessWriteDevice, typename ConstBufferSequence,
+    typename CompletionCondition>
+std::size_t write_at(SyncRandomAccessWriteDevice& d,
+    boost::uint64_t offset, const ConstBufferSequence& buffers,
+    CompletionCondition completion_condition, asio::error_code& ec)
+{
+  ec = asio::error_code();
+  asio::detail::consuming_buffers<
+    const_buffer, ConstBufferSequence> tmp(buffers);
+  std::size_t total_transferred = 0;
+  tmp.prepare(detail::adapt_completion_condition_result(
+        completion_condition(ec, total_transferred)));
+  while (tmp.begin() != tmp.end())
+  {
+    std::size_t bytes_transferred = d.write_some_at(
+        offset + total_transferred, tmp, ec);
+    tmp.consume(bytes_transferred);
+    total_transferred += bytes_transferred;
+    tmp.prepare(detail::adapt_completion_condition_result(
+          completion_condition(ec, total_transferred)));
+  }
+  return total_transferred;
+}
+
+template <typename SyncRandomAccessWriteDevice, typename ConstBufferSequence>
+inline std::size_t write_at(SyncRandomAccessWriteDevice& d,
+    boost::uint64_t offset, const ConstBufferSequence& buffers)
+{
+  asio::error_code ec;
+  std::size_t bytes_transferred = write_at(
+      d, offset, buffers, transfer_all(), ec);
+  asio::detail::throw_error(ec);
+  return bytes_transferred;
+}
+
+template <typename SyncRandomAccessWriteDevice, typename ConstBufferSequence,
+    typename CompletionCondition>
+inline std::size_t write_at(SyncRandomAccessWriteDevice& d,
+    boost::uint64_t offset, const ConstBufferSequence& buffers,
+    CompletionCondition completion_condition)
+{
+  asio::error_code ec;
+  std::size_t bytes_transferred = write_at(
+      d, offset, buffers, completion_condition, ec);
+  asio::detail::throw_error(ec);
+  return bytes_transferred;
+}
+
+#if !defined(BOOST_NO_IOSTREAM)
+
+template <typename SyncRandomAccessWriteDevice, typename Allocator,
+    typename CompletionCondition>
+std::size_t write_at(SyncRandomAccessWriteDevice& d,
+    boost::uint64_t offset, asio::basic_streambuf<Allocator>& b,
+    CompletionCondition completion_condition, asio::error_code& ec)
+{
+  std::size_t bytes_transferred = write_at(
+      d, offset, b.data(), completion_condition, ec);
+  b.consume(bytes_transferred);
+  return bytes_transferred;
+}
+
+template <typename SyncRandomAccessWriteDevice, typename Allocator>
+inline std::size_t write_at(SyncRandomAccessWriteDevice& d,
+    boost::uint64_t offset, asio::basic_streambuf<Allocator>& b)
+{
+  asio::error_code ec;
+  std::size_t bytes_transferred = write_at(d, offset, b, transfer_all(), ec);
+  asio::detail::throw_error(ec);
+  return bytes_transferred;
+}
+
+template <typename SyncRandomAccessWriteDevice, typename Allocator,
+    typename CompletionCondition>
+inline std::size_t write_at(SyncRandomAccessWriteDevice& d,
+    boost::uint64_t offset, asio::basic_streambuf<Allocator>& b,
+    CompletionCondition completion_condition)
+{
+  asio::error_code ec;
+  std::size_t bytes_transferred = write_at(
+      d, offset, b, completion_condition, ec);
+  asio::detail::throw_error(ec);
+  return bytes_transferred;
+}
+
+#endif // !defined(BOOST_NO_IOSTREAM)
+
+namespace detail
+{
+  template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence,
+      typename CompletionCondition, typename WriteHandler>
+  class write_at_op
+    : detail::base_from_completion_cond<CompletionCondition>
+  {
+  public:
+    write_at_op(AsyncRandomAccessWriteDevice& device,
+        boost::uint64_t offset, const ConstBufferSequence& buffers,
+        CompletionCondition completion_condition, WriteHandler handler)
+      : detail::base_from_completion_cond<
+          CompletionCondition>(completion_condition),
+        device_(device),
+        offset_(offset),
+        buffers_(buffers),
+        total_transferred_(0),
+        handler_(handler)
+    {
+    }
+
+    void operator()(const asio::error_code& ec,
+        std::size_t bytes_transferred, int start = 0)
+    {
+      switch (start)
+      {
+        case 1:
+        buffers_.prepare(this->check_for_completion(ec, total_transferred_));
+        for (;;)
+        {
+          device_.async_write_some_at(
+              offset_ + total_transferred_, buffers_, *this);
+          return; default:
+          total_transferred_ += bytes_transferred;
+          buffers_.consume(bytes_transferred);
+          buffers_.prepare(this->check_for_completion(ec, total_transferred_));
+          if ((!ec && bytes_transferred == 0)
+              || buffers_.begin() == buffers_.end())
+            break;
+        }
+
+        handler_(ec, static_cast<const std::size_t&>(total_transferred_));
+      }
+    }
+
+  //private:
+    AsyncRandomAccessWriteDevice& device_;
+    boost::uint64_t offset_;
+    asio::detail::consuming_buffers<
+      const_buffer, ConstBufferSequence> buffers_;
+    std::size_t total_transferred_;
+    WriteHandler handler_;
+  };
+
+  template <typename AsyncRandomAccessWriteDevice,
+      typename CompletionCondition, typename WriteHandler>
+  class write_at_op<AsyncRandomAccessWriteDevice,
+      asio::mutable_buffers_1, CompletionCondition, WriteHandler>
+    : detail::base_from_completion_cond<CompletionCondition>
+  {
+  public:
+    write_at_op(AsyncRandomAccessWriteDevice& device,
+        boost::uint64_t offset, const asio::mutable_buffers_1& buffers,
+        CompletionCondition completion_condition,
+        WriteHandler handler)
+      : detail::base_from_completion_cond<
+          CompletionCondition>(completion_condition),
+        device_(device),
+        offset_(offset),
+        buffer_(buffers),
+        total_transferred_(0),
+        handler_(handler)
+    {
+    }
+
+    void operator()(const asio::error_code& ec,
+        std::size_t bytes_transferred, int start = 0)
+    {
+      std::size_t n = 0;
+      switch (start)
+      {
+        case 1:
+        n = this->check_for_completion(ec, total_transferred_);
+        for (;;)
+        {
+          device_.async_write_some_at(offset_ + total_transferred_,
+              asio::buffer(buffer_ + total_transferred_, n), *this);
+          return; default:
+          total_transferred_ += bytes_transferred;
+          if ((!ec && bytes_transferred == 0)
+              || (n = this->check_for_completion(ec, total_transferred_)) == 0
+              || total_transferred_ == asio::buffer_size(buffer_))
+            break;
+        }
+
+        handler_(ec, static_cast<const std::size_t&>(total_transferred_));
+      }
+    }
+
+  //private:
+    AsyncRandomAccessWriteDevice& device_;
+    boost::uint64_t offset_;
+    asio::mutable_buffer buffer_;
+    std::size_t total_transferred_;
+    WriteHandler handler_;
+  };
+
+  template <typename AsyncRandomAccessWriteDevice,
+      typename CompletionCondition, typename WriteHandler>
+  class write_at_op<AsyncRandomAccessWriteDevice, asio::const_buffers_1,
+      CompletionCondition, WriteHandler>
+    : detail::base_from_completion_cond<CompletionCondition>
+  {
+  public:
+    write_at_op(AsyncRandomAccessWriteDevice& device,
+        boost::uint64_t offset, const asio::const_buffers_1& buffers,
+        CompletionCondition completion_condition,
+        WriteHandler handler)
+      : detail::base_from_completion_cond<
+          CompletionCondition>(completion_condition),
+        device_(device),
+        offset_(offset),
+        buffer_(buffers),
+        total_transferred_(0),
+        handler_(handler)
+    {
+    }
+
+    void operator()(const asio::error_code& ec,
+        std::size_t bytes_transferred, int start = 0)
+    {
+      std::size_t n = 0;
+      switch (start)
+      {
+        case 1:
+        n = this->check_for_completion(ec, total_transferred_);
+        for (;;)
+        {
+          device_.async_write_some_at(offset_ + total_transferred_,
+              asio::buffer(buffer_ + total_transferred_, n), *this);
+          return; default:
+          total_transferred_ += bytes_transferred;
+          if ((!ec && bytes_transferred == 0)
+              || (n = this->check_for_completion(ec, total_transferred_)) == 0
+              || total_transferred_ == asio::buffer_size(buffer_))
+            break;
+        }
+
+        handler_(ec, static_cast<const std::size_t&>(total_transferred_));
+      }
+    }
+
+  //private:
+    AsyncRandomAccessWriteDevice& device_;
+    boost::uint64_t offset_;
+    asio::const_buffer buffer_;
+    std::size_t total_transferred_;
+    WriteHandler handler_;
+  };
+
+  template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence,
+      typename CompletionCondition, typename WriteHandler>
+  inline void* asio_handler_allocate(std::size_t size,
+      write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence,
+        CompletionCondition, WriteHandler>* this_handler)
+  {
+    return asio_handler_alloc_helpers::allocate(
+        size, this_handler->handler_);
+  }
+
+  template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence,
+      typename CompletionCondition, typename WriteHandler>
+  inline void asio_handler_deallocate(void* pointer, std::size_t size,
+      write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence,
+        CompletionCondition, WriteHandler>* this_handler)
+  {
+    asio_handler_alloc_helpers::deallocate(
+        pointer, size, this_handler->handler_);
+  }
+
+  template <typename Function, typename AsyncRandomAccessWriteDevice,
+      typename ConstBufferSequence, typename CompletionCondition,
+      typename WriteHandler>
+  inline void asio_handler_invoke(const Function& function,
+      write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence,
+        CompletionCondition, WriteHandler>* this_handler)
+  {
+    asio_handler_invoke_helpers::invoke(
+        function, this_handler->handler_);
+  }
+} // namespace detail
+
+template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence,
+    typename CompletionCondition, typename WriteHandler>
+inline void async_write_at(AsyncRandomAccessWriteDevice& d,
+    boost::uint64_t offset, const ConstBufferSequence& buffers,
+    CompletionCondition completion_condition, WriteHandler handler)
+{
+  detail::write_at_op<AsyncRandomAccessWriteDevice,
+    ConstBufferSequence, CompletionCondition, WriteHandler>(
+      d, offset, buffers, completion_condition, handler)(
+        asio::error_code(), 0, 1);
+}
+
+template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence,
+    typename WriteHandler>
+inline void async_write_at(AsyncRandomAccessWriteDevice& d,
+    boost::uint64_t offset, const ConstBufferSequence& buffers,
+    WriteHandler handler)
+{
+  async_write_at(d, offset, buffers, transfer_all(), handler);
+}
+
+#if !defined(BOOST_NO_IOSTREAM)
+
+namespace detail
+{
+  template <typename AsyncRandomAccessWriteDevice,
+      typename Allocator, typename WriteHandler>
+  class write_at_streambuf_op
+  {
+  public:
+    write_at_streambuf_op(
+        asio::basic_streambuf<Allocator>& streambuf,
+        WriteHandler handler)
+      : streambuf_(streambuf),
+        handler_(handler)
+    {
+    }
+
+    void operator()(const asio::error_code& ec,
+        const std::size_t bytes_transferred)
+    {
+      streambuf_.consume(bytes_transferred);
+      handler_(ec, bytes_transferred);
+    }
+
+  //private:
+    asio::basic_streambuf<Allocator>& streambuf_;
+    WriteHandler handler_;
+  };
+
+  template <typename AsyncRandomAccessWriteDevice, typename Allocator,
+      typename WriteHandler>
+  inline void* asio_handler_allocate(std::size_t size,
+      write_at_streambuf_op<AsyncRandomAccessWriteDevice,
+        Allocator, WriteHandler>* this_handler)
+  {
+    return asio_handler_alloc_helpers::allocate(
+        size, this_handler->handler_);
+  }
+
+  template <typename AsyncRandomAccessWriteDevice, typename Allocator,
+      typename WriteHandler>
+  inline void asio_handler_deallocate(void* pointer, std::size_t size,
+      write_at_streambuf_op<AsyncRandomAccessWriteDevice,
+        Allocator, WriteHandler>* this_handler)
+  {
+    asio_handler_alloc_helpers::deallocate(
+        pointer, size, this_handler->handler_);
+  }
+
+  template <typename Function, typename AsyncRandomAccessWriteDevice,
+      typename Allocator, typename WriteHandler>
+  inline void asio_handler_invoke(const Function& function,
+      write_at_streambuf_op<AsyncRandomAccessWriteDevice,
+        Allocator, WriteHandler>* this_handler)
+  {
+    asio_handler_invoke_helpers::invoke(
+        function, this_handler->handler_);
+  }
+} // namespace detail
+
+template <typename AsyncRandomAccessWriteDevice, typename Allocator,
+    typename CompletionCondition, typename WriteHandler>
+inline void async_write_at(AsyncRandomAccessWriteDevice& d,
+    boost::uint64_t offset, asio::basic_streambuf<Allocator>& b,
+    CompletionCondition completion_condition, WriteHandler handler)
+{
+  async_write_at(d, offset, b.data(), completion_condition,
+      detail::write_at_streambuf_op<
+        AsyncRandomAccessWriteDevice, Allocator, WriteHandler>(b, handler));
+}
+
+template <typename AsyncRandomAccessWriteDevice, typename Allocator,
+    typename WriteHandler>
+inline void async_write_at(AsyncRandomAccessWriteDevice& d,
+    boost::uint64_t offset, asio::basic_streambuf<Allocator>& b,
+    WriteHandler handler)
+{
+  async_write_at(d, offset, b, transfer_all(), handler);
+}
+
+#endif // !defined(BOOST_NO_IOSTREAM)
+
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_IMPL_WRITE_AT_HPP
diff --git a/ext/asio/asio/io_service.hpp b/ext/asio/asio/io_service.hpp
index 62d9e54..4fc3e05 100644
--- a/ext/asio/asio/io_service.hpp
+++ b/ext/asio/asio/io_service.hpp
@@ -2,7 +2,7 @@
 // io_service.hpp
 // ~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,25 +15,29 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 #include <cstddef>
 #include <stdexcept>
 #include <typeinfo>
-#include <boost/config.hpp>
-#include <boost/throw_exception.hpp>
-#include "asio/detail/pop_options.hpp"
-
-#include "asio/error_code.hpp"
 #include "asio/detail/noncopyable.hpp"
-#include "asio/detail/reactor_fwd.hpp"
 #include "asio/detail/service_registry_fwd.hpp"
-#include "asio/detail/signal_init.hpp"
-#include "asio/detail/task_io_service_fwd.hpp"
-#include "asio/detail/win_iocp_io_service_fwd.hpp"
-#include "asio/detail/winsock_init.hpp"
 #include "asio/detail/wrapped_handler.hpp"
+#include "asio/error_code.hpp"
+
+#if defined(ASIO_HAS_IOCP)
+# include "asio/detail/win_iocp_io_service_fwd.hpp"
+#else
+# include "asio/detail/task_io_service_fwd.hpp"
+#endif
+
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+# include "asio/detail/winsock_init.hpp"
+#elif defined(__sun) || defined(__QNX__) || defined(__hpux) || defined(_AIX) \
+  || defined(__osf__)
+# include "asio/detail/signal_init.hpp"
+#endif
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 
@@ -45,7 +49,7 @@ template <typename Service> bool has_service(io_service& ios);
 #if defined(ASIO_HAS_IOCP)
 namespace detail { typedef win_iocp_io_service io_service_impl; }
 #else
-namespace detail { typedef task_io_service<reactor> io_service_impl; }
+namespace detail { typedef task_io_service io_service_impl; }
 #endif
 
 /// Provides core I/O functionality.
@@ -196,7 +200,7 @@ public:
   class strand;
 
   /// Constructor.
-  io_service();
+  ASIO_DECL io_service();
 
   /// Constructor.
   /**
@@ -205,7 +209,7 @@ public:
    * @param concurrency_hint A suggestion to the implementation on how many
    * threads it should allow to run simultaneously.
    */
-  explicit io_service(std::size_t concurrency_hint);
+  ASIO_DECL explicit io_service(std::size_t concurrency_hint);
 
   /// Destructor.
   /**
@@ -239,7 +243,7 @@ public:
    * destructor defined above destroys all handlers, causing all @c shared_ptr
    * references to all connection objects to be destroyed.
    */
-  ~io_service();
+  ASIO_DECL ~io_service();
 
   /// Run the io_service object's event processing loop.
   /**
@@ -265,7 +269,7 @@ public:
    * The poll() function may also be used to dispatch ready handlers, but
    * without blocking.
    */
-  std::size_t run();
+  ASIO_DECL std::size_t run();
 
   /// Run the io_service object's event processing loop.
   /**
@@ -291,7 +295,7 @@ public:
    * The poll() function may also be used to dispatch ready handlers, but
    * without blocking.
    */
-  std::size_t run(asio::error_code& ec);
+  ASIO_DECL std::size_t run(asio::error_code& ec);
 
   /// Run the io_service object's event processing loop to execute at most one
   /// handler.
@@ -303,7 +307,7 @@ public:
    *
    * @throws asio::system_error Thrown on failure.
    */
-  std::size_t run_one();
+  ASIO_DECL std::size_t run_one();
 
   /// Run the io_service object's event processing loop to execute at most one
   /// handler.
@@ -315,7 +319,7 @@ public:
    *
    * @return The number of handlers that were executed.
    */
-  std::size_t run_one(asio::error_code& ec);
+  ASIO_DECL std::size_t run_one(asio::error_code& ec);
 
   /// Run the io_service object's event processing loop to execute ready
   /// handlers.
@@ -327,7 +331,7 @@ public:
    *
    * @throws asio::system_error Thrown on failure.
    */
-  std::size_t poll();
+  ASIO_DECL std::size_t poll();
 
   /// Run the io_service object's event processing loop to execute ready
   /// handlers.
@@ -339,7 +343,7 @@ public:
    *
    * @return The number of handlers that were executed.
    */
-  std::size_t poll(asio::error_code& ec);
+  ASIO_DECL std::size_t poll(asio::error_code& ec);
 
   /// Run the io_service object's event processing loop to execute one ready
   /// handler.
@@ -351,7 +355,7 @@ public:
    *
    * @throws asio::system_error Thrown on failure.
    */
-  std::size_t poll_one();
+  ASIO_DECL std::size_t poll_one();
 
   /// Run the io_service object's event processing loop to execute one ready
   /// handler.
@@ -363,7 +367,7 @@ public:
    *
    * @return The number of handlers that were executed.
    */
-  std::size_t poll_one(asio::error_code& ec);
+  ASIO_DECL std::size_t poll_one(asio::error_code& ec);
 
   /// Stop the io_service object's event processing loop.
   /**
@@ -372,7 +376,7 @@ public:
    * return as soon as possible. Subsequent calls to run(), run_one(), poll()
    * or poll_one() will return immediately until reset() is called.
    */
-  void stop();
+  ASIO_DECL void stop();
 
   /// Reset the io_service in preparation for a subsequent run() invocation.
   /**
@@ -385,7 +389,7 @@ public:
    * This function must not be called while there are any unfinished calls to
    * the run(), run_one(), poll() or poll_one() functions.
    */
-  void reset();
+  ASIO_DECL void reset();
 
   /// Request the io_service to invoke the given handler.
   /**
@@ -605,10 +609,10 @@ protected:
   /**
    * @param owner The io_service object that owns the service.
    */
-  service(asio::io_service& owner);
+  ASIO_DECL service(asio::io_service& owner);
 
   /// Destructor.
-  virtual ~service();
+  ASIO_DECL virtual ~service();
 
 private:
   /// Destroy all user-defined handler objects owned by the service.
@@ -631,10 +635,7 @@ class service_already_exists
   : public std::logic_error
 {
 public:
-  service_already_exists()
-    : std::logic_error("Service already exists.")
-  {
-  }
+  ASIO_DECL service_already_exists();
 };
 
 /// Exception thrown when trying to add a service object to an io_service where
@@ -643,16 +644,44 @@ class invalid_service_owner
   : public std::logic_error
 {
 public:
-  invalid_service_owner()
-    : std::logic_error("Invalid service owner.")
+  ASIO_DECL invalid_service_owner();
+};
+
+namespace detail {
+
+// Special derived service id type to keep classes header-file only.
+template <typename Type>
+class service_id
+  : public asio::io_service::id
+{
+};
+
+// Special service base class to keep classes header-file only.
+template <typename Type>
+class service_base
+  : public asio::io_service::service
+{
+public:
+  static asio::detail::service_id<Type> id;
+
+  // Constructor.
+  service_base(asio::io_service& io_service)
+    : asio::io_service::service(io_service)
   {
   }
 };
 
-} // namespace asio
+template <typename Type>
+asio::detail::service_id<Type> service_base<Type>::id;
 
-#include "asio/impl/io_service.ipp"
+} // namespace detail
+} // namespace asio
 
 #include "asio/detail/pop_options.hpp"
 
+#include "asio/impl/io_service.hpp"
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/impl/io_service.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
 #endif // ASIO_IO_SERVICE_HPP
diff --git a/ext/asio/asio/ip/address.hpp b/ext/asio/asio/ip/address.hpp
index 92ee4ae..47683db 100644
--- a/ext/asio/asio/ip/address.hpp
+++ b/ext/asio/asio/ip/address.hpp
@@ -1,8 +1,8 @@
 //
-// address.hpp
-// ~~~~~~~~~~~
+// ip/address.hpp
+// ~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,21 +15,17 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
+#include <string>
+#include "asio/error_code.hpp"
+#include "asio/ip/address_v4.hpp"
+#include "asio/ip/address_v6.hpp"
 
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
 #if !defined(BOOST_NO_IOSTREAM)
 # include <iosfwd>
 #endif // !defined(BOOST_NO_IOSTREAM)
-#include <string>
-#include <boost/throw_exception.hpp>
-#include "asio/detail/pop_options.hpp"
 
-#include "asio/error.hpp"
-#include "asio/ip/address_v4.hpp"
-#include "asio/ip/address_v6.hpp"
-#include "asio/detail/throw_error.hpp"
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 namespace ip {
@@ -47,63 +43,27 @@ class address
 {
 public:
   /// Default constructor.
-  address()
-    : type_(ipv4),
-      ipv4_address_(),
-      ipv6_address_()
-  {
-  }
+  ASIO_DECL address();
 
   /// Construct an address from an IPv4 address.
-  address(const asio::ip::address_v4& ipv4_address)
-    : type_(ipv4),
-      ipv4_address_(ipv4_address),
-      ipv6_address_()
-  {
-  }
+  ASIO_DECL address(const asio::ip::address_v4& ipv4_address);
 
   /// Construct an address from an IPv6 address.
-  address(const asio::ip::address_v6& ipv6_address)
-    : type_(ipv6),
-      ipv4_address_(),
-      ipv6_address_(ipv6_address)
-  {
-  }
+  ASIO_DECL address(const asio::ip::address_v6& ipv6_address);
 
   /// Copy constructor.
-  address(const address& other)
-    : type_(other.type_),
-      ipv4_address_(other.ipv4_address_),
-      ipv6_address_(other.ipv6_address_)
-  {
-  }
+  ASIO_DECL address(const address& other);
 
   /// Assign from another address.
-  address& operator=(const address& other)
-  {
-    type_ = other.type_;
-    ipv4_address_ = other.ipv4_address_;
-    ipv6_address_ = other.ipv6_address_;
-    return *this;
-  }
+  ASIO_DECL address& operator=(const address& other);
 
   /// Assign from an IPv4 address.
-  address& operator=(const asio::ip::address_v4& ipv4_address)
-  {
-    type_ = ipv4;
-    ipv4_address_ = ipv4_address;
-    ipv6_address_ = asio::ip::address_v6();
-    return *this;
-  }
+  ASIO_DECL address& operator=(
+      const asio::ip::address_v4& ipv4_address);
 
   /// Assign from an IPv6 address.
-  address& operator=(const asio::ip::address_v6& ipv6_address)
-  {
-    type_ = ipv6;
-    ipv4_address_ = asio::ip::address_v4();
-    ipv6_address_ = ipv6_address;
-    return *this;
-  }
+  ASIO_DECL address& operator=(
+      const asio::ip::address_v6& ipv6_address);
 
   /// Get whether the address is an IP version 4 address.
   bool is_v4() const
@@ -118,127 +78,63 @@ public:
   }
 
   /// Get the address as an IP version 4 address.
-  asio::ip::address_v4 to_v4() const
-  {
-    if (type_ != ipv4)
-    {
-      asio::system_error e(
-          asio::error::address_family_not_supported);
-      boost::throw_exception(e);
-    }
-    return ipv4_address_;
-  }
+  ASIO_DECL asio::ip::address_v4 to_v4() const;
 
   /// Get the address as an IP version 6 address.
-  asio::ip::address_v6 to_v6() const
-  {
-    if (type_ != ipv6)
-    {
-      asio::system_error e(
-          asio::error::address_family_not_supported);
-      boost::throw_exception(e);
-    }
-    return ipv6_address_;
-  }
+  ASIO_DECL asio::ip::address_v6 to_v6() const;
 
   /// Get the address as a string in dotted decimal format.
-  std::string to_string() const
-  {
-    if (type_ == ipv6)
-      return ipv6_address_.to_string();
-    return ipv4_address_.to_string();
-  }
+  ASIO_DECL std::string to_string() const;
 
   /// Get the address as a string in dotted decimal format.
-  std::string to_string(asio::error_code& ec) const
-  {
-    if (type_ == ipv6)
-      return ipv6_address_.to_string(ec);
-    return ipv4_address_.to_string(ec);
-  }
+  ASIO_DECL std::string to_string(asio::error_code& ec) const;
 
   /// Create an address from an IPv4 address string in dotted decimal form,
   /// or from an IPv6 address in hexadecimal notation.
-  static address from_string(const char* str)
-  {
-    asio::error_code ec;
-    address addr = from_string(str, ec);
-    asio::detail::throw_error(ec);
-    return addr;
-  }
+  ASIO_DECL static address from_string(const char* str);
 
   /// Create an address from an IPv4 address string in dotted decimal form,
   /// or from an IPv6 address in hexadecimal notation.
-  static address from_string(const char* str, asio::error_code& ec)
-  {
-    asio::ip::address_v6 ipv6_address =
-      asio::ip::address_v6::from_string(str, ec);
-    if (!ec)
-    {
-      address tmp;
-      tmp.type_ = ipv6;
-      tmp.ipv6_address_ = ipv6_address;
-      return tmp;
-    }
-
-    asio::ip::address_v4 ipv4_address =
-      asio::ip::address_v4::from_string(str, ec);
-    if (!ec)
-    {
-      address tmp;
-      tmp.type_ = ipv4;
-      tmp.ipv4_address_ = ipv4_address;
-      return tmp;
-    }
-
-    return address();
-  }
+  ASIO_DECL static address from_string(
+      const char* str, asio::error_code& ec);
 
   /// Create an address from an IPv4 address string in dotted decimal form,
   /// or from an IPv6 address in hexadecimal notation.
-  static address from_string(const std::string& str)
-  {
-    return from_string(str.c_str());
-  }
+  ASIO_DECL static address from_string(const std::string& str);
 
   /// Create an address from an IPv4 address string in dotted decimal form,
   /// or from an IPv6 address in hexadecimal notation.
-  static address from_string(const std::string& str,
-      asio::error_code& ec)
+  ASIO_DECL static address from_string(
+      const std::string& str, asio::error_code& ec);
+
+  /// Compare two addresses for equality.
+  ASIO_DECL friend bool operator==(const address& a1, const address& a2);
+
+  /// Compare two addresses for inequality.
+  friend bool operator!=(const address& a1, const address& a2)
   {
-    return from_string(str.c_str(), ec);
+    return !(a1 == a2);
   }
 
-  /// Compare two addresses for equality.
-  friend bool operator==(const address& a1, const address& a2)
+  /// Compare addresses for ordering.
+  ASIO_DECL friend bool operator<(const address& a1, const address& a2);
+
+  /// Compare addresses for ordering.
+  friend bool operator>(const address& a1, const address& a2)
   {
-    if (a1.type_ != a2.type_)
-      return false;
-    if (a1.type_ == ipv6)
-      return a1.ipv6_address_ == a2.ipv6_address_;
-    return a1.ipv4_address_ == a2.ipv4_address_;
+    return a2 < a1;
   }
 
-  /// Compare two addresses for inequality.
-  friend bool operator!=(const address& a1, const address& a2)
+  /// Compare addresses for ordering.
+  friend bool operator<=(const address& a1, const address& a2)
   {
-    if (a1.type_ != a2.type_)
-      return true;
-    if (a1.type_ == ipv6)
-      return a1.ipv6_address_ != a2.ipv6_address_;
-    return a1.ipv4_address_ != a2.ipv4_address_;
+    return !(a2 < a1);
   }
 
   /// Compare addresses for ordering.
-  friend bool operator<(const address& a1, const address& a2)
+  friend bool operator>=(const address& a1, const address& a2)
   {
-    if (a1.type_ < a2.type_)
-      return true;
-    if (a1.type_ > a2.type_)
-      return false;
-    if (a1.type_ == ipv6)
-      return a1.ipv6_address_ < a2.ipv6_address_;
-    return a1.ipv4_address_ < a2.ipv4_address_;
+    return !(a1 < a2);
   }
 
 private:
@@ -268,11 +164,7 @@ private:
  */
 template <typename Elem, typename Traits>
 std::basic_ostream<Elem, Traits>& operator<<(
-    std::basic_ostream<Elem, Traits>& os, const address& addr)
-{
-  os << addr.to_string();
-  return os;
-}
+    std::basic_ostream<Elem, Traits>& os, const address& addr);
 
 #endif // !defined(BOOST_NO_IOSTREAM)
 
@@ -281,4 +173,9 @@ std::basic_ostream<Elem, Traits>& operator<<(
 
 #include "asio/detail/pop_options.hpp"
 
+#include "asio/ip/impl/address.hpp"
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/ip/impl/address.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
 #endif // ASIO_IP_ADDRESS_HPP
diff --git a/ext/asio/asio/ip/address_v4.hpp b/ext/asio/asio/ip/address_v4.hpp
index 1b49556..7567ef9 100644
--- a/ext/asio/asio/ip/address_v4.hpp
+++ b/ext/asio/asio/ip/address_v4.hpp
@@ -1,8 +1,8 @@
 //
-// address_v4.hpp
-// ~~~~~~~~~~~~~~
+// ip/address_v4.hpp
+// ~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,24 +15,18 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
+#include <string>
+#include <boost/array.hpp>
+#include "asio/detail/socket_types.hpp"
+#include "asio/detail/winsock_init.hpp"
+#include "asio/error_code.hpp"
 
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
 #if !defined(BOOST_NO_IOSTREAM)
 # include <iosfwd>
 #endif // !defined(BOOST_NO_IOSTREAM)
-#include <climits>
-#include <string>
-#include <stdexcept>
-#include <boost/array.hpp>
-#include <boost/throw_exception.hpp>
-#include "asio/detail/pop_options.hpp"
 
-#include "asio/error.hpp"
-#include "asio/detail/socket_ops.hpp"
-#include "asio/detail/socket_types.hpp"
-#include "asio/detail/throw_error.hpp"
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 namespace ip {
@@ -59,34 +53,10 @@ public:
   }
 
   /// Construct an address from raw bytes.
-  explicit address_v4(const bytes_type& bytes)
-  {
-#if UCHAR_MAX > 0xFF
-    if (bytes[0] > 0xFF || bytes[1] > 0xFF
-        || bytes[2] > 0xFF || bytes[3] > 0xFF)
-    {
-      std::out_of_range ex("address_v4 from bytes_type");
-      boost::throw_exception(ex);
-    }
-#endif // UCHAR_MAX > 0xFF
-
-    using namespace std; // For memcpy.
-    memcpy(&addr_.s_addr, bytes.elems, 4);
-  }
+  ASIO_DECL explicit address_v4(const bytes_type& bytes);
 
   /// Construct an address from a unsigned long in host byte order.
-  explicit address_v4(unsigned long addr)
-  {
-#if ULONG_MAX > 0xFFFFFFFF
-    if (addr > 0xFFFFFFFF)
-    {
-      std::out_of_range ex("address_v4 from unsigned long");
-      boost::throw_exception(ex);
-    }
-#endif // ULONG_MAX > 0xFFFFFFFF
-
-    addr_.s_addr = asio::detail::socket_ops::host_to_network_long(addr);
-  }
+  ASIO_DECL explicit address_v4(unsigned long addr);
 
   /// Copy constructor.
   address_v4(const address_v4& other)
@@ -102,96 +72,42 @@ public:
   }
 
   /// Get the address in bytes, in network byte order.
-  bytes_type to_bytes() const
-  {
-    using namespace std; // For memcpy.
-    bytes_type bytes;
-    memcpy(bytes.elems, &addr_.s_addr, 4);
-    return bytes;
-  }
+  ASIO_DECL bytes_type to_bytes() const;
 
   /// Get the address as an unsigned long in host byte order
-  unsigned long to_ulong() const
-  {
-    return asio::detail::socket_ops::network_to_host_long(addr_.s_addr);
-  }
+  ASIO_DECL unsigned long to_ulong() const;
 
   /// Get the address as a string in dotted decimal format.
-  std::string to_string() const
-  {
-    asio::error_code ec;
-    std::string addr = to_string(ec);
-    asio::detail::throw_error(ec);
-    return addr;
-  }
+  ASIO_DECL std::string to_string() const;
 
   /// Get the address as a string in dotted decimal format.
-  std::string to_string(asio::error_code& ec) const
-  {
-    char addr_str[asio::detail::max_addr_v4_str_len];
-    const char* addr =
-      asio::detail::socket_ops::inet_ntop(AF_INET, &addr_, addr_str,
-          asio::detail::max_addr_v4_str_len, 0, ec);
-    if (addr == 0)
-      return std::string();
-    return addr;
-  }
+  ASIO_DECL std::string to_string(asio::error_code& ec) const;
 
   /// Create an address from an IP address string in dotted decimal form.
-  static address_v4 from_string(const char* str)
-  {
-    asio::error_code ec;
-    address_v4 addr = from_string(str, ec);
-    asio::detail::throw_error(ec);
-    return addr;
-  }
+  ASIO_DECL static address_v4 from_string(const char* str);
 
   /// Create an address from an IP address string in dotted decimal form.
-  static address_v4 from_string(const char* str, asio::error_code& ec)
-  {
-    address_v4 tmp;
-    if (asio::detail::socket_ops::inet_pton(
-          AF_INET, str, &tmp.addr_, 0, ec) <= 0)
-      return address_v4();
-    return tmp;
-  }
+  ASIO_DECL static address_v4 from_string(
+      const char* str, asio::error_code& ec);
 
   /// Create an address from an IP address string in dotted decimal form.
-  static address_v4 from_string(const std::string& str)
-  {
-    return from_string(str.c_str());
-  }
+  ASIO_DECL static address_v4 from_string(const std::string& str);
 
   /// Create an address from an IP address string in dotted decimal form.
-  static address_v4 from_string(const std::string& str,
-      asio::error_code& ec)
-  {
-    return from_string(str.c_str(), ec);
-  }
+  ASIO_DECL static address_v4 from_string(
+      const std::string& str, asio::error_code& ec);
 
   /// Determine whether the address is a class A address.
-  bool is_class_a() const
-  {
-    return IN_CLASSA(to_ulong());
-  }
+  ASIO_DECL bool is_class_a() const;
 
   /// Determine whether the address is a class B address.
-  bool is_class_b() const
-  {
-    return IN_CLASSB(to_ulong());
-  }
+  ASIO_DECL bool is_class_b() const;
 
   /// Determine whether the address is a class C address.
-  bool is_class_c() const
-  {
-    return IN_CLASSC(to_ulong());
-  }
+  ASIO_DECL bool is_class_c() const;
 
   /// Determine whether the address is a multicast address.
-  bool is_multicast() const
-  {
-    return IN_MULTICAST(to_ulong());
-  }
+  ASIO_DECL bool is_multicast() const;
 
   /// Compare two addresses for equality.
   friend bool operator==(const address_v4& a1, const address_v4& a2)
@@ -249,23 +165,12 @@ public:
 
   /// Obtain an address object that represents the broadcast address that
   /// corresponds to the specified address and netmask.
-  static address_v4 broadcast(const address_v4& addr, const address_v4& mask)
-  {
-    return address_v4(addr.to_ulong() | ~mask.to_ulong());
-  }
+  ASIO_DECL static address_v4 broadcast(
+      const address_v4& addr, const address_v4& mask);
 
   /// Obtain the netmask that corresponds to the address, based on its address
   /// class.
-  static address_v4 netmask(const address_v4& addr)
-  {
-    if (addr.is_class_a())
-      return address_v4(0xFF000000);
-    if (addr.is_class_b())
-      return address_v4(0xFFFF0000);
-    if (addr.is_class_c())
-      return address_v4(0xFFFFFF00);
-    return address_v4(0xFFFFFFFF);
-  }
+  ASIO_DECL static address_v4 netmask(const address_v4& addr);
 
 private:
   // The underlying IPv4 address.
@@ -288,22 +193,7 @@ private:
  */
 template <typename Elem, typename Traits>
 std::basic_ostream<Elem, Traits>& operator<<(
-    std::basic_ostream<Elem, Traits>& os, const address_v4& addr)
-{
-  asio::error_code ec;
-  std::string s = addr.to_string(ec);
-  if (ec)
-  {
-    if (os.exceptions() & std::ios::failbit)
-      asio::detail::throw_error(ec);
-    else
-      os.setstate(std::ios_base::failbit);
-  }
-  else
-    for (std::string::iterator i = s.begin(); i != s.end(); ++i)
-      os << os.widen(*i);
-  return os;
-}
+    std::basic_ostream<Elem, Traits>& os, const address_v4& addr);
 
 #endif // !defined(BOOST_NO_IOSTREAM)
 
@@ -312,4 +202,9 @@ std::basic_ostream<Elem, Traits>& operator<<(
 
 #include "asio/detail/pop_options.hpp"
 
+#include "asio/ip/impl/address_v4.hpp"
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/ip/impl/address_v4.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
 #endif // ASIO_IP_ADDRESS_V4_HPP
diff --git a/ext/asio/asio/ip/address_v6.hpp b/ext/asio/asio/ip/address_v6.hpp
index 8d2c083..261c651 100644
--- a/ext/asio/asio/ip/address_v6.hpp
+++ b/ext/asio/asio/ip/address_v6.hpp
@@ -1,8 +1,8 @@
 //
-// address_v6.hpp
-// ~~~~~~~~~~~~~~
+// ip/address_v6.hpp
+// ~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,26 +15,19 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
+#include <string>
+#include <boost/array.hpp>
+#include "asio/detail/socket_types.hpp"
+#include "asio/detail/winsock_init.hpp"
+#include "asio/error_code.hpp"
+#include "asio/ip/address_v4.hpp"
 
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
 #if !defined(BOOST_NO_IOSTREAM)
 # include <iosfwd>
 #endif // !defined(BOOST_NO_IOSTREAM)
-#include <cstring>
-#include <string>
-#include <stdexcept>
-#include <typeinfo>
-#include <boost/array.hpp>
-#include <boost/throw_exception.hpp>
-#include "asio/detail/pop_options.hpp"
 
-#include "asio/error.hpp"
-#include "asio/detail/socket_ops.hpp"
-#include "asio/detail/socket_types.hpp"
-#include "asio/detail/throw_error.hpp"
-#include "asio/ip/address_v4.hpp"
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 namespace ip {
@@ -55,46 +48,17 @@ public:
   typedef boost::array<unsigned char, 16> bytes_type;
 
   /// Default constructor.
-  address_v6()
-    : scope_id_(0)
-  {
-    asio::detail::in6_addr_type tmp_addr = IN6ADDR_ANY_INIT;
-    addr_ = tmp_addr;
-  }
+  ASIO_DECL address_v6();
 
   /// Construct an address from raw bytes and scope ID.
-  explicit address_v6(const bytes_type& bytes, unsigned long scope_id = 0)
-    : scope_id_(scope_id)
-  {
-#if UCHAR_MAX > 0xFF
-    for (std::size_t i = 0; i < bytes.size(); ++i)
-    {
-      if (bytes[i] > 0xFF)
-      {
-        std::out_of_range ex("address_v6 from bytes_type");
-        boost::throw_exception(ex);
-      }
-    }
-#endif // UCHAR_MAX > 0xFF
-
-    using namespace std; // For memcpy.
-    memcpy(addr_.s6_addr, bytes.elems, 16);
-  }
+  ASIO_DECL explicit address_v6(const bytes_type& bytes,
+      unsigned long scope_id = 0);
 
   /// Copy constructor.
-  address_v6(const address_v6& other)
-    : addr_(other.addr_),
-      scope_id_(other.scope_id_)
-  {
-  }
+  ASIO_DECL address_v6(const address_v6& other);
 
   /// Assign from another address.
-  address_v6& operator=(const address_v6& other)
-  {
-    addr_ = other.addr_;
-    scope_id_ = other.scope_id_;
-    return *this;
-  }
+  ASIO_DECL address_v6& operator=(const address_v6& other);
 
   /// The scope ID of the address.
   /**
@@ -115,217 +79,80 @@ public:
   }
 
   /// Get the address in bytes, in network byte order.
-  bytes_type to_bytes() const
-  {
-    using namespace std; // For memcpy.
-    bytes_type bytes;
-    memcpy(bytes.elems, addr_.s6_addr, 16);
-    return bytes;
-  }
+  ASIO_DECL bytes_type to_bytes() const;
 
   /// Get the address as a string.
-  std::string to_string() const
-  {
-    asio::error_code ec;
-    std::string addr = to_string(ec);
-    asio::detail::throw_error(ec);
-    return addr;
-  }
+  ASIO_DECL std::string to_string() const;
 
   /// Get the address as a string.
-  std::string to_string(asio::error_code& ec) const
-  {
-    char addr_str[asio::detail::max_addr_v6_str_len];
-    const char* addr =
-      asio::detail::socket_ops::inet_ntop(AF_INET6, &addr_, addr_str,
-          asio::detail::max_addr_v6_str_len, scope_id_, ec);
-    if (addr == 0)
-      return std::string();
-    return addr;
-  }
+  ASIO_DECL std::string to_string(asio::error_code& ec) const;
 
   /// Create an address from an IP address string.
-  static address_v6 from_string(const char* str)
-  {
-    asio::error_code ec;
-    address_v6 addr = from_string(str, ec);
-    asio::detail::throw_error(ec);
-    return addr;
-  }
+  ASIO_DECL static address_v6 from_string(const char* str);
 
   /// Create an address from an IP address string.
-  static address_v6 from_string(const char* str, asio::error_code& ec)
-  {
-    address_v6 tmp;
-    if (asio::detail::socket_ops::inet_pton(
-          AF_INET6, str, &tmp.addr_, &tmp.scope_id_, ec) <= 0)
-      return address_v6();
-    return tmp;
-  }
+  ASIO_DECL static address_v6 from_string(
+      const char* str, asio::error_code& ec);
 
   /// Create an address from an IP address string.
-  static address_v6 from_string(const std::string& str)
-  {
-    return from_string(str.c_str());
-  }
+  ASIO_DECL static address_v6 from_string(const std::string& str);
 
   /// Create an address from an IP address string.
-  static address_v6 from_string(const std::string& str,
-      asio::error_code& ec)
-  {
-    return from_string(str.c_str(), ec);
-  }
+  ASIO_DECL static address_v6 from_string(
+      const std::string& str, asio::error_code& ec);
 
   /// Converts an IPv4-mapped or IPv4-compatible address to an IPv4 address.
-  address_v4 to_v4() const
-  {
-    if (!is_v4_mapped() && !is_v4_compatible())
-    {
-      std::bad_cast ex;
-      boost::throw_exception(ex);
-    }
-
-    address_v4::bytes_type v4_bytes = { { addr_.s6_addr[12],
-      addr_.s6_addr[13], addr_.s6_addr[14], addr_.s6_addr[15] } };
-    return address_v4(v4_bytes);
-  }
+  ASIO_DECL address_v4 to_v4() const;
 
   /// Determine whether the address is a loopback address.
-  bool is_loopback() const
-  {
-#if defined(__BORLANDC__)
-    return ((addr_.s6_addr[0] == 0) && (addr_.s6_addr[1] == 0)
-        && (addr_.s6_addr[2] == 0) && (addr_.s6_addr[3] == 0)
-        && (addr_.s6_addr[4] == 0) && (addr_.s6_addr[5] == 0)
-        && (addr_.s6_addr[6] == 0) && (addr_.s6_addr[7] == 0)
-        && (addr_.s6_addr[8] == 0) && (addr_.s6_addr[9] == 0)
-        && (addr_.s6_addr[10] == 0) && (addr_.s6_addr[11] == 0)
-        && (addr_.s6_addr[12] == 0) && (addr_.s6_addr[13] == 0)
-        && (addr_.s6_addr[14] == 0) && (addr_.s6_addr[15] == 1));
-#else
-    using namespace asio::detail;
-    return IN6_IS_ADDR_LOOPBACK(&addr_) != 0;
-#endif
-  }
+  ASIO_DECL bool is_loopback() const;
 
   /// Determine whether the address is unspecified.
-  bool is_unspecified() const
-  {
-#if defined(__BORLANDC__)
-    return ((addr_.s6_addr[0] == 0) && (addr_.s6_addr[1] == 0)
-        && (addr_.s6_addr[2] == 0) && (addr_.s6_addr[3] == 0)
-        && (addr_.s6_addr[4] == 0) && (addr_.s6_addr[5] == 0)
-        && (addr_.s6_addr[6] == 0) && (addr_.s6_addr[7] == 0)
-        && (addr_.s6_addr[8] == 0) && (addr_.s6_addr[9] == 0)
-        && (addr_.s6_addr[10] == 0) && (addr_.s6_addr[11] == 0)
-        && (addr_.s6_addr[12] == 0) && (addr_.s6_addr[13] == 0)
-        && (addr_.s6_addr[14] == 0) && (addr_.s6_addr[15] == 0));
-#else
-    using namespace asio::detail;
-    return IN6_IS_ADDR_UNSPECIFIED(&addr_) != 0;
-#endif
-  }
+  ASIO_DECL bool is_unspecified() const;
 
   /// Determine whether the address is link local.
-  bool is_link_local() const
-  {
-    using namespace asio::detail;
-    return IN6_IS_ADDR_LINKLOCAL(&addr_) != 0;
-  }
+  ASIO_DECL bool is_link_local() const;
 
   /// Determine whether the address is site local.
-  bool is_site_local() const
-  {
-    using namespace asio::detail;
-    return IN6_IS_ADDR_SITELOCAL(&addr_) != 0;
-  }
+  ASIO_DECL bool is_site_local() const;
 
   /// Determine whether the address is a mapped IPv4 address.
-  bool is_v4_mapped() const
-  {
-    using namespace asio::detail;
-    return IN6_IS_ADDR_V4MAPPED(&addr_) != 0;
-  }
+  ASIO_DECL bool is_v4_mapped() const;
 
   /// Determine whether the address is an IPv4-compatible address.
-  bool is_v4_compatible() const
-  {
-    using namespace asio::detail;
-    return IN6_IS_ADDR_V4COMPAT(&addr_) != 0;
-  }
+  ASIO_DECL bool is_v4_compatible() const;
 
   /// Determine whether the address is a multicast address.
-  bool is_multicast() const
-  {
-    using namespace asio::detail;
-    return IN6_IS_ADDR_MULTICAST(&addr_) != 0;
-  }
+  ASIO_DECL bool is_multicast() const;
 
   /// Determine whether the address is a global multicast address.
-  bool is_multicast_global() const
-  {
-    using namespace asio::detail;
-    return IN6_IS_ADDR_MC_GLOBAL(&addr_) != 0;
-  }
+  ASIO_DECL bool is_multicast_global() const;
 
   /// Determine whether the address is a link-local multicast address.
-  bool is_multicast_link_local() const
-  {
-    using namespace asio::detail;
-    return IN6_IS_ADDR_MC_LINKLOCAL(&addr_) != 0;
-  }
+  ASIO_DECL bool is_multicast_link_local() const;
 
   /// Determine whether the address is a node-local multicast address.
-  bool is_multicast_node_local() const
-  {
-    using namespace asio::detail;
-    return IN6_IS_ADDR_MC_NODELOCAL(&addr_) != 0;
-  }
+  ASIO_DECL bool is_multicast_node_local() const;
 
   /// Determine whether the address is a org-local multicast address.
-  bool is_multicast_org_local() const
-  {
-    using namespace asio::detail;
-    return IN6_IS_ADDR_MC_ORGLOCAL(&addr_) != 0;
-  }
+  ASIO_DECL bool is_multicast_org_local() const;
 
   /// Determine whether the address is a site-local multicast address.
-  bool is_multicast_site_local() const
-  {
-    using namespace asio::detail;
-    return IN6_IS_ADDR_MC_SITELOCAL(&addr_) != 0;
-  }
+  ASIO_DECL bool is_multicast_site_local() const;
 
   /// Compare two addresses for equality.
-  friend bool operator==(const address_v6& a1, const address_v6& a2)
-  {
-    using namespace std; // For memcmp.
-    return memcmp(&a1.addr_, &a2.addr_,
-        sizeof(asio::detail::in6_addr_type)) == 0
-      && a1.scope_id_ == a2.scope_id_;
-  }
+  ASIO_DECL friend bool operator==(
+      const address_v6& a1, const address_v6& a2);
 
   /// Compare two addresses for inequality.
   friend bool operator!=(const address_v6& a1, const address_v6& a2)
   {
-    using namespace std; // For memcmp.
-    return memcmp(&a1.addr_, &a2.addr_,
-        sizeof(asio::detail::in6_addr_type)) != 0
-      || a1.scope_id_ != a2.scope_id_;
+    return !(a1 == a2);
   }
 
   /// Compare addresses for ordering.
-  friend bool operator<(const address_v6& a1, const address_v6& a2)
-  {
-    using namespace std; // For memcmp.
-    int memcmp_result = memcmp(&a1.addr_, &a2.addr_,
-        sizeof(asio::detail::in6_addr_type));
-    if (memcmp_result < 0)
-      return true;
-    if (memcmp_result > 0)
-      return false;
-    return a1.scope_id_ < a2.scope_id_;
-  }
+  ASIO_DECL friend bool operator<(
+      const address_v6& a1, const address_v6& a2);
 
   /// Compare addresses for ordering.
   friend bool operator>(const address_v6& a1, const address_v6& a2)
@@ -352,31 +179,13 @@ public:
   }
 
   /// Obtain an address object that represents the loopback address.
-  static address_v6 loopback()
-  {
-    address_v6 tmp;
-    asio::detail::in6_addr_type tmp_addr = IN6ADDR_LOOPBACK_INIT;
-    tmp.addr_ = tmp_addr;
-    return tmp;
-  }
+  ASIO_DECL static address_v6 loopback();
 
   /// Create an IPv4-mapped IPv6 address.
-  static address_v6 v4_mapped(const address_v4& addr)
-  {
-    address_v4::bytes_type v4_bytes = addr.to_bytes();
-    bytes_type v6_bytes = { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF,
-      v4_bytes[0], v4_bytes[1], v4_bytes[2], v4_bytes[3] } };
-    return address_v6(v6_bytes);
-  }
+  ASIO_DECL static address_v6 v4_mapped(const address_v4& addr);
 
   /// Create an IPv4-compatible IPv6 address.
-  static address_v6 v4_compatible(const address_v4& addr)
-  {
-    address_v4::bytes_type v4_bytes = addr.to_bytes();
-    bytes_type v6_bytes = { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-      v4_bytes[0], v4_bytes[1], v4_bytes[2], v4_bytes[3] } };
-    return address_v6(v6_bytes);
-  }
+  ASIO_DECL static address_v6 v4_compatible(const address_v4& addr);
 
 private:
   // The underlying IPv6 address.
@@ -402,22 +211,7 @@ private:
  */
 template <typename Elem, typename Traits>
 std::basic_ostream<Elem, Traits>& operator<<(
-    std::basic_ostream<Elem, Traits>& os, const address_v6& addr)
-{
-  asio::error_code ec;
-  std::string s = addr.to_string(ec);
-  if (ec)
-  {
-    if (os.exceptions() & std::ios::failbit)
-      asio::detail::throw_error(ec);
-    else
-      os.setstate(std::ios_base::failbit);
-  }
-  else
-    for (std::string::iterator i = s.begin(); i != s.end(); ++i)
-      os << os.widen(*i);
-  return os;
-}
+    std::basic_ostream<Elem, Traits>& os, const address_v6& addr);
 
 #endif // !defined(BOOST_NO_IOSTREAM)
 
@@ -426,4 +220,9 @@ std::basic_ostream<Elem, Traits>& operator<<(
 
 #include "asio/detail/pop_options.hpp"
 
+#include "asio/ip/impl/address_v6.hpp"
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/ip/impl/address_v6.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
 #endif // ASIO_IP_ADDRESS_V6_HPP
diff --git a/ext/asio/asio/ip/basic_endpoint.hpp b/ext/asio/asio/ip/basic_endpoint.hpp
index 4ad3f68..5e5ef0b 100644
--- a/ext/asio/asio/ip/basic_endpoint.hpp
+++ b/ext/asio/asio/ip/basic_endpoint.hpp
@@ -1,8 +1,8 @@
 //
-// basic_endpoint.hpp
-// ~~~~~~~~~~~~~~~~~~
+// ip/basic_endpoint.hpp
+// ~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,25 +15,15 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
+#include "asio/ip/address.hpp"
+#include "asio/ip/detail/endpoint.hpp"
 
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include <boost/throw_exception.hpp>
-#include <boost/detail/workaround.hpp>
-#include <cstring>
 #if !defined(BOOST_NO_IOSTREAM)
-# if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
-#  include <ostream>
-# endif // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
-# include <sstream>
+# include <iosfwd>
 #endif // !defined(BOOST_NO_IOSTREAM)
-#include "asio/detail/pop_options.hpp"
 
-#include "asio/error.hpp"
-#include "asio/ip/address.hpp"
-#include "asio/detail/socket_ops.hpp"
-#include "asio/detail/socket_types.hpp"
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 namespace ip {
@@ -67,11 +57,8 @@ public:
 
   /// Default constructor.
   basic_endpoint()
-    : data_()
+    : impl_()
   {
-    data_.v4.sin_family = AF_INET;
-    data_.v4.sin_port = 0;
-    data_.v4.sin_addr.s_addr = INADDR_ANY;
   }
 
   /// Construct an endpoint using a port number, specified in the host's byte
@@ -91,74 +78,35 @@ public:
    * @endcode
    */
   basic_endpoint(const InternetProtocol& protocol, unsigned short port_num)
-    : data_()
+    : impl_(protocol.family(), port_num)
   {
-    using namespace std; // For memcpy.
-    if (protocol.family() == PF_INET)
-    {
-      data_.v4.sin_family = AF_INET;
-      data_.v4.sin_port =
-        asio::detail::socket_ops::host_to_network_short(port_num);
-      data_.v4.sin_addr.s_addr = INADDR_ANY;
-    }
-    else
-    {
-      data_.v6.sin6_family = AF_INET6;
-      data_.v6.sin6_port =
-        asio::detail::socket_ops::host_to_network_short(port_num);
-      data_.v6.sin6_flowinfo = 0;
-      asio::detail::in6_addr_type tmp_addr = IN6ADDR_ANY_INIT;
-      data_.v6.sin6_addr = tmp_addr;
-      data_.v6.sin6_scope_id = 0;
-    }
   }
 
   /// Construct an endpoint using a port number and an IP address. This
   /// constructor may be used for accepting connections on a specific interface
   /// or for making a connection to a remote endpoint.
   basic_endpoint(const asio::ip::address& addr, unsigned short port_num)
-    : data_()
+    : impl_(addr, port_num)
   {
-    using namespace std; // For memcpy.
-    if (addr.is_v4())
-    {
-      data_.v4.sin_family = AF_INET;
-      data_.v4.sin_port =
-        asio::detail::socket_ops::host_to_network_short(port_num);
-      data_.v4.sin_addr.s_addr =
-        asio::detail::socket_ops::host_to_network_long(
-            addr.to_v4().to_ulong());
-    }
-    else
-    {
-      data_.v6.sin6_family = AF_INET6;
-      data_.v6.sin6_port =
-        asio::detail::socket_ops::host_to_network_short(port_num);
-      data_.v6.sin6_flowinfo = 0;
-      asio::ip::address_v6 v6_addr = addr.to_v6();
-      asio::ip::address_v6::bytes_type bytes = v6_addr.to_bytes();
-      memcpy(data_.v6.sin6_addr.s6_addr, bytes.elems, 16);
-      data_.v6.sin6_scope_id = v6_addr.scope_id();
-    }
   }
 
   /// Copy constructor.
   basic_endpoint(const basic_endpoint& other)
-    : data_(other.data_)
+    : impl_(other.impl_)
   {
   }
 
   /// Assign from another endpoint.
   basic_endpoint& operator=(const basic_endpoint& other)
   {
-    data_ = other.data_;
+    impl_ = other.impl_;
     return *this;
   }
 
   /// The protocol associated with the endpoint.
   protocol_type protocol() const
   {
-    if (is_v4())
+    if (impl_.is_v4())
       return InternetProtocol::v4();
     return InternetProtocol::v6();
   }
@@ -166,137 +114,104 @@ public:
   /// Get the underlying endpoint in the native type.
   data_type* data()
   {
-    return &data_.base;
+    return impl_.data();
   }
 
   /// Get the underlying endpoint in the native type.
   const data_type* data() const
   {
-    return &data_.base;
+    return impl_.data();
   }
 
   /// Get the underlying size of the endpoint in the native type.
   std::size_t size() const
   {
-    if (is_v4())
-      return sizeof(asio::detail::sockaddr_in4_type);
-    else
-      return sizeof(asio::detail::sockaddr_in6_type);
+    return impl_.size();
   }
 
   /// Set the underlying size of the endpoint in the native type.
   void resize(std::size_t size)
   {
-    if (size > sizeof(asio::detail::sockaddr_storage_type))
-    {
-      asio::system_error e(asio::error::invalid_argument);
-      boost::throw_exception(e);
-    }
+    impl_.resize(size);
   }
 
   /// Get the capacity of the endpoint in the native type.
   std::size_t capacity() const
   {
-    return sizeof(asio::detail::sockaddr_storage_type);
+    return impl_.capacity();
   }
 
   /// Get the port associated with the endpoint. The port number is always in
   /// the host's byte order.
   unsigned short port() const
   {
-    if (is_v4())
-    {
-      return asio::detail::socket_ops::network_to_host_short(
-          data_.v4.sin_port);
-    }
-    else
-    {
-      return asio::detail::socket_ops::network_to_host_short(
-          data_.v6.sin6_port);
-    }
+    return impl_.port();
   }
 
   /// Set the port associated with the endpoint. The port number is always in
   /// the host's byte order.
   void port(unsigned short port_num)
   {
-    if (is_v4())
-    {
-      data_.v4.sin_port
-        = asio::detail::socket_ops::host_to_network_short(port_num);
-    }
-    else
-    {
-      data_.v6.sin6_port
-        = asio::detail::socket_ops::host_to_network_short(port_num);
-    }
+    impl_.port(port_num);
   }
 
   /// Get the IP address associated with the endpoint.
   asio::ip::address address() const
   {
-    using namespace std; // For memcpy.
-    if (is_v4())
-    {
-      return asio::ip::address_v4(
-          asio::detail::socket_ops::network_to_host_long(
-            data_.v4.sin_addr.s_addr));
-    }
-    else
-    {
-      asio::ip::address_v6::bytes_type bytes;
-      memcpy(bytes.elems, data_.v6.sin6_addr.s6_addr, 16);
-      return asio::ip::address_v6(bytes, data_.v6.sin6_scope_id);
-    }
+    return impl_.address();
   }
 
   /// Set the IP address associated with the endpoint.
   void address(const asio::ip::address& addr)
   {
-    basic_endpoint<InternetProtocol> tmp_endpoint(addr, port());
-    data_ = tmp_endpoint.data_;
+    impl_.address(addr);
   }
 
   /// Compare two endpoints for equality.
   friend bool operator==(const basic_endpoint<InternetProtocol>& e1,
       const basic_endpoint<InternetProtocol>& e2)
   {
-    return e1.address() == e2.address() && e1.port() == e2.port();
+    return e1.impl_ == e2.impl_;
   }
 
   /// Compare two endpoints for inequality.
   friend bool operator!=(const basic_endpoint<InternetProtocol>& e1,
       const basic_endpoint<InternetProtocol>& e2)
   {
-    return e1.address() != e2.address() || e1.port() != e2.port();
+    return !(e1 == e2);
   }
 
   /// Compare endpoints for ordering.
   friend bool operator<(const basic_endpoint<InternetProtocol>& e1,
       const basic_endpoint<InternetProtocol>& e2)
   {
-    if (e1.address() < e2.address())
-      return true;
-    if (e1.address() != e2.address())
-      return false;
-    return e1.port() < e2.port();
+    return e1.impl_ < e2.impl_;
   }
 
-private:
-  // Helper function to determine whether the endpoint is IPv4.
-  bool is_v4() const
+  /// Compare endpoints for ordering.
+  friend bool operator>(const basic_endpoint<InternetProtocol>& e1,
+      const basic_endpoint<InternetProtocol>& e2)
+  {
+    return e2.impl_ < e1.impl_;
+  }
+
+  /// Compare endpoints for ordering.
+  friend bool operator<=(const basic_endpoint<InternetProtocol>& e1,
+      const basic_endpoint<InternetProtocol>& e2)
   {
-    return data_.base.sa_family == AF_INET;
+    return !(e2 < e1);
   }
 
-  // The underlying IP socket address.
-  union data_union
+  /// Compare endpoints for ordering.
+  friend bool operator>=(const basic_endpoint<InternetProtocol>& e1,
+      const basic_endpoint<InternetProtocol>& e2)
   {
-    asio::detail::socket_addr_type base;
-    asio::detail::sockaddr_storage_type storage;
-    asio::detail::sockaddr_in4_type v4;
-    asio::detail::sockaddr_in6_type v6;
-  } data_;
+    return !(e1 < e2);
+  }
+
+private:
+  // The underlying IP endpoint.
+  asio::ip::detail::endpoint impl_;
 };
 
 #if !defined(BOOST_NO_IOSTREAM)
@@ -313,64 +228,10 @@ private:
  *
  * @relates asio::ip::basic_endpoint
  */
-#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
-template <typename InternetProtocol>
-std::ostream& operator<<(std::ostream& os,
-    const basic_endpoint<InternetProtocol>& endpoint)
-{
-  const address& addr = endpoint.address();
-  asio::error_code ec;
-  std::string a = addr.to_string(ec);
-  if (ec)
-  {
-    if (os.exceptions() & std::ios::failbit)
-      asio::detail::throw_error(ec);
-    else
-      os.setstate(std::ios_base::failbit);
-  }
-  else
-  {
-    std::ostringstream tmp_os;
-    tmp_os.imbue(std::locale::classic());
-    if (addr.is_v4())
-      tmp_os << a;
-    else
-      tmp_os << '[' << a << ']';
-    tmp_os << ':' << endpoint.port();
-    os << tmp_os.str();
-  }
-  return os;
-}
-#else // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
 template <typename Elem, typename Traits, typename InternetProtocol>
 std::basic_ostream<Elem, Traits>& operator<<(
     std::basic_ostream<Elem, Traits>& os,
-    const basic_endpoint<InternetProtocol>& endpoint)
-{
-  const address& addr = endpoint.address();
-  asio::error_code ec;
-  std::string a = addr.to_string(ec);
-  if (ec)
-  {
-    if (os.exceptions() & std::ios::failbit)
-      asio::detail::throw_error(ec);
-    else
-      os.setstate(std::ios_base::failbit);
-  }
-  else
-  {
-    std::ostringstream tmp_os;
-    tmp_os.imbue(std::locale::classic());
-    if (addr.is_v4())
-      tmp_os << a;
-    else
-      tmp_os << '[' << a << ']';
-    tmp_os << ':' << endpoint.port();
-    os << tmp_os.str();
-  }
-  return os;
-}
-#endif // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
+    const basic_endpoint<InternetProtocol>& endpoint);
 
 #endif // !defined(BOOST_NO_IOSTREAM)
 
@@ -379,4 +240,6 @@ std::basic_ostream<Elem, Traits>& operator<<(
 
 #include "asio/detail/pop_options.hpp"
 
+#include "asio/ip/impl/basic_endpoint.hpp"
+
 #endif // ASIO_IP_BASIC_ENDPOINT_HPP
diff --git a/ext/asio/asio/ip/basic_resolver.hpp b/ext/asio/asio/ip/basic_resolver.hpp
index 43a37af..c8847e1 100644
--- a/ext/asio/asio/ip/basic_resolver.hpp
+++ b/ext/asio/asio/ip/basic_resolver.hpp
@@ -1,8 +1,8 @@
 //
-// basic_resolver.hpp
-// ~~~~~~~~~~~~~~~~~~
+// ip/basic_resolver.hpp
+// ~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,14 +15,15 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
+#include "asio/detail/config.hpp"
 #include "asio/basic_io_object.hpp"
+#include "asio/detail/throw_error.hpp"
 #include "asio/error.hpp"
 #include "asio/ip/basic_resolver_iterator.hpp"
 #include "asio/ip/basic_resolver_query.hpp"
 #include "asio/ip/resolver_service.hpp"
-#include "asio/detail/throw_error.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 namespace ip {
diff --git a/ext/asio/asio/ip/basic_resolver_entry.hpp b/ext/asio/asio/ip/basic_resolver_entry.hpp
index 09b144b..4117b7b 100644
--- a/ext/asio/asio/ip/basic_resolver_entry.hpp
+++ b/ext/asio/asio/ip/basic_resolver_entry.hpp
@@ -1,8 +1,8 @@
 //
-// basic_resolver_entry.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~
+// ip/basic_resolver_entry.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,11 +15,10 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
+#include <string>
 
 #include "asio/detail/push_options.hpp"
-#include <string>
-#include "asio/detail/pop_options.hpp"
 
 namespace asio {
 namespace ip {
diff --git a/ext/asio/asio/ip/basic_resolver_iterator.hpp b/ext/asio/asio/ip/basic_resolver_iterator.hpp
index 1982d62..033b7e0 100644
--- a/ext/asio/asio/ip/basic_resolver_iterator.hpp
+++ b/ext/asio/asio/ip/basic_resolver_iterator.hpp
@@ -1,8 +1,8 @@
 //
-// basic_resolver_iterator.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// ip/basic_resolver_iterator.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,20 +15,18 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 #include <boost/iterator.hpp>
-#include <boost/shared_ptr.hpp>
 #include <cstring>
 #include <string>
 #include <vector>
-#include "asio/detail/pop_options.hpp"
-
+#include "asio/detail/shared_ptr.hpp"
 #include "asio/detail/socket_ops.hpp"
 #include "asio/detail/socket_types.hpp"
 #include "asio/ip/basic_resolver_entry.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 namespace ip {
 
@@ -176,7 +174,7 @@ private:
   }
 
   typedef std::vector<basic_resolver_entry<InternetProtocol> > values_type;
-  boost::shared_ptr<values_type> values_;
+  asio::detail::shared_ptr<values_type> values_;
   std::size_t index_;
 };
 
diff --git a/ext/asio/asio/ip/basic_resolver_query.hpp b/ext/asio/asio/ip/basic_resolver_query.hpp
index 3cbb335..22ab643 100644
--- a/ext/asio/asio/ip/basic_resolver_query.hpp
+++ b/ext/asio/asio/ip/basic_resolver_query.hpp
@@ -1,8 +1,8 @@
 //
-// basic_resolver_query.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~
+// ip/basic_resolver_query.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,16 +15,13 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
+#include "asio/detail/config.hpp"
 #include <string>
-#include "asio/detail/pop_options.hpp"
-
 #include "asio/detail/socket_ops.hpp"
 #include "asio/ip/resolver_query_base.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 namespace ip {
 
diff --git a/ext/asio/asio/ip/detail/endpoint.hpp b/ext/asio/asio/ip/detail/endpoint.hpp
new file mode 100644
index 0000000..fbea71e
--- /dev/null
+++ b/ext/asio/asio/ip/detail/endpoint.hpp
@@ -0,0 +1,140 @@
+//
+// ip/detail/endpoint.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_IP_DETAIL_ENDPOINT_HPP
+#define ASIO_IP_DETAIL_ENDPOINT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+#include <string>
+#include "asio/detail/socket_types.hpp"
+#include "asio/detail/winsock_init.hpp"
+#include "asio/error_code.hpp"
+#include "asio/ip/address.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace ip {
+namespace detail {
+
+// Helper class for implementating an IP endpoint.
+class endpoint
+{
+public:
+  // Default constructor.
+  ASIO_DECL endpoint();
+
+  // Construct an endpoint using a family and port number.
+  ASIO_DECL endpoint(int family, unsigned short port_num);
+
+  // Construct an endpoint using an address and port number.
+  ASIO_DECL endpoint(const asio::ip::address& addr,
+      unsigned short port_num);
+
+  // Copy constructor.
+  endpoint(const endpoint& other)
+    : data_(other.data_)
+  {
+  }
+
+  // Assign from another endpoint.
+  endpoint& operator=(const endpoint& other)
+  {
+    data_ = other.data_;
+    return *this;
+  }
+
+  // Get the underlying endpoint in the native type.
+  asio::detail::socket_addr_type* data()
+  {
+    return &data_.base;
+  }
+
+  // Get the underlying endpoint in the native type.
+  const asio::detail::socket_addr_type* data() const
+  {
+    return &data_.base;
+  }
+
+  // Get the underlying size of the endpoint in the native type.
+  std::size_t size() const
+  {
+    if (is_v4())
+      return sizeof(asio::detail::sockaddr_in4_type);
+    else
+      return sizeof(asio::detail::sockaddr_in6_type);
+  }
+
+  // Set the underlying size of the endpoint in the native type.
+  ASIO_DECL void resize(std::size_t size);
+
+  // Get the capacity of the endpoint in the native type.
+  std::size_t capacity() const
+  {
+    return sizeof(asio::detail::sockaddr_storage_type);
+  }
+
+  // Get the port associated with the endpoint.
+  ASIO_DECL unsigned short port() const;
+
+  // Set the port associated with the endpoint.
+  ASIO_DECL void port(unsigned short port_num);
+
+  // Get the IP address associated with the endpoint.
+  ASIO_DECL asio::ip::address address() const;
+
+  // Set the IP address associated with the endpoint.
+  ASIO_DECL void address(const asio::ip::address& addr);
+
+  // Compare two endpoints for equality.
+  ASIO_DECL friend bool operator==(
+      const endpoint& e1, const endpoint& e2);
+
+  // Compare endpoints for ordering.
+  ASIO_DECL friend bool operator<(
+      const endpoint& e1, const endpoint& e2);
+
+  // Determine whether the endpoint is IPv4.
+  bool is_v4() const
+  {
+    return data_.base.sa_family == AF_INET;
+  }
+
+#if !defined(BOOST_NO_IOSTREAM)
+  // Convert to a string.
+  ASIO_DECL std::string to_string(asio::error_code& ec) const;
+#endif // !defined(BOOST_NO_IOSTREAM)
+
+private:
+  // The underlying IP socket address.
+  union data_union
+  {
+    asio::detail::socket_addr_type base;
+    asio::detail::sockaddr_storage_type storage;
+    asio::detail::sockaddr_in4_type v4;
+    asio::detail::sockaddr_in6_type v6;
+  } data_;
+};
+
+} // namespace detail
+} // namespace ip
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/ip/detail/impl/endpoint.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
+#endif // ASIO_IP_DETAIL_ENDPOINT_HPP
diff --git a/ext/asio/asio/ip/detail/impl/endpoint.ipp b/ext/asio/asio/ip/detail/impl/endpoint.ipp
new file mode 100644
index 0000000..b1469c8
--- /dev/null
+++ b/ext/asio/asio/ip/detail/impl/endpoint.ipp
@@ -0,0 +1,202 @@
+//
+// ip/detail/impl/endpoint.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_IP_DETAIL_IMPL_ENDPOINT_IPP
+#define ASIO_IP_DETAIL_IMPL_ENDPOINT_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+#include <cstring>
+#if !defined(BOOST_NO_IOSTREAM)
+# include <sstream>
+#endif // !defined(BOOST_NO_IOSTREAM)
+#include "asio/detail/socket_ops.hpp"
+#include "asio/detail/throw_error.hpp"
+#include "asio/error.hpp"
+#include "asio/ip/detail/endpoint.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace ip {
+namespace detail {
+
+ASIO_DECL
+endpoint::endpoint()
+  : data_()
+{
+  data_.v4.sin_family = AF_INET;
+  data_.v4.sin_port = 0;
+  data_.v4.sin_addr.s_addr = INADDR_ANY;
+}
+
+ASIO_DECL
+endpoint::endpoint(int family, unsigned short port_num)
+  : data_()
+{
+  using namespace std; // For memcpy.
+  if (family == PF_INET)
+  {
+    data_.v4.sin_family = AF_INET;
+    data_.v4.sin_port =
+      asio::detail::socket_ops::host_to_network_short(port_num);
+    data_.v4.sin_addr.s_addr = INADDR_ANY;
+  }
+  else
+  {
+    data_.v6.sin6_family = AF_INET6;
+    data_.v6.sin6_port =
+      asio::detail::socket_ops::host_to_network_short(port_num);
+    data_.v6.sin6_flowinfo = 0;
+    asio::detail::in6_addr_type tmp_addr = IN6ADDR_ANY_INIT;
+    data_.v6.sin6_addr = tmp_addr;
+    data_.v6.sin6_scope_id = 0;
+  }
+}
+
+ASIO_DECL
+endpoint::endpoint(const asio::ip::address& addr,
+    unsigned short port_num)
+  : data_()
+{
+  using namespace std; // For memcpy.
+  if (addr.is_v4())
+  {
+    data_.v4.sin_family = AF_INET;
+    data_.v4.sin_port =
+      asio::detail::socket_ops::host_to_network_short(port_num);
+    data_.v4.sin_addr.s_addr =
+      asio::detail::socket_ops::host_to_network_long(
+          addr.to_v4().to_ulong());
+  }
+  else
+  {
+    data_.v6.sin6_family = AF_INET6;
+    data_.v6.sin6_port =
+      asio::detail::socket_ops::host_to_network_short(port_num);
+    data_.v6.sin6_flowinfo = 0;
+    asio::ip::address_v6 v6_addr = addr.to_v6();
+    asio::ip::address_v6::bytes_type bytes = v6_addr.to_bytes();
+    memcpy(data_.v6.sin6_addr.s6_addr, bytes.elems, 16);
+    data_.v6.sin6_scope_id = v6_addr.scope_id();
+  }
+}
+
+ASIO_DECL
+void endpoint::resize(std::size_t size)
+{
+  if (size > sizeof(asio::detail::sockaddr_storage_type))
+  {
+    asio::error_code ec(asio::error::invalid_argument);
+    asio::detail::throw_error(ec);
+  }
+}
+
+ASIO_DECL
+unsigned short endpoint::port() const
+{
+  if (is_v4())
+  {
+    return asio::detail::socket_ops::network_to_host_short(
+        data_.v4.sin_port);
+  }
+  else
+  {
+    return asio::detail::socket_ops::network_to_host_short(
+        data_.v6.sin6_port);
+  }
+}
+
+ASIO_DECL
+void endpoint::port(unsigned short port_num)
+{
+  if (is_v4())
+  {
+    data_.v4.sin_port
+      = asio::detail::socket_ops::host_to_network_short(port_num);
+  }
+  else
+  {
+    data_.v6.sin6_port
+      = asio::detail::socket_ops::host_to_network_short(port_num);
+  }
+}
+
+ASIO_DECL
+asio::ip::address endpoint::address() const
+{
+  using namespace std; // For memcpy.
+  if (is_v4())
+  {
+    return asio::ip::address_v4(
+        asio::detail::socket_ops::network_to_host_long(
+          data_.v4.sin_addr.s_addr));
+  }
+  else
+  {
+    asio::ip::address_v6::bytes_type bytes;
+    memcpy(bytes.elems, data_.v6.sin6_addr.s6_addr, 16);
+    return asio::ip::address_v6(bytes, data_.v6.sin6_scope_id);
+  }
+}
+
+ASIO_DECL
+void endpoint::address(const asio::ip::address& addr)
+{
+  endpoint tmp_endpoint(addr, port());
+  data_ = tmp_endpoint.data_;
+}
+
+ASIO_DECL
+bool operator==(const endpoint& e1, const endpoint& e2)
+{
+  return e1.address() == e2.address() && e1.port() == e2.port();
+}
+
+ASIO_DECL
+bool operator<(const endpoint& e1, const endpoint& e2)
+{
+  if (e1.address() < e2.address())
+    return true;
+  if (e1.address() != e2.address())
+    return false;
+  return e1.port() < e2.port();
+}
+
+#if !defined(BOOST_NO_IOSTREAM)
+ASIO_DECL
+std::string endpoint::to_string(asio::error_code& ec) const
+{
+  std::string a = address().to_string(ec);
+  if (ec)
+    return std::string();
+
+  std::ostringstream tmp_os;
+  tmp_os.imbue(std::locale::classic());
+  if (is_v4())
+    tmp_os << a;
+  else
+    tmp_os << '[' << a << ']';
+  tmp_os << ':' << port();
+
+  return tmp_os.str();
+}
+#endif // !defined(BOOST_NO_IOSTREAM)
+
+} // namespace detail
+} // namespace ip
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_IP_DETAIL_IMPL_ENDPOINT_IPP
diff --git a/ext/asio/asio/ip/detail/socket_option.hpp b/ext/asio/asio/ip/detail/socket_option.hpp
index 00045f8..e370b11 100644
--- a/ext/asio/asio/ip/detail/socket_option.hpp
+++ b/ext/asio/asio/ip/detail/socket_option.hpp
@@ -1,8 +1,8 @@
 //
-// socket_option.hpp
-// ~~~~~~~~~~~~~~~~~
+// detail/socket_option.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,18 +15,15 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 #include <cstddef>
 #include <cstring>
-#include <boost/config.hpp>
 #include <boost/throw_exception.hpp>
-#include "asio/detail/pop_options.hpp"
-
-#include "asio/ip/address.hpp"
 #include "asio/detail/socket_ops.hpp"
 #include "asio/detail/socket_types.hpp"
+#include "asio/ip/address.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 namespace ip {
diff --git a/ext/asio/asio/ip/host_name.hpp b/ext/asio/asio/ip/host_name.hpp
index f24ce1a..8bfaae9 100644
--- a/ext/asio/asio/ip/host_name.hpp
+++ b/ext/asio/asio/ip/host_name.hpp
@@ -1,8 +1,8 @@
 //
-// host_name.hpp
-// ~~~~~~~~~~~~~
+// ip/host_name.hpp
+// ~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,48 +15,28 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 #include <string>
-#include "asio/detail/pop_options.hpp"
+#include "asio/error_code.hpp"
 
-#include "asio/error.hpp"
-#include "asio/detail/socket_ops.hpp"
-#include "asio/detail/throw_error.hpp"
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 namespace ip {
 
 /// Get the current host name.
-std::string host_name();
+ASIO_DECL std::string host_name();
 
 /// Get the current host name.
-std::string host_name(asio::error_code& ec);
-
-inline std::string host_name()
-{
-  char name[1024];
-  asio::error_code ec;
-  if (asio::detail::socket_ops::gethostname(name, sizeof(name), ec) != 0)
-  {
-    asio::detail::throw_error(ec);
-    return std::string();
-  }
-  return std::string(name);
-}
-
-inline std::string host_name(asio::error_code& ec)
-{
-  char name[1024];
-  if (asio::detail::socket_ops::gethostname(name, sizeof(name), ec) != 0)
-    return std::string();
-  return std::string(name);
-}
+ASIO_DECL std::string host_name(asio::error_code& ec);
 
 } // namespace ip
 } // namespace asio
 
 #include "asio/detail/pop_options.hpp"
 
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/ip/impl/host_name.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
 #endif // ASIO_IP_HOST_NAME_HPP
diff --git a/ext/asio/asio/ip/icmp.hpp b/ext/asio/asio/ip/icmp.hpp
index d76b4d1..59df5b0 100644
--- a/ext/asio/asio/ip/icmp.hpp
+++ b/ext/asio/asio/ip/icmp.hpp
@@ -1,8 +1,8 @@
 //
-// icmp.hpp
-// ~~~~~~~~
+// ip/icmp.hpp
+// ~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,14 +15,15 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
+#include "asio/detail/config.hpp"
+#include "asio/detail/socket_types.hpp"
 #include "asio/basic_raw_socket.hpp"
 #include "asio/ip/basic_endpoint.hpp"
 #include "asio/ip/basic_resolver.hpp"
 #include "asio/ip/basic_resolver_iterator.hpp"
 #include "asio/ip/basic_resolver_query.hpp"
-#include "asio/detail/socket_types.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 namespace ip {
diff --git a/ext/asio/asio/ip/impl/address.hpp b/ext/asio/asio/ip/impl/address.hpp
new file mode 100644
index 0000000..0983d24
--- /dev/null
+++ b/ext/asio/asio/ip/impl/address.hpp
@@ -0,0 +1,53 @@
+//
+// ip/impl/address.hpp
+// ~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_IP_IMPL_ADDRESS_HPP
+#define ASIO_IP_IMPL_ADDRESS_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#if !defined(BOOST_NO_IOSTREAM)
+
+#include "asio/detail/throw_error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace ip {
+
+template <typename Elem, typename Traits>
+std::basic_ostream<Elem, Traits>& operator<<(
+    std::basic_ostream<Elem, Traits>& os, const address& addr)
+{
+  asio::error_code ec;
+  std::string s = addr.to_string(ec);
+  if (ec)
+  {
+    if (os.exceptions() & std::basic_ostream<Elem, Traits>::failbit)
+      asio::detail::throw_error(ec);
+    else
+      os.setstate(std::basic_ostream<Elem, Traits>::failbit);
+  }
+  else
+    for (std::string::iterator i = s.begin(); i != s.end(); ++i)
+      os << os.widen(*i);
+  return os;
+}
+
+} // namespace ip
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // !defined(BOOST_NO_IOSTREAM)
+
+#endif // ASIO_IP_IMPL_ADDRESS_HPP
diff --git a/ext/asio/asio/ip/impl/address.ipp b/ext/asio/asio/ip/impl/address.ipp
new file mode 100644
index 0000000..24916ab
--- /dev/null
+++ b/ext/asio/asio/ip/impl/address.ipp
@@ -0,0 +1,203 @@
+//
+// ip/impl/address.ipp
+// ~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_IP_IMPL_ADDRESS_IPP
+#define ASIO_IP_IMPL_ADDRESS_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+#include <typeinfo>
+#include <boost/throw_exception.hpp>
+#include "asio/detail/throw_error.hpp"
+#include "asio/error.hpp"
+#include "asio/ip/address.hpp"
+#include "asio/system_error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace ip {
+
+ASIO_DECL
+address::address()
+  : type_(ipv4),
+    ipv4_address_(),
+    ipv6_address_()
+{
+}
+
+ASIO_DECL
+address::address(const asio::ip::address_v4& ipv4_address)
+  : type_(ipv4),
+    ipv4_address_(ipv4_address),
+    ipv6_address_()
+{
+}
+
+ASIO_DECL
+address::address(const asio::ip::address_v6& ipv6_address)
+  : type_(ipv6),
+    ipv4_address_(),
+    ipv6_address_(ipv6_address)
+{
+}
+
+ASIO_DECL
+address::address(const address& other)
+  : type_(other.type_),
+    ipv4_address_(other.ipv4_address_),
+    ipv6_address_(other.ipv6_address_)
+{
+}
+
+ASIO_DECL
+address& address::operator=(const address& other)
+{
+  type_ = other.type_;
+  ipv4_address_ = other.ipv4_address_;
+  ipv6_address_ = other.ipv6_address_;
+  return *this;
+}
+
+ASIO_DECL
+address& address::operator=(const asio::ip::address_v4& ipv4_address)
+{
+  type_ = ipv4;
+  ipv4_address_ = ipv4_address;
+  ipv6_address_ = asio::ip::address_v6();
+  return *this;
+}
+
+ASIO_DECL
+address& address::operator=(const asio::ip::address_v6& ipv6_address)
+{
+  type_ = ipv6;
+  ipv4_address_ = asio::ip::address_v4();
+  ipv6_address_ = ipv6_address;
+  return *this;
+}
+
+ASIO_DECL
+asio::ip::address_v4 address::to_v4() const
+{
+  if (type_ != ipv4)
+  {
+    std::bad_cast ex;
+    boost::throw_exception(ex);
+  }
+  return ipv4_address_;
+}
+
+ASIO_DECL
+asio::ip::address_v6 address::to_v6() const
+{
+  if (type_ != ipv6)
+  {
+    std::bad_cast ex;
+    boost::throw_exception(ex);
+  }
+  return ipv6_address_;
+}
+
+ASIO_DECL
+std::string address::to_string() const
+{
+  if (type_ == ipv6)
+    return ipv6_address_.to_string();
+  return ipv4_address_.to_string();
+}
+
+ASIO_DECL
+std::string address::to_string(asio::error_code& ec) const
+{
+  if (type_ == ipv6)
+    return ipv6_address_.to_string(ec);
+  return ipv4_address_.to_string(ec);
+}
+
+ASIO_DECL
+address address::from_string(const char* str)
+{
+  asio::error_code ec;
+  address addr = from_string(str, ec);
+  asio::detail::throw_error(ec);
+  return addr;
+}
+
+ASIO_DECL
+address address::from_string(const char* str, asio::error_code& ec)
+{
+  asio::ip::address_v6 ipv6_address =
+    asio::ip::address_v6::from_string(str, ec);
+  if (!ec)
+  {
+    address tmp;
+    tmp.type_ = ipv6;
+    tmp.ipv6_address_ = ipv6_address;
+    return tmp;
+  }
+
+  asio::ip::address_v4 ipv4_address =
+    asio::ip::address_v4::from_string(str, ec);
+  if (!ec)
+  {
+    address tmp;
+    tmp.type_ = ipv4;
+    tmp.ipv4_address_ = ipv4_address;
+    return tmp;
+  }
+
+  return address();
+}
+
+ASIO_DECL
+address address::from_string(const std::string& str)
+{
+  return from_string(str.c_str());
+}
+
+ASIO_DECL
+address address::from_string(const std::string& str,
+    asio::error_code& ec)
+{
+  return from_string(str.c_str(), ec);
+}
+
+ASIO_DECL
+bool operator==(const address& a1, const address& a2)
+{
+  if (a1.type_ != a2.type_)
+    return false;
+  if (a1.type_ == address::ipv6)
+    return a1.ipv6_address_ == a2.ipv6_address_;
+  return a1.ipv4_address_ == a2.ipv4_address_;
+}
+
+ASIO_DECL
+bool operator<(const address& a1, const address& a2)
+{
+  if (a1.type_ < a2.type_)
+    return true;
+  if (a1.type_ > a2.type_)
+    return false;
+  if (a1.type_ == address::ipv6)
+    return a1.ipv6_address_ < a2.ipv6_address_;
+  return a1.ipv4_address_ < a2.ipv4_address_;
+}
+
+} // namespace ip
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_IP_IMPL_ADDRESS_IPP
diff --git a/ext/asio/asio/ip/impl/address_v4.hpp b/ext/asio/asio/ip/impl/address_v4.hpp
new file mode 100644
index 0000000..bbe0882
--- /dev/null
+++ b/ext/asio/asio/ip/impl/address_v4.hpp
@@ -0,0 +1,53 @@
+//
+// ip/impl/address_v4.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_IP_IMPL_ADDRESS_V4_HPP
+#define ASIO_IP_IMPL_ADDRESS_V4_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#if !defined(BOOST_NO_IOSTREAM)
+
+#include "asio/detail/throw_error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace ip {
+
+template <typename Elem, typename Traits>
+std::basic_ostream<Elem, Traits>& operator<<(
+    std::basic_ostream<Elem, Traits>& os, const address_v4& addr)
+{
+  asio::error_code ec;
+  std::string s = addr.to_string(ec);
+  if (ec)
+  {
+    if (os.exceptions() & std::basic_ostream<Elem, Traits>::failbit)
+      asio::detail::throw_error(ec);
+    else
+      os.setstate(std::basic_ostream<Elem, Traits>::failbit);
+  }
+  else
+    for (std::string::iterator i = s.begin(); i != s.end(); ++i)
+      os << os.widen(*i);
+  return os;
+}
+
+} // namespace ip
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // !defined(BOOST_NO_IOSTREAM)
+
+#endif // ASIO_IP_IMPL_ADDRESS_V4_HPP
diff --git a/ext/asio/asio/ip/impl/address_v4.ipp b/ext/asio/asio/ip/impl/address_v4.ipp
new file mode 100644
index 0000000..2c8e9aa
--- /dev/null
+++ b/ext/asio/asio/ip/impl/address_v4.ipp
@@ -0,0 +1,178 @@
+//
+// ip/impl/address_v4.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_IP_IMPL_ADDRESS_V4_IPP
+#define ASIO_IP_IMPL_ADDRESS_V4_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+#include <climits>
+#include <stdexcept>
+#include <boost/throw_exception.hpp>
+#include "asio/error.hpp"
+#include "asio/detail/socket_ops.hpp"
+#include "asio/detail/throw_error.hpp"
+#include "asio/ip/address_v4.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace ip {
+
+ASIO_DECL
+address_v4::address_v4(const address_v4::bytes_type& bytes)
+{
+#if UCHAR_MAX > 0xFF
+  if (bytes[0] > 0xFF || bytes[1] > 0xFF
+      || bytes[2] > 0xFF || bytes[3] > 0xFF)
+  {
+    std::out_of_range ex("address_v4 from bytes_type");
+    boost::throw_exception(ex);
+  }
+#endif // UCHAR_MAX > 0xFF
+
+  using namespace std; // For memcpy.
+  memcpy(&addr_.s_addr, bytes.elems, 4);
+}
+
+ASIO_DECL
+address_v4::address_v4(unsigned long addr)
+{
+#if ULONG_MAX > 0xFFFFFFFF
+  if (addr > 0xFFFFFFFF)
+  {
+    std::out_of_range ex("address_v4 from unsigned long");
+    boost::throw_exception(ex);
+  }
+#endif // ULONG_MAX > 0xFFFFFFFF
+
+  addr_.s_addr = asio::detail::socket_ops::host_to_network_long(addr);
+}
+
+ASIO_DECL
+address_v4::bytes_type address_v4::to_bytes() const
+{
+  using namespace std; // For memcpy.
+  bytes_type bytes;
+  memcpy(bytes.elems, &addr_.s_addr, 4);
+  return bytes;
+}
+
+ASIO_DECL
+unsigned long address_v4::to_ulong() const
+{
+  return asio::detail::socket_ops::network_to_host_long(addr_.s_addr);
+}
+
+ASIO_DECL
+std::string address_v4::to_string() const
+{
+  asio::error_code ec;
+  std::string addr = to_string(ec);
+  asio::detail::throw_error(ec);
+  return addr;
+}
+
+ASIO_DECL
+std::string address_v4::to_string(asio::error_code& ec) const
+{
+  char addr_str[asio::detail::max_addr_v4_str_len];
+  const char* addr =
+    asio::detail::socket_ops::inet_ntop(AF_INET, &addr_, addr_str,
+        asio::detail::max_addr_v4_str_len, 0, ec);
+  if (addr == 0)
+    return std::string();
+  return addr;
+}
+
+ASIO_DECL
+address_v4 address_v4::from_string(const char* str)
+{
+  asio::error_code ec;
+  address_v4 addr = from_string(str, ec);
+  asio::detail::throw_error(ec);
+  return addr;
+}
+
+ASIO_DECL
+address_v4 address_v4::from_string(
+    const char* str, asio::error_code& ec)
+{
+  address_v4 tmp;
+  if (asio::detail::socket_ops::inet_pton(
+        AF_INET, str, &tmp.addr_, 0, ec) <= 0)
+    return address_v4();
+  return tmp;
+}
+
+ASIO_DECL
+address_v4 address_v4::from_string(const std::string& str)
+{
+  return from_string(str.c_str());
+}
+
+ASIO_DECL
+address_v4 address_v4::from_string(
+    const std::string& str, asio::error_code& ec)
+{
+  return from_string(str.c_str(), ec);
+}
+
+ASIO_DECL
+bool address_v4::is_class_a() const
+{
+  return IN_CLASSA(to_ulong());
+}
+
+ASIO_DECL
+bool address_v4::is_class_b() const
+{
+  return IN_CLASSB(to_ulong());
+}
+
+ASIO_DECL
+bool address_v4::is_class_c() const
+{
+  return IN_CLASSC(to_ulong());
+}
+
+ASIO_DECL
+bool address_v4::is_multicast() const
+{
+  return IN_MULTICAST(to_ulong());
+}
+
+ASIO_DECL
+address_v4 address_v4::broadcast(const address_v4& addr, const address_v4& mask)
+{
+  return address_v4(addr.to_ulong() | (mask.to_ulong() ^ 0xFFFFFFFF));
+}
+
+ASIO_DECL
+address_v4 address_v4::netmask(const address_v4& addr)
+{
+  if (addr.is_class_a())
+    return address_v4(0xFF000000);
+  if (addr.is_class_b())
+    return address_v4(0xFFFF0000);
+  if (addr.is_class_c())
+    return address_v4(0xFFFFFF00);
+  return address_v4(0xFFFFFFFF);
+}
+
+} // namespace ip
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_IP_IMPL_ADDRESS_V4_IPP
diff --git a/ext/asio/asio/ip/impl/address_v6.hpp b/ext/asio/asio/ip/impl/address_v6.hpp
new file mode 100644
index 0000000..796a505
--- /dev/null
+++ b/ext/asio/asio/ip/impl/address_v6.hpp
@@ -0,0 +1,53 @@
+//
+// ip/impl/address_v6.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_IP_IMPL_ADDRESS_V6_HPP
+#define ASIO_IP_IMPL_ADDRESS_V6_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#if !defined(BOOST_NO_IOSTREAM)
+
+#include "asio/detail/throw_error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace ip {
+
+template <typename Elem, typename Traits>
+std::basic_ostream<Elem, Traits>& operator<<(
+    std::basic_ostream<Elem, Traits>& os, const address_v6& addr)
+{
+  asio::error_code ec;
+  std::string s = addr.to_string(ec);
+  if (ec)
+  {
+    if (os.exceptions() & std::basic_ostream<Elem, Traits>::failbit)
+      asio::detail::throw_error(ec);
+    else
+      os.setstate(std::basic_ostream<Elem, Traits>::failbit);
+  }
+  else
+    for (std::string::iterator i = s.begin(); i != s.end(); ++i)
+      os << os.widen(*i);
+  return os;
+}
+
+} // namespace ip
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // !defined(BOOST_NO_IOSTREAM)
+
+#endif // ASIO_IP_IMPL_ADDRESS_V6_HPP
diff --git a/ext/asio/asio/ip/impl/address_v6.ipp b/ext/asio/asio/ip/impl/address_v6.ipp
new file mode 100644
index 0000000..17b6382
--- /dev/null
+++ b/ext/asio/asio/ip/impl/address_v6.ipp
@@ -0,0 +1,313 @@
+//
+// ip/impl/address_v6.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_IP_IMPL_ADDRESS_V6_IPP
+#define ASIO_IP_IMPL_ADDRESS_V6_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+#include <cstring>
+#include <stdexcept>
+#include <typeinfo>
+#include <boost/throw_exception.hpp>
+#include "asio/detail/socket_ops.hpp"
+#include "asio/detail/throw_error.hpp"
+#include "asio/error.hpp"
+#include "asio/ip/address_v6.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace ip {
+
+ASIO_DECL
+address_v6::address_v6()
+  : scope_id_(0)
+{
+  asio::detail::in6_addr_type tmp_addr = IN6ADDR_ANY_INIT;
+  addr_ = tmp_addr;
+}
+
+ASIO_DECL
+address_v6::address_v6(const address_v6::bytes_type& bytes,
+    unsigned long scope_id)
+  : scope_id_(scope_id)
+{
+#if UCHAR_MAX > 0xFF
+  for (std::size_t i = 0; i < bytes.size(); ++i)
+  {
+    if (bytes[i] > 0xFF)
+    {
+      std::out_of_range ex("address_v6 from bytes_type");
+      boost::throw_exception(ex);
+    }
+  }
+#endif // UCHAR_MAX > 0xFF
+
+  using namespace std; // For memcpy.
+  memcpy(addr_.s6_addr, bytes.elems, 16);
+}
+
+ASIO_DECL
+address_v6::address_v6(const address_v6& other)
+  : addr_(other.addr_),
+    scope_id_(other.scope_id_)
+{
+}
+
+ASIO_DECL
+address_v6& address_v6::operator=(const address_v6& other)
+{
+  addr_ = other.addr_;
+  scope_id_ = other.scope_id_;
+  return *this;
+}
+
+ASIO_DECL
+address_v6::bytes_type address_v6::to_bytes() const
+{
+  using namespace std; // For memcpy.
+  bytes_type bytes;
+  memcpy(bytes.elems, addr_.s6_addr, 16);
+  return bytes;
+}
+
+ASIO_DECL
+std::string address_v6::to_string() const
+{
+  asio::error_code ec;
+  std::string addr = to_string(ec);
+  asio::detail::throw_error(ec);
+  return addr;
+}
+
+ASIO_DECL
+std::string address_v6::to_string(asio::error_code& ec) const
+{
+  char addr_str[asio::detail::max_addr_v6_str_len];
+  const char* addr =
+    asio::detail::socket_ops::inet_ntop(AF_INET6, &addr_, addr_str,
+        asio::detail::max_addr_v6_str_len, scope_id_, ec);
+  if (addr == 0)
+    return std::string();
+  return addr;
+}
+
+ASIO_DECL
+address_v6 address_v6::from_string(const char* str)
+{
+  asio::error_code ec;
+  address_v6 addr = from_string(str, ec);
+  asio::detail::throw_error(ec);
+  return addr;
+}
+
+ASIO_DECL
+address_v6 address_v6::from_string(
+    const char* str, asio::error_code& ec)
+{
+  address_v6 tmp;
+  if (asio::detail::socket_ops::inet_pton(
+        AF_INET6, str, &tmp.addr_, &tmp.scope_id_, ec) <= 0)
+    return address_v6();
+  return tmp;
+}
+
+ASIO_DECL
+address_v6 address_v6::from_string(const std::string& str)
+{
+  return from_string(str.c_str());
+}
+
+ASIO_DECL
+address_v6 address_v6::from_string(
+    const std::string& str, asio::error_code& ec)
+{
+  return from_string(str.c_str(), ec);
+}
+
+ASIO_DECL
+address_v4 address_v6::to_v4() const
+{
+  if (!is_v4_mapped() && !is_v4_compatible())
+  {
+    std::bad_cast ex;
+    boost::throw_exception(ex);
+  }
+
+  address_v4::bytes_type v4_bytes = { { addr_.s6_addr[12],
+    addr_.s6_addr[13], addr_.s6_addr[14], addr_.s6_addr[15] } };
+  return address_v4(v4_bytes);
+}
+
+ASIO_DECL
+bool address_v6::is_loopback() const
+{
+#if defined(__BORLANDC__)
+  return ((addr_.s6_addr[0] == 0) && (addr_.s6_addr[1] == 0)
+      && (addr_.s6_addr[2] == 0) && (addr_.s6_addr[3] == 0)
+      && (addr_.s6_addr[4] == 0) && (addr_.s6_addr[5] == 0)
+      && (addr_.s6_addr[6] == 0) && (addr_.s6_addr[7] == 0)
+      && (addr_.s6_addr[8] == 0) && (addr_.s6_addr[9] == 0)
+      && (addr_.s6_addr[10] == 0) && (addr_.s6_addr[11] == 0)
+      && (addr_.s6_addr[12] == 0) && (addr_.s6_addr[13] == 0)
+      && (addr_.s6_addr[14] == 0) && (addr_.s6_addr[15] == 1));
+#else
+  using namespace asio::detail;
+  return IN6_IS_ADDR_LOOPBACK(&addr_) != 0;
+#endif
+}
+
+ASIO_DECL
+bool address_v6::is_unspecified() const
+{
+#if defined(__BORLANDC__)
+  return ((addr_.s6_addr[0] == 0) && (addr_.s6_addr[1] == 0)
+      && (addr_.s6_addr[2] == 0) && (addr_.s6_addr[3] == 0)
+      && (addr_.s6_addr[4] == 0) && (addr_.s6_addr[5] == 0)
+      && (addr_.s6_addr[6] == 0) && (addr_.s6_addr[7] == 0)
+      && (addr_.s6_addr[8] == 0) && (addr_.s6_addr[9] == 0)
+      && (addr_.s6_addr[10] == 0) && (addr_.s6_addr[11] == 0)
+      && (addr_.s6_addr[12] == 0) && (addr_.s6_addr[13] == 0)
+      && (addr_.s6_addr[14] == 0) && (addr_.s6_addr[15] == 0));
+#else
+  using namespace asio::detail;
+  return IN6_IS_ADDR_UNSPECIFIED(&addr_) != 0;
+#endif
+}
+
+ASIO_DECL
+bool address_v6::is_link_local() const
+{
+  using namespace asio::detail;
+  return IN6_IS_ADDR_LINKLOCAL(&addr_) != 0;
+}
+
+ASIO_DECL
+bool address_v6::is_site_local() const
+{
+  using namespace asio::detail;
+  return IN6_IS_ADDR_SITELOCAL(&addr_) != 0;
+}
+
+ASIO_DECL
+bool address_v6::is_v4_mapped() const
+{
+  using namespace asio::detail;
+  return IN6_IS_ADDR_V4MAPPED(&addr_) != 0;
+}
+
+ASIO_DECL
+bool address_v6::is_v4_compatible() const
+{
+  using namespace asio::detail;
+  return IN6_IS_ADDR_V4COMPAT(&addr_) != 0;
+}
+
+ASIO_DECL
+bool address_v6::is_multicast() const
+{
+  using namespace asio::detail;
+  return IN6_IS_ADDR_MULTICAST(&addr_) != 0;
+}
+
+ASIO_DECL
+bool address_v6::is_multicast_global() const
+{
+  using namespace asio::detail;
+  return IN6_IS_ADDR_MC_GLOBAL(&addr_) != 0;
+}
+
+ASIO_DECL
+bool address_v6::is_multicast_link_local() const
+{
+  using namespace asio::detail;
+  return IN6_IS_ADDR_MC_LINKLOCAL(&addr_) != 0;
+}
+
+ASIO_DECL
+bool address_v6::is_multicast_node_local() const
+{
+  using namespace asio::detail;
+  return IN6_IS_ADDR_MC_NODELOCAL(&addr_) != 0;
+}
+
+ASIO_DECL
+bool address_v6::is_multicast_org_local() const
+{
+  using namespace asio::detail;
+  return IN6_IS_ADDR_MC_ORGLOCAL(&addr_) != 0;
+}
+
+ASIO_DECL
+bool address_v6::is_multicast_site_local() const
+{
+  using namespace asio::detail;
+  return IN6_IS_ADDR_MC_SITELOCAL(&addr_) != 0;
+}
+
+ASIO_DECL
+bool operator==(const address_v6& a1, const address_v6& a2)
+{
+  using namespace std; // For memcmp.
+  return memcmp(&a1.addr_, &a2.addr_,
+      sizeof(asio::detail::in6_addr_type)) == 0
+    && a1.scope_id_ == a2.scope_id_;
+}
+
+ASIO_DECL
+bool operator<(const address_v6& a1, const address_v6& a2)
+{
+  using namespace std; // For memcmp.
+  int memcmp_result = memcmp(&a1.addr_, &a2.addr_,
+      sizeof(asio::detail::in6_addr_type));
+  if (memcmp_result < 0)
+    return true;
+  if (memcmp_result > 0)
+    return false;
+  return a1.scope_id_ < a2.scope_id_;
+}
+
+ASIO_DECL
+address_v6 address_v6::loopback()
+{
+  address_v6 tmp;
+  asio::detail::in6_addr_type tmp_addr = IN6ADDR_LOOPBACK_INIT;
+  tmp.addr_ = tmp_addr;
+  return tmp;
+}
+
+ASIO_DECL
+address_v6 address_v6::v4_mapped(const address_v4& addr)
+{
+  address_v4::bytes_type v4_bytes = addr.to_bytes();
+  bytes_type v6_bytes = { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF,
+    v4_bytes[0], v4_bytes[1], v4_bytes[2], v4_bytes[3] } };
+  return address_v6(v6_bytes);
+}
+
+ASIO_DECL
+address_v6 address_v6::v4_compatible(const address_v4& addr)
+{
+  address_v4::bytes_type v4_bytes = addr.to_bytes();
+  bytes_type v6_bytes = { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    v4_bytes[0], v4_bytes[1], v4_bytes[2], v4_bytes[3] } };
+  return address_v6(v6_bytes);
+}
+
+} // namespace ip
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_IP_IMPL_ADDRESS_V6_IPP
diff --git a/ext/asio/asio/ip/impl/basic_endpoint.hpp b/ext/asio/asio/ip/impl/basic_endpoint.hpp
new file mode 100644
index 0000000..db7d5fb
--- /dev/null
+++ b/ext/asio/asio/ip/impl/basic_endpoint.hpp
@@ -0,0 +1,55 @@
+//
+// ip/impl/basic_endpoint.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_IP_IMPL_BASIC_ENDPOINT_HPP
+#define ASIO_IP_IMPL_BASIC_ENDPOINT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#if !defined(BOOST_NO_IOSTREAM)
+
+#include "asio/detail/throw_error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace ip {
+
+template <typename Elem, typename Traits, typename InternetProtocol>
+std::basic_ostream<Elem, Traits>& operator<<(
+    std::basic_ostream<Elem, Traits>& os,
+    const basic_endpoint<InternetProtocol>& endpoint)
+{
+  asio::ip::detail::endpoint tmp_ep(endpoint.address(), endpoint.port());
+  asio::error_code ec;
+  std::string s = tmp_ep.to_string(ec);
+  if (ec)
+  {
+    if (os.exceptions() & std::basic_ostream<Elem, Traits>::failbit)
+      asio::detail::throw_error(ec);
+    else
+      os.setstate(std::basic_ostream<Elem, Traits>::failbit);
+  }
+  else
+    for (std::string::iterator i = s.begin(); i != s.end(); ++i)
+      os << os.widen(*i);
+  return os;
+}
+
+} // namespace ip
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // !defined(BOOST_NO_IOSTREAM)
+
+#endif // ASIO_IP_IMPL_BASIC_ENDPOINT_HPP
diff --git a/ext/asio/asio/ip/impl/host_name.ipp b/ext/asio/asio/ip/impl/host_name.ipp
new file mode 100644
index 0000000..5bf5cca
--- /dev/null
+++ b/ext/asio/asio/ip/impl/host_name.ipp
@@ -0,0 +1,56 @@
+//
+// ip/impl/host_name.ipp
+// ~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_IP_IMPL_HOST_NAME_IPP
+#define ASIO_IP_IMPL_HOST_NAME_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+#include "asio/detail/socket_ops.hpp"
+#include "asio/detail/throw_error.hpp"
+#include "asio/detail/winsock_init.hpp"
+#include "asio/ip/host_name.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace ip {
+
+ASIO_DECL
+std::string host_name()
+{
+  char name[1024];
+  asio::error_code ec;
+  if (asio::detail::socket_ops::gethostname(name, sizeof(name), ec) != 0)
+  {
+    asio::detail::throw_error(ec);
+    return std::string();
+  }
+  return std::string(name);
+}
+
+ASIO_DECL
+std::string host_name(asio::error_code& ec)
+{
+  char name[1024];
+  if (asio::detail::socket_ops::gethostname(name, sizeof(name), ec) != 0)
+    return std::string();
+  return std::string(name);
+}
+
+} // namespace ip
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_IP_IMPL_HOST_NAME_IPP
diff --git a/ext/asio/asio/ip/multicast.hpp b/ext/asio/asio/ip/multicast.hpp
index eeedc6c..f2193c0 100644
--- a/ext/asio/asio/ip/multicast.hpp
+++ b/ext/asio/asio/ip/multicast.hpp
@@ -1,8 +1,8 @@
 //
-// multicast.hpp
-// ~~~~~~~~~~~~~
+// ip/multicast.hpp
+// ~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,15 +15,12 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 #include <cstddef>
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
-
 #include "asio/ip/detail/socket_option.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 namespace ip {
 namespace multicast {
diff --git a/ext/asio/asio/ip/resolver_query_base.hpp b/ext/asio/asio/ip/resolver_query_base.hpp
index 5a0acea..8963f41 100644
--- a/ext/asio/asio/ip/resolver_query_base.hpp
+++ b/ext/asio/asio/ip/resolver_query_base.hpp
@@ -1,8 +1,8 @@
 //
-// resolver_query_base.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~
+// ip/resolver_query_base.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,15 +15,12 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
+#include "asio/detail/config.hpp"
 #include <boost/detail/workaround.hpp>
-#include "asio/detail/pop_options.hpp"
-
 #include "asio/detail/socket_types.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 namespace ip {
 
diff --git a/ext/asio/asio/ip/resolver_service.hpp b/ext/asio/asio/ip/resolver_service.hpp
index 75f6b2c..0d866d6 100644
--- a/ext/asio/asio/ip/resolver_service.hpp
+++ b/ext/asio/asio/ip/resolver_service.hpp
@@ -1,8 +1,8 @@
 //
-// resolver_service.hpp
-// ~~~~~~~~~~~~~~~~~~~~
+// ip/resolver_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,14 +15,14 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/error.hpp"
+#include "asio/detail/config.hpp"
+#include "asio/error_code.hpp"
+#include "asio/detail/resolver_service.hpp"
 #include "asio/io_service.hpp"
 #include "asio/ip/basic_resolver_iterator.hpp"
 #include "asio/ip/basic_resolver_query.hpp"
-#include "asio/detail/resolver_service.hpp"
-#include "asio/detail/service_base.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 namespace ip {
@@ -72,13 +72,14 @@ public:
   explicit resolver_service(asio::io_service& io_service)
     : asio::detail::service_base<
         resolver_service<InternetProtocol> >(io_service),
-      service_impl_(asio::use_service<service_impl_type>(io_service))
+      service_impl_(io_service)
   {
   }
 
   /// Destroy all user-defined handler objects owned by the service.
   void shutdown_service()
   {
+    service_impl_.shutdown_service();
   }
 
   /// Construct a new resolver implementation.
@@ -130,8 +131,8 @@ public:
   }
 
 private:
-  // The service that provides the platform-specific implementation.
-  service_impl_type& service_impl_;
+  // The platform-specific implementation.
+  service_impl_type service_impl_;
 };
 
 } // namespace ip
diff --git a/ext/asio/asio/ip/tcp.hpp b/ext/asio/asio/ip/tcp.hpp
index a2e9ac9..67fb09f 100644
--- a/ext/asio/asio/ip/tcp.hpp
+++ b/ext/asio/asio/ip/tcp.hpp
@@ -1,8 +1,8 @@
 //
-// tcp.hpp
-// ~~~~~~~
+// ip/tcp.hpp
+// ~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,17 +15,18 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
+#include "asio/detail/config.hpp"
 #include "asio/basic_socket_acceptor.hpp"
 #include "asio/basic_socket_iostream.hpp"
 #include "asio/basic_stream_socket.hpp"
+#include "asio/detail/socket_option.hpp"
+#include "asio/detail/socket_types.hpp"
 #include "asio/ip/basic_endpoint.hpp"
 #include "asio/ip/basic_resolver.hpp"
 #include "asio/ip/basic_resolver_iterator.hpp"
 #include "asio/ip/basic_resolver_query.hpp"
-#include "asio/detail/socket_option.hpp"
-#include "asio/detail/socket_types.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 namespace ip {
diff --git a/ext/asio/asio/ip/udp.hpp b/ext/asio/asio/ip/udp.hpp
index fb26118..ca3ac78 100644
--- a/ext/asio/asio/ip/udp.hpp
+++ b/ext/asio/asio/ip/udp.hpp
@@ -1,8 +1,8 @@
 //
-// udp.hpp
-// ~~~~~~~
+// ip/udp.hpp
+// ~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,14 +15,15 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
+#include "asio/detail/config.hpp"
 #include "asio/basic_datagram_socket.hpp"
+#include "asio/detail/socket_types.hpp"
 #include "asio/ip/basic_endpoint.hpp"
 #include "asio/ip/basic_resolver.hpp"
 #include "asio/ip/basic_resolver_iterator.hpp"
 #include "asio/ip/basic_resolver_query.hpp"
-#include "asio/detail/socket_types.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 namespace ip {
diff --git a/ext/asio/asio/ip/unicast.hpp b/ext/asio/asio/ip/unicast.hpp
index 46d7239..e3d04e5 100644
--- a/ext/asio/asio/ip/unicast.hpp
+++ b/ext/asio/asio/ip/unicast.hpp
@@ -1,8 +1,8 @@
 //
-// unicast.hpp
-// ~~~~~~~~~~~
+// ip/unicast.hpp
+// ~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,15 +15,12 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 #include <cstddef>
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
-
 #include "asio/ip/detail/socket_option.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 namespace ip {
 namespace unicast {
diff --git a/ext/asio/asio/ip/v6_only.hpp b/ext/asio/asio/ip/v6_only.hpp
index 928caff..5ac6a37 100644
--- a/ext/asio/asio/ip/v6_only.hpp
+++ b/ext/asio/asio/ip/v6_only.hpp
@@ -1,8 +1,8 @@
 //
-// v6_only.hpp
-// ~~~~~~~~~~~
+// ip/v6_only.hpp
+// ~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,10 +15,11 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
+#include "asio/detail/config.hpp"
 #include "asio/detail/socket_option.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 namespace ip {
 
diff --git a/ext/asio/asio/is_read_buffered.hpp b/ext/asio/asio/is_read_buffered.hpp
index 8d97174..e48de55 100644
--- a/ext/asio/asio/is_read_buffered.hpp
+++ b/ext/asio/asio/is_read_buffered.hpp
@@ -2,7 +2,7 @@
 // is_read_buffered.hpp
 // ~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,15 +15,12 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
-
+#include "asio/detail/config.hpp"
 #include "asio/buffered_read_stream_fwd.hpp"
 #include "asio/buffered_stream_fwd.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 
 namespace detail {
diff --git a/ext/asio/asio/is_write_buffered.hpp b/ext/asio/asio/is_write_buffered.hpp
index 5d16b1c..c681a2b 100644
--- a/ext/asio/asio/is_write_buffered.hpp
+++ b/ext/asio/asio/is_write_buffered.hpp
@@ -2,7 +2,7 @@
 // is_write_buffered.hpp
 // ~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,15 +15,12 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
-
+#include "asio/detail/config.hpp"
 #include "asio/buffered_stream_fwd.hpp"
 #include "asio/buffered_write_stream_fwd.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 
 namespace detail {
diff --git a/ext/asio/asio/local/basic_endpoint.hpp b/ext/asio/asio/local/basic_endpoint.hpp
index 81e6a7e..d2d0a02 100644
--- a/ext/asio/asio/local/basic_endpoint.hpp
+++ b/ext/asio/asio/local/basic_endpoint.hpp
@@ -1,8 +1,8 @@
 //
-// basic_endpoint.hpp
-// ~~~~~~~~~~~~~~~~~~
+// local/basic_endpoint.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 // Derived from a public domain implementation written by Daniel Casimiro.
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
@@ -16,30 +16,18 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <boost/throw_exception.hpp>
-#include <cstddef>
-#include <cstring>
-#include <ostream>
-#include "asio/detail/pop_options.hpp"
-
-#include "asio/error.hpp"
-#include "asio/system_error.hpp"
-#include "asio/detail/socket_ops.hpp"
-#include "asio/detail/socket_types.hpp"
-#include "asio/detail/throw_error.hpp"
-
-#if !defined(ASIO_DISABLE_LOCAL_SOCKETS)
-# if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
-#  define ASIO_HAS_LOCAL_SOCKETS 1
-# endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
-#endif // !defined(ASIO_DISABLE_LOCAL_SOCKETS)
+#include "asio/detail/config.hpp"
 
 #if defined(ASIO_HAS_LOCAL_SOCKETS) \
   || defined(GENERATING_DOCUMENTATION)
 
+#include "asio/local/detail/endpoint.hpp"
+
+#if !defined(BOOST_NO_IOSTREAM)
+# include <iosfwd>
+#endif // !defined(BOOST_NO_IOSTREAM)
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 namespace local {
@@ -74,34 +62,30 @@ public:
   /// Default constructor.
   basic_endpoint()
   {
-    init("", 0);
   }
 
   /// Construct an endpoint using the specified path name.
   basic_endpoint(const char* path)
+    : impl_(path)
   {
-    using namespace std; // For strlen.
-    init(path, strlen(path));
   }
 
   /// Construct an endpoint using the specified path name.
   basic_endpoint(const std::string& path)
+    : impl_(path)
   {
-    init(path.data(), path.length());
   }
 
   /// Copy constructor.
   basic_endpoint(const basic_endpoint& other)
-    : data_(other.data_),
-      path_length_(other.path_length_)
+    : impl_(other.impl_)
   {
   }
 
   /// Assign from another endpoint.
   basic_endpoint& operator=(const basic_endpoint& other)
   {
-    data_ = other.data_;
-    path_length_ = other.path_length_;
+    impl_ = other.impl_;
     return *this;
   }
 
@@ -114,123 +98,96 @@ public:
   /// Get the underlying endpoint in the native type.
   data_type* data()
   {
-    return &data_.base;
+    return impl_.data();
   }
 
   /// Get the underlying endpoint in the native type.
   const data_type* data() const
   {
-    return &data_.base;
+    return impl_.data();
   }
 
   /// Get the underlying size of the endpoint in the native type.
   std::size_t size() const
   {
-    return path_length_
-      + offsetof(asio::detail::sockaddr_un_type, sun_path);
+    return impl_.size();
   }
 
   /// Set the underlying size of the endpoint in the native type.
   void resize(std::size_t size)
   {
-    if (size > sizeof(asio::detail::sockaddr_un_type))
-    {
-      asio::system_error e(asio::error::invalid_argument);
-      boost::throw_exception(e);
-    }
-    else if (size == 0)
-    {
-      path_length_ = 0;
-    }
-    else
-    {
-      path_length_ = size
-        - offsetof(asio::detail::sockaddr_un_type, sun_path);
-
-      // The path returned by the operating system may be NUL-terminated.
-      if (path_length_ > 0 && data_.local.sun_path[path_length_ - 1] == 0)
-        --path_length_;
-    }
+    impl_.resize(size);
   }
 
   /// Get the capacity of the endpoint in the native type.
   std::size_t capacity() const
   {
-    return sizeof(asio::detail::sockaddr_un_type);
+    return impl_.capacity();
   }
 
   /// Get the path associated with the endpoint.
   std::string path() const
   {
-    return std::string(data_.local.sun_path, path_length_);
+    return impl_.path();
   }
 
   /// Set the path associated with the endpoint.
   void path(const char* p)
   {
-    using namespace std; // For strlen.
-    init(p, strlen(p));
+    impl_.path(p);
   }
 
   /// Set the path associated with the endpoint.
   void path(const std::string& p)
   {
-    init(p.data(), p.length());
+    impl_.path(p);
   }
 
   /// Compare two endpoints for equality.
   friend bool operator==(const basic_endpoint<Protocol>& e1,
       const basic_endpoint<Protocol>& e2)
   {
-    return e1.path() == e2.path();
+    return e1.impl_ == e2.impl_;
   }
 
   /// Compare two endpoints for inequality.
   friend bool operator!=(const basic_endpoint<Protocol>& e1,
       const basic_endpoint<Protocol>& e2)
   {
-    return e1.path() != e2.path();
+    return !(e1.impl_ == e2.impl_);
   }
 
   /// Compare endpoints for ordering.
   friend bool operator<(const basic_endpoint<Protocol>& e1,
       const basic_endpoint<Protocol>& e2)
   {
-    return e1.path() < e2.path();
+    return e1.impl_ < e2.impl_;
   }
 
-private:
-  // The underlying UNIX socket address.
-  union data_union
+  /// Compare endpoints for ordering.
+  friend bool operator>(const basic_endpoint<Protocol>& e1,
+      const basic_endpoint<Protocol>& e2)
   {
-    asio::detail::socket_addr_type base;
-    asio::detail::sockaddr_un_type local;
-  } data_;
+    return e2.impl_ < e1.impl_;
+  }
 
-  // The length of the path associated with the endpoint.
-  std::size_t path_length_;
+  /// Compare endpoints for ordering.
+  friend bool operator<=(const basic_endpoint<Protocol>& e1,
+      const basic_endpoint<Protocol>& e2)
+  {
+    return !(e2 < e1);
+  }
 
-  // Initialise with a specified path.
-  void init(const char* path, std::size_t path_length)
+  /// Compare endpoints for ordering.
+  friend bool operator>=(const basic_endpoint<Protocol>& e1,
+      const basic_endpoint<Protocol>& e2)
   {
-    if (path_length > sizeof(data_.local.sun_path) - 1)
-    {
-      // The buffer is not large enough to store this address.
-      asio::error_code ec(asio::error::name_too_long);
-      asio::detail::throw_error(ec);
-    }
-
-    using namespace std; // For memcpy.
-    data_.local = asio::detail::sockaddr_un_type();
-    data_.local.sun_family = AF_UNIX;
-    memcpy(data_.local.sun_path, path, path_length);
-    path_length_ = path_length;
-
-    // NUL-terminate normal path names. Names that start with a NUL are in the
-    // UNIX domain protocol's "abstract namespace" and are not NUL-terminated.
-    if (path_length > 0 && data_.local.sun_path[0] == 0)
-      data_.local.sun_path[path_length] = 0;
+    return !(e1 < e2);
   }
+
+private:
+  // The underlying UNIX domain endpoint.
+  asio::local::detail::endpoint impl_;
 };
 
 /// Output an endpoint as a string.
@@ -257,9 +214,9 @@ std::basic_ostream<Elem, Traits>& operator<<(
 } // namespace local
 } // namespace asio
 
+#include "asio/detail/pop_options.hpp"
+
 #endif // defined(ASIO_HAS_LOCAL_SOCKETS)
        //   || defined(GENERATING_DOCUMENTATION)
 
-#include "asio/detail/pop_options.hpp"
-
 #endif // ASIO_LOCAL_BASIC_ENDPOINT_HPP
diff --git a/ext/asio/asio/local/connect_pair.hpp b/ext/asio/asio/local/connect_pair.hpp
index da1d4fc..4a58247 100644
--- a/ext/asio/asio/local/connect_pair.hpp
+++ b/ext/asio/asio/local/connect_pair.hpp
@@ -1,8 +1,8 @@
 //
-// connect_pair.hpp
-// ~~~~~~~~~~~~~~~~
+// local/connect_pair.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,16 +15,18 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
+
+#if defined(ASIO_HAS_LOCAL_SOCKETS) \
+  || defined(GENERATING_DOCUMENTATION)
 
 #include "asio/basic_socket.hpp"
-#include "asio/error.hpp"
-#include "asio/local/basic_endpoint.hpp"
 #include "asio/detail/socket_ops.hpp"
 #include "asio/detail/throw_error.hpp"
+#include "asio/error.hpp"
+#include "asio/local/basic_endpoint.hpp"
 
-#if defined(ASIO_HAS_LOCAL_SOCKETS) \
-  || defined(GENERATING_DOCUMENTATION)
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 namespace local {
@@ -73,8 +75,9 @@ inline asio::error_code connect_pair(
   if (socket1.assign(protocol, sv[0], ec))
   {
     asio::error_code temp_ec;
-    asio::detail::socket_ops::close(sv[0], temp_ec);
-    asio::detail::socket_ops::close(sv[1], temp_ec);
+    asio::detail::socket_ops::state_type state[2] = { 0, 0 };
+    asio::detail::socket_ops::close(sv[0], state[0], true, temp_ec);
+    asio::detail::socket_ops::close(sv[1], state[1], true, temp_ec);
     return ec;
   }
 
@@ -82,7 +85,8 @@ inline asio::error_code connect_pair(
   {
     asio::error_code temp_ec;
     socket1.close(temp_ec);
-    asio::detail::socket_ops::close(sv[1], temp_ec);
+    asio::detail::socket_ops::state_type state = 0;
+    asio::detail::socket_ops::close(sv[1], state, true, temp_ec);
     return ec;
   }
 
@@ -92,9 +96,9 @@ inline asio::error_code connect_pair(
 } // namespace local
 } // namespace asio
 
+#include "asio/detail/pop_options.hpp"
+
 #endif // defined(ASIO_HAS_LOCAL_SOCKETS)
        //   || defined(GENERATING_DOCUMENTATION)
 
-#include "asio/detail/pop_options.hpp"
-
 #endif // ASIO_LOCAL_CONNECT_PAIR_HPP
diff --git a/ext/asio/asio/local/datagram_protocol.hpp b/ext/asio/asio/local/datagram_protocol.hpp
index 0340180..39f47ce 100644
--- a/ext/asio/asio/local/datagram_protocol.hpp
+++ b/ext/asio/asio/local/datagram_protocol.hpp
@@ -1,8 +1,8 @@
 //
-// datagram_protocol.hpp
-// ~~~~~~~~~~~~~~~~~~~~~
+// local/datagram_protocol.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,14 +15,16 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
+
+#if defined(ASIO_HAS_LOCAL_SOCKETS) \
+  || defined(GENERATING_DOCUMENTATION)
 
 #include "asio/basic_datagram_socket.hpp"
-#include "asio/local/basic_endpoint.hpp"
 #include "asio/detail/socket_types.hpp"
+#include "asio/local/basic_endpoint.hpp"
 
-#if defined(ASIO_HAS_LOCAL_SOCKETS) \
-  || defined(GENERATING_DOCUMENTATION)
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 namespace local {
@@ -70,9 +72,9 @@ public:
 } // namespace local
 } // namespace asio
 
+#include "asio/detail/pop_options.hpp"
+
 #endif // defined(ASIO_HAS_LOCAL_SOCKETS)
        //   || defined(GENERATING_DOCUMENTATION)
 
-#include "asio/detail/pop_options.hpp"
-
 #endif // ASIO_LOCAL_DATAGRAM_PROTOCOL_HPP
diff --git a/ext/asio/asio/local/detail/endpoint.hpp b/ext/asio/asio/local/detail/endpoint.hpp
new file mode 100644
index 0000000..05fc992
--- /dev/null
+++ b/ext/asio/asio/local/detail/endpoint.hpp
@@ -0,0 +1,133 @@
+//
+// local/detail/endpoint.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Derived from a public domain implementation written by Daniel Casimiro.
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_LOCAL_DETAIL_ENDPOINT_HPP
+#define ASIO_LOCAL_DETAIL_ENDPOINT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(ASIO_HAS_LOCAL_SOCKETS)
+
+#include <cstddef>
+#include <string>
+#include "asio/detail/socket_types.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace local {
+namespace detail {
+
+// Helper class for implementing a UNIX domain endpoint.
+class endpoint
+{
+public:
+  // Default constructor.
+  ASIO_DECL endpoint();
+
+  // Construct an endpoint using the specified path name.
+  ASIO_DECL endpoint(const char* path);
+
+  // Construct an endpoint using the specified path name.
+  ASIO_DECL endpoint(const std::string& path);
+
+  // Copy constructor.
+  endpoint(const endpoint& other)
+    : data_(other.data_),
+      path_length_(other.path_length_)
+  {
+  }
+
+  // Assign from another endpoint.
+  endpoint& operator=(const endpoint& other)
+  {
+    data_ = other.data_;
+    path_length_ = other.path_length_;
+    return *this;
+  }
+
+  // Get the underlying endpoint in the native type.
+  asio::detail::socket_addr_type* data()
+  {
+    return &data_.base;
+  }
+
+  // Get the underlying endpoint in the native type.
+  const asio::detail::socket_addr_type* data() const
+  {
+    return &data_.base;
+  }
+
+  // Get the underlying size of the endpoint in the native type.
+  std::size_t size() const
+  {
+    return path_length_
+      + offsetof(asio::detail::sockaddr_un_type, sun_path);
+  }
+
+  // Set the underlying size of the endpoint in the native type.
+  ASIO_DECL void resize(std::size_t size);
+
+  // Get the capacity of the endpoint in the native type.
+  std::size_t capacity() const
+  {
+    return sizeof(asio::detail::sockaddr_un_type);
+  }
+
+  // Get the path associated with the endpoint.
+  ASIO_DECL std::string path() const;
+
+  // Set the path associated with the endpoint.
+  ASIO_DECL void path(const char* p);
+
+  // Set the path associated with the endpoint.
+  ASIO_DECL void path(const std::string& p);
+
+  // Compare two endpoints for equality.
+  ASIO_DECL friend bool operator==(
+      const endpoint& e1, const endpoint& e2);
+
+  // Compare endpoints for ordering.
+  ASIO_DECL friend bool operator<(
+      const endpoint& e1, const endpoint& e2);
+
+private:
+  // The underlying UNIX socket address.
+  union data_union
+  {
+    asio::detail::socket_addr_type base;
+    asio::detail::sockaddr_un_type local;
+  } data_;
+
+  // The length of the path associated with the endpoint.
+  std::size_t path_length_;
+
+  // Initialise with a specified path.
+  ASIO_DECL void init(const char* path, std::size_t path_length);
+};
+
+} // namespace detail
+} // namespace local
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/local/detail/impl/endpoint.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
+#endif // defined(ASIO_HAS_LOCAL_SOCKETS)
+
+#endif // ASIO_LOCAL_DETAIL_ENDPOINT_HPP
diff --git a/ext/asio/asio/local/detail/impl/endpoint.ipp b/ext/asio/asio/local/detail/impl/endpoint.ipp
new file mode 100644
index 0000000..1bc2c94
--- /dev/null
+++ b/ext/asio/asio/local/detail/impl/endpoint.ipp
@@ -0,0 +1,138 @@
+//
+// local/detail/impl/endpoint.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Derived from a public domain implementation written by Daniel Casimiro.
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_LOCAL_DETAIL_IMPL_ENDPOINT_IPP
+#define ASIO_LOCAL_DETAIL_IMPL_ENDPOINT_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(ASIO_HAS_LOCAL_SOCKETS)
+
+#include <cstring>
+#include "asio/detail/socket_ops.hpp"
+#include "asio/detail/throw_error.hpp"
+#include "asio/error.hpp"
+#include "asio/local/detail/endpoint.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace local {
+namespace detail {
+
+ASIO_DECL
+endpoint::endpoint()
+{
+  init("", 0);
+}
+
+ASIO_DECL
+endpoint::endpoint(const char* path)
+{
+  using namespace std; // For strlen.
+  init(path, strlen(path));
+}
+
+ASIO_DECL
+endpoint::endpoint(const std::string& path)
+{
+  init(path.data(), path.length());
+}
+
+ASIO_DECL
+void endpoint::resize(std::size_t size)
+{
+  if (size > sizeof(asio::detail::sockaddr_un_type))
+  {
+    asio::error_code ec(asio::error::invalid_argument);
+    asio::detail::throw_error(ec);
+  }
+  else if (size == 0)
+  {
+    path_length_ = 0;
+  }
+  else
+  {
+    path_length_ = size
+      - offsetof(asio::detail::sockaddr_un_type, sun_path);
+
+    // The path returned by the operating system may be NUL-terminated.
+    if (path_length_ > 0 && data_.local.sun_path[path_length_ - 1] == 0)
+      --path_length_;
+  }
+}
+
+ASIO_DECL
+std::string endpoint::path() const
+{
+  return std::string(data_.local.sun_path, path_length_);
+}
+
+ASIO_DECL
+void endpoint::path(const char* p)
+{
+  using namespace std; // For strlen.
+  init(p, strlen(p));
+}
+
+ASIO_DECL
+void endpoint::path(const std::string& p)
+{
+  init(p.data(), p.length());
+}
+
+ASIO_DECL
+bool operator==(const endpoint& e1, const endpoint& e2)
+{
+  return e1.path() == e2.path();
+}
+
+ASIO_DECL
+bool operator<(const endpoint& e1, const endpoint& e2)
+{
+  return e1.path() < e2.path();
+}
+
+ASIO_DECL
+void endpoint::init(const char* path, std::size_t path_length)
+{
+  if (path_length > sizeof(data_.local.sun_path) - 1)
+  {
+    // The buffer is not large enough to store this address.
+    asio::error_code ec(asio::error::name_too_long);
+    asio::detail::throw_error(ec);
+  }
+
+  using namespace std; // For memcpy.
+  data_.local = asio::detail::sockaddr_un_type();
+  data_.local.sun_family = AF_UNIX;
+  memcpy(data_.local.sun_path, path, path_length);
+  path_length_ = path_length;
+
+  // NUL-terminate normal path names. Names that start with a NUL are in the
+  // UNIX domain protocol's "abstract namespace" and are not NUL-terminated.
+  if (path_length > 0 && data_.local.sun_path[0] == 0)
+    data_.local.sun_path[path_length] = 0;
+}
+
+} // namespace detail
+} // namespace local
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(ASIO_HAS_LOCAL_SOCKETS)
+
+#endif // ASIO_LOCAL_DETAIL_IMPL_ENDPOINT_IPP
diff --git a/ext/asio/asio/local/stream_protocol.hpp b/ext/asio/asio/local/stream_protocol.hpp
index 47fe42f..e65a2f6 100644
--- a/ext/asio/asio/local/stream_protocol.hpp
+++ b/ext/asio/asio/local/stream_protocol.hpp
@@ -1,8 +1,8 @@
 //
-// stream_protocol.hpp
-// ~~~~~~~~~~~~~~~~~~~
+// local/stream_protocol.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,16 +15,18 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
+
+#if defined(ASIO_HAS_LOCAL_SOCKETS) \
+  || defined(GENERATING_DOCUMENTATION)
 
 #include "asio/basic_socket_acceptor.hpp"
 #include "asio/basic_socket_iostream.hpp"
 #include "asio/basic_stream_socket.hpp"
-#include "asio/local/basic_endpoint.hpp"
 #include "asio/detail/socket_types.hpp"
+#include "asio/local/basic_endpoint.hpp"
 
-#if defined(ASIO_HAS_LOCAL_SOCKETS) \
-  || defined(GENERATING_DOCUMENTATION)
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 namespace local {
@@ -80,9 +82,9 @@ public:
 } // namespace local
 } // namespace asio
 
+#include "asio/detail/pop_options.hpp"
+
 #endif // defined(ASIO_HAS_LOCAL_SOCKETS)
        //   || defined(GENERATING_DOCUMENTATION)
 
-#include "asio/detail/pop_options.hpp"
-
 #endif // ASIO_LOCAL_STREAM_PROTOCOL_HPP
diff --git a/ext/asio/asio/placeholders.hpp b/ext/asio/asio/placeholders.hpp
index 70e69fc..6fda487 100644
--- a/ext/asio/asio/placeholders.hpp
+++ b/ext/asio/asio/placeholders.hpp
@@ -2,7 +2,7 @@
 // placeholders.hpp
 // ~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,12 +15,11 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 #include <boost/bind/arg.hpp>
 #include <boost/detail/workaround.hpp>
-#include "asio/detail/pop_options.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 namespace placeholders {
diff --git a/ext/asio/asio/posix/basic_descriptor.hpp b/ext/asio/asio/posix/basic_descriptor.hpp
index 37bcc94..591e65a 100644
--- a/ext/asio/asio/posix/basic_descriptor.hpp
+++ b/ext/asio/asio/posix/basic_descriptor.hpp
@@ -1,8 +1,8 @@
 //
-// basic_descriptor.hpp
-// ~~~~~~~~~~~~~~~~~~~~
+// posix/basic_descriptor.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,16 +15,17 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
+#if defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) \
+  || defined(GENERATING_DOCUMENTATION)
 
 #include "asio/basic_io_object.hpp"
+#include "asio/detail/throw_error.hpp"
 #include "asio/error.hpp"
 #include "asio/posix/descriptor_base.hpp"
-#include "asio/detail/throw_error.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 namespace posix {
@@ -291,4 +292,7 @@ protected:
 
 #include "asio/detail/pop_options.hpp"
 
+#endif // defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR)
+       //   || defined(GENERATING_DOCUMENTATION)
+
 #endif // ASIO_POSIX_BASIC_DESCRIPTOR_HPP
diff --git a/ext/asio/asio/posix/basic_stream_descriptor.hpp b/ext/asio/asio/posix/basic_stream_descriptor.hpp
index 21e2287..8211c58 100644
--- a/ext/asio/asio/posix/basic_stream_descriptor.hpp
+++ b/ext/asio/asio/posix/basic_stream_descriptor.hpp
@@ -1,8 +1,8 @@
 //
-// basic_stream_descriptor.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// posix/basic_stream_descriptor.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,20 +15,18 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 
-#include "asio/detail/push_options.hpp"
-#include <cstddef>
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
+#if defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) \
+  || defined(GENERATING_DOCUMENTATION)
 
+#include <cstddef>
+#include "asio/detail/throw_error.hpp"
 #include "asio/error.hpp"
 #include "asio/posix/basic_descriptor.hpp"
 #include "asio/posix/stream_descriptor_service.hpp"
-#include "asio/detail/throw_error.hpp"
 
-#if defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) \
-  || defined(GENERATING_DOCUMENTATION)
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 namespace posix {
@@ -296,9 +294,9 @@ public:
 } // namespace posix
 } // namespace asio
 
+#include "asio/detail/pop_options.hpp"
+
 #endif // defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR)
        //   || defined(GENERATING_DOCUMENTATION)
 
-#include "asio/detail/pop_options.hpp"
-
 #endif // ASIO_POSIX_BASIC_STREAM_DESCRIPTOR_HPP
diff --git a/ext/asio/asio/posix/descriptor_base.hpp b/ext/asio/asio/posix/descriptor_base.hpp
index 29e1746..2222915 100644
--- a/ext/asio/asio/posix/descriptor_base.hpp
+++ b/ext/asio/asio/posix/descriptor_base.hpp
@@ -1,8 +1,8 @@
 //
-// descriptor_base.hpp
-// ~~~~~~~~~~~~~~~~~~~
+// posix/descriptor_base.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,16 +15,16 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include <boost/detail/workaround.hpp>
-#include "asio/detail/pop_options.hpp"
+#if defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) \
+  || defined(GENERATING_DOCUMENTATION)
 
 #include "asio/detail/io_control.hpp"
 #include "asio/detail/socket_option.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 namespace posix {
 
@@ -90,4 +90,7 @@ protected:
 
 #include "asio/detail/pop_options.hpp"
 
+#endif // defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR)
+       //   || defined(GENERATING_DOCUMENTATION)
+
 #endif // ASIO_POSIX_DESCRIPTOR_BASE_HPP
diff --git a/ext/asio/asio/posix/stream_descriptor.hpp b/ext/asio/asio/posix/stream_descriptor.hpp
index 72fbbed..48c20a3 100644
--- a/ext/asio/asio/posix/stream_descriptor.hpp
+++ b/ext/asio/asio/posix/stream_descriptor.hpp
@@ -1,8 +1,8 @@
 //
-// stream_descriptor.hpp
-// ~~~~~~~~~~~~~~~~~~~~~
+// posix/stream_descriptor.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,13 +15,13 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/posix/basic_stream_descriptor.hpp"
+#include "asio/detail/config.hpp"
 
 #if defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) \
   || defined(GENERATING_DOCUMENTATION)
 
+#include "asio/posix/basic_stream_descriptor.hpp"
+
 namespace asio {
 namespace posix {
 
@@ -34,6 +34,4 @@ typedef basic_stream_descriptor<> stream_descriptor;
 #endif // defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR)
        //   || defined(GENERATING_DOCUMENTATION)
 
-#include "asio/detail/pop_options.hpp"
-
 #endif // ASIO_POSIX_STREAM_DESCRIPTOR_HPP
diff --git a/ext/asio/asio/posix/stream_descriptor_service.hpp b/ext/asio/asio/posix/stream_descriptor_service.hpp
index 61cee1b..4660e79 100644
--- a/ext/asio/asio/posix/stream_descriptor_service.hpp
+++ b/ext/asio/asio/posix/stream_descriptor_service.hpp
@@ -1,8 +1,8 @@
 //
-// stream_descriptor_service.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// posix/stream_descriptor_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,28 +15,18 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <cstddef>
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
-
-#include "asio/error.hpp"
-#include "asio/io_service.hpp"
-#include "asio/detail/service_base.hpp"
-
-#if !defined(ASIO_DISABLE_POSIX_STREAM_DESCRIPTOR)
-# if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
-#  define ASIO_HAS_POSIX_STREAM_DESCRIPTOR 1
-# endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
-#endif // !defined(ASIO_DISABLE_POSIX_STREAM_DESCRIPTOR)
+#include "asio/detail/config.hpp"
 
 #if defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) \
   || defined(GENERATING_DOCUMENTATION)
 
+#include <cstddef>
+#include "asio/error.hpp"
+#include "asio/io_service.hpp"
 #include "asio/detail/reactive_descriptor_service.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 namespace posix {
 
@@ -179,9 +169,9 @@ private:
 } // namespace posix
 } // namespace asio
 
+#include "asio/detail/pop_options.hpp"
+
 #endif // defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR)
        //   || defined(GENERATING_DOCUMENTATION)
 
-#include "asio/detail/pop_options.hpp"
-
 #endif // ASIO_POSIX_STREAM_DESCRIPTOR_SERVICE_HPP
diff --git a/ext/asio/asio/raw_socket_service.hpp b/ext/asio/asio/raw_socket_service.hpp
index a8973d3..3d0016d 100644
--- a/ext/asio/asio/raw_socket_service.hpp
+++ b/ext/asio/asio/raw_socket_service.hpp
@@ -2,7 +2,7 @@
 // raw_socket_service.hpp
 // ~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,16 +15,10 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 #include <cstddef>
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
-
 #include "asio/error.hpp"
 #include "asio/io_service.hpp"
-#include "asio/detail/service_base.hpp"
 
 #if defined(ASIO_HAS_IOCP)
 # include "asio/detail/win_iocp_socket_service.hpp"
@@ -32,6 +26,8 @@
 # include "asio/detail/reactive_socket_service.hpp"
 #endif
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 
 /// Default service implementation for a raw socket.
diff --git a/ext/asio/asio/read.hpp b/ext/asio/asio/read.hpp
index 859c05a..7f04b07 100644
--- a/ext/asio/asio/read.hpp
+++ b/ext/asio/asio/read.hpp
@@ -2,7 +2,7 @@
 // read.hpp
 // ~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,16 +15,13 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 #include <cstddef>
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
-
-#include "asio/basic_streambuf.hpp"
+#include "asio/basic_streambuf_fwd.hpp"
 #include "asio/error.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 
 /**
@@ -536,8 +533,8 @@ void async_read(AsyncReadStream& s, basic_streambuf<Allocator>& b,
 
 } // namespace asio
 
-#include "asio/impl/read.ipp"
-
 #include "asio/detail/pop_options.hpp"
 
+#include "asio/impl/read.hpp"
+
 #endif // ASIO_READ_HPP
diff --git a/ext/asio/asio/read_at.hpp b/ext/asio/asio/read_at.hpp
index 6bb3fe1..4be1f96 100644
--- a/ext/asio/asio/read_at.hpp
+++ b/ext/asio/asio/read_at.hpp
@@ -2,7 +2,7 @@
 // read_at.hpp
 // ~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,17 +15,14 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 #include <cstddef>
-#include <boost/config.hpp>
 #include <boost/cstdint.hpp>
-#include "asio/detail/pop_options.hpp"
-
-#include "asio/basic_streambuf.hpp"
+#include "asio/basic_streambuf_fwd.hpp"
 #include "asio/error.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 
 /**
@@ -569,8 +566,8 @@ void async_read_at(AsyncRandomAccessReadDevice& d,
 
 } // namespace asio
 
-#include "asio/impl/read_at.ipp"
-
 #include "asio/detail/pop_options.hpp"
 
+#include "asio/impl/read_at.hpp"
+
 #endif // ASIO_READ_AT_HPP
diff --git a/ext/asio/asio/read_until.hpp b/ext/asio/asio/read_until.hpp
index 5df71ce..67fa066 100644
--- a/ext/asio/asio/read_until.hpp
+++ b/ext/asio/asio/read_until.hpp
@@ -2,7 +2,7 @@
 // read_until.hpp
 // ~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,27 +15,22 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
+#include "asio/detail/config.hpp"
 
 #if !defined(BOOST_NO_IOSTREAM)
 
-#include "asio/detail/push_options.hpp"
 #include <cstddef>
-#include <boost/regex.hpp>
 #include <boost/type_traits/is_function.hpp>
 #include <boost/type_traits/remove_pointer.hpp>
 #include <boost/utility/enable_if.hpp>
 #include <boost/detail/workaround.hpp>
 #include <string>
-#include "asio/detail/pop_options.hpp"
-
 #include "asio/basic_streambuf.hpp"
+#include "asio/detail/regex_fwd.hpp"
 #include "asio/error.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 
 namespace detail
@@ -914,10 +909,10 @@ void async_read_until(AsyncReadStream& s,
 
 } // namespace asio
 
-#include "asio/impl/read_until.ipp"
+#include "asio/detail/pop_options.hpp"
+
+#include "asio/impl/read_until.hpp"
 
 #endif // !defined(BOOST_NO_IOSTREAM)
 
-#include "asio/detail/pop_options.hpp"
-
 #endif // ASIO_READ_UNTIL_HPP
diff --git a/ext/asio/asio/serial_port.hpp b/ext/asio/asio/serial_port.hpp
index a55a03a..4cc6fd4 100644
--- a/ext/asio/asio/serial_port.hpp
+++ b/ext/asio/asio/serial_port.hpp
@@ -2,7 +2,7 @@
 // serial_port.hpp
 // ~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 // Copyright (c) 2008 Rep Invariant Systems, Inc. (info at repinvariant.com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
@@ -16,13 +16,13 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/basic_serial_port.hpp"
+#include "asio/detail/config.hpp"
 
 #if defined(ASIO_HAS_SERIAL_PORT) \
   || defined(GENERATING_DOCUMENTATION)
 
+#include "asio/basic_serial_port.hpp"
+
 namespace asio {
 
 /// Typedef for the typical usage of a serial port.
@@ -33,6 +33,4 @@ typedef basic_serial_port<> serial_port;
 #endif // defined(ASIO_HAS_SERIAL_PORT)
        //   || defined(GENERATING_DOCUMENTATION)
 
-#include "asio/detail/pop_options.hpp"
-
 #endif // ASIO_SERIAL_PORT_HPP
diff --git a/ext/asio/asio/serial_port_base.hpp b/ext/asio/asio/serial_port_base.hpp
index 28e51a0..9c7a773 100644
--- a/ext/asio/asio/serial_port_base.hpp
+++ b/ext/asio/asio/serial_port_base.hpp
@@ -2,7 +2,7 @@
 // serial_port_base.hpp
 // ~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 // Copyright (c) 2008 Rep Invariant Systems, Inc. (info at repinvariant.com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
@@ -16,32 +16,18 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <stdexcept>
-#include <boost/config.hpp>
-#include <boost/detail/workaround.hpp>
-#include "asio/detail/pop_options.hpp"
-
-#if !defined(ASIO_DISABLE_SERIAL_PORT)
-# if defined(ASIO_HAS_IOCP) \
-    || !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
-#  define ASIO_HAS_SERIAL_PORT 1
-# endif // defined(ASIO_HAS_IOCP)
-#endif // !defined(ASIO_DISABLE_STREAM_HANDLE)
+#include "asio/detail/config.hpp"
 
 #if defined(ASIO_HAS_SERIAL_PORT) \
   || defined(GENERATING_DOCUMENTATION)
 
 #if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
-# include "asio/detail/push_options.hpp"
 # include <termios.h>
-# include "asio/detail/pop_options.hpp"
 #endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
 
-#include "asio/error_code.hpp"
+#include <boost/detail/workaround.hpp>
 #include "asio/detail/socket_types.hpp"
+#include "asio/error_code.hpp"
 
 #if defined(GENERATING_DOCUMENTATION)
 # define ASIO_OPTION_STORAGE implementation_defined
@@ -51,6 +37,8 @@
 # define ASIO_OPTION_STORAGE termios
 #endif
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 
 /// The serial_port_base class is used as a base for the basic_serial_port class
@@ -67,9 +55,11 @@ public:
   public:
     explicit baud_rate(unsigned int rate = 0);
     unsigned int value() const;
-    asio::error_code store(ASIO_OPTION_STORAGE& storage,
+    ASIO_DECL asio::error_code store(
+        ASIO_OPTION_STORAGE& storage,
         asio::error_code& ec) const;
-    asio::error_code load(const ASIO_OPTION_STORAGE& storage,
+    ASIO_DECL asio::error_code load(
+        const ASIO_OPTION_STORAGE& storage,
         asio::error_code& ec);
   private:
     unsigned int value_;
@@ -83,11 +73,13 @@ public:
   {
   public:
     enum type { none, software, hardware };
-    explicit flow_control(type t = none);
+    ASIO_DECL explicit flow_control(type t = none);
     type value() const;
-    asio::error_code store(ASIO_OPTION_STORAGE& storage,
+    ASIO_DECL asio::error_code store(
+        ASIO_OPTION_STORAGE& storage,
         asio::error_code& ec) const;
-    asio::error_code load(const ASIO_OPTION_STORAGE& storage,
+    ASIO_DECL asio::error_code load(
+        const ASIO_OPTION_STORAGE& storage,
         asio::error_code& ec);
   private:
     type value_;
@@ -101,11 +93,13 @@ public:
   {
   public:
     enum type { none, odd, even };
-    explicit parity(type t = none);
+    ASIO_DECL explicit parity(type t = none);
     type value() const;
-    asio::error_code store(ASIO_OPTION_STORAGE& storage,
+    ASIO_DECL asio::error_code store(
+        ASIO_OPTION_STORAGE& storage,
         asio::error_code& ec) const;
-    asio::error_code load(const ASIO_OPTION_STORAGE& storage,
+    ASIO_DECL asio::error_code load(
+        const ASIO_OPTION_STORAGE& storage,
         asio::error_code& ec);
   private:
     type value_;
@@ -119,11 +113,13 @@ public:
   {
   public:
     enum type { one, onepointfive, two };
-    explicit stop_bits(type t = one);
+    ASIO_DECL explicit stop_bits(type t = one);
     type value() const;
-    asio::error_code store(ASIO_OPTION_STORAGE& storage,
+    ASIO_DECL asio::error_code store(
+        ASIO_OPTION_STORAGE& storage,
         asio::error_code& ec) const;
-    asio::error_code load(const ASIO_OPTION_STORAGE& storage,
+    ASIO_DECL asio::error_code load(
+        const ASIO_OPTION_STORAGE& storage,
         asio::error_code& ec);
   private:
     type value_;
@@ -136,11 +132,13 @@ public:
   class character_size
   {
   public:
-    explicit character_size(unsigned int t = 8);
+    ASIO_DECL explicit character_size(unsigned int t = 8);
     unsigned int value() const;
-    asio::error_code store(ASIO_OPTION_STORAGE& storage,
+    ASIO_DECL asio::error_code store(
+        ASIO_OPTION_STORAGE& storage,
         asio::error_code& ec) const;
-    asio::error_code load(const ASIO_OPTION_STORAGE& storage,
+    ASIO_DECL asio::error_code load(
+        const ASIO_OPTION_STORAGE& storage,
         asio::error_code& ec);
   private:
     unsigned int value_;
@@ -161,13 +159,16 @@ private:
 
 } // namespace asio
 
-#include "asio/impl/serial_port_base.ipp"
+#include "asio/detail/pop_options.hpp"
 
 #undef ASIO_OPTION_STORAGE
 
+#include "asio/impl/serial_port_base.hpp"
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/impl/serial_port_base.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
 #endif // defined(ASIO_HAS_SERIAL_PORT)
        //   || defined(GENERATING_DOCUMENTATION)
 
-#include "asio/detail/pop_options.hpp"
-
 #endif // ASIO_SERIAL_PORT_BASE_HPP
diff --git a/ext/asio/asio/serial_port_service.hpp b/ext/asio/asio/serial_port_service.hpp
index 5847c29..37142d5 100644
--- a/ext/asio/asio/serial_port_service.hpp
+++ b/ext/asio/asio/serial_port_service.hpp
@@ -2,7 +2,7 @@
 // serial_port_service.hpp
 // ~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,23 +15,20 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
+
+#if defined(ASIO_HAS_SERIAL_PORT) \
+  || defined(GENERATING_DOCUMENTATION)
 
-#include "asio/detail/push_options.hpp"
 #include <cstddef>
-#include <boost/config.hpp>
 #include <string>
-#include "asio/detail/pop_options.hpp"
-
+#include "asio/detail/reactive_serial_port_service.hpp"
+#include "asio/detail/win_iocp_serial_port_service.hpp"
 #include "asio/error.hpp"
 #include "asio/io_service.hpp"
 #include "asio/serial_port_base.hpp"
-#include "asio/detail/service_base.hpp"
-#include "asio/detail/reactive_serial_port_service.hpp"
-#include "asio/detail/win_iocp_serial_port_service.hpp"
 
-#if defined(ASIO_HAS_SERIAL_PORT) \
-  || defined(GENERATING_DOCUMENTATION)
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 
@@ -199,9 +196,9 @@ private:
 
 } // namespace asio
 
+#include "asio/detail/pop_options.hpp"
+
 #endif // defined(ASIO_HAS_SERIAL_PORT)
        //   || defined(GENERATING_DOCUMENTATION)
 
-#include "asio/detail/pop_options.hpp"
-
 #endif // ASIO_SERIAL_PORT_SERVICE_HPP
diff --git a/ext/asio/asio/socket_acceptor_service.hpp b/ext/asio/asio/socket_acceptor_service.hpp
index b2e2c6d..a1e4874 100644
--- a/ext/asio/asio/socket_acceptor_service.hpp
+++ b/ext/asio/asio/socket_acceptor_service.hpp
@@ -2,7 +2,7 @@
 // socket_acceptor_service.hpp
 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,12 +15,10 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
+#include "asio/detail/config.hpp"
 #include "asio/basic_socket.hpp"
 #include "asio/error.hpp"
 #include "asio/io_service.hpp"
-#include "asio/detail/service_base.hpp"
 
 #if defined(ASIO_HAS_IOCP)
 # include "asio/detail/win_iocp_socket_service.hpp"
@@ -28,6 +26,8 @@
 # include "asio/detail/reactive_socket_service.hpp"
 #endif
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 
 /// Default service implementation for a socket acceptor.
diff --git a/ext/asio/asio/socket_base.hpp b/ext/asio/asio/socket_base.hpp
index d82cd22..56585e1 100644
--- a/ext/asio/asio/socket_base.hpp
+++ b/ext/asio/asio/socket_base.hpp
@@ -2,7 +2,7 @@
 // socket_base.hpp
 // ~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,17 +15,14 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
+#include "asio/detail/config.hpp"
 #include <boost/detail/workaround.hpp>
-#include "asio/detail/pop_options.hpp"
-
 #include "asio/detail/io_control.hpp"
 #include "asio/detail/socket_option.hpp"
 #include "asio/detail/socket_types.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 
 /// The socket_base class is used as a base for the basic_stream_socket and
diff --git a/ext/asio/asio/ssl.hpp b/ext/asio/asio/ssl.hpp
index a9fff5e..48aff5a 100644
--- a/ext/asio/asio/ssl.hpp
+++ b/ext/asio/asio/ssl.hpp
@@ -2,7 +2,7 @@
 // ssl.hpp
 // ~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/ext/asio/asio/ssl/basic_context.hpp b/ext/asio/asio/ssl/basic_context.hpp
index ea3893e..20ed57d 100755
--- a/ext/asio/asio/ssl/basic_context.hpp
+++ b/ext/asio/asio/ssl/basic_context.hpp
@@ -1,9 +1,9 @@
 //
-// basic_context.hpp
-// ~~~~~~~~~~~~~~~~~
+// ssl/basic_context.hpp
+// ~~~~~~~~~~~~~~~~~~~~~
 //
 // Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com
-// Copyright (c) 2005-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2005-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -16,17 +16,15 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 #include <string>
 #include <boost/noncopyable.hpp>
-#include "asio/detail/pop_options.hpp"
-
+#include "asio/detail/throw_error.hpp"
 #include "asio/error.hpp"
 #include "asio/io_service.hpp"
 #include "asio/ssl/context_base.hpp"
-#include "asio/detail/throw_error.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 namespace ssl {
diff --git a/ext/asio/asio/ssl/context.hpp b/ext/asio/asio/ssl/context.hpp
index d53882a..7aedc4d 100644
--- a/ext/asio/asio/ssl/context.hpp
+++ b/ext/asio/asio/ssl/context.hpp
@@ -1,9 +1,9 @@
 //
-// context.hpp
-// ~~~~~~~~~~~
+// ssl/context.hpp
+// ~~~~~~~~~~~~~~~
 //
 // Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com
-// Copyright (c) 2005-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2005-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -16,8 +16,7 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
+#include "asio/detail/config.hpp"
 #include "asio/ssl/basic_context.hpp"
 #include "asio/ssl/context_service.hpp"
 
@@ -30,6 +29,4 @@ typedef basic_context<context_service> context;
 } // namespace ssl
 } // namespace asio
 
-#include "asio/detail/pop_options.hpp"
-
 #endif // ASIO_SSL_CONTEXT_HPP
diff --git a/ext/asio/asio/ssl/context_base.hpp b/ext/asio/asio/ssl/context_base.hpp
index a0700ca..7636bed 100755
--- a/ext/asio/asio/ssl/context_base.hpp
+++ b/ext/asio/asio/ssl/context_base.hpp
@@ -1,8 +1,8 @@
 //
-// context_base.hpp
-// ~~~~~~~~~~~~~~~~
+// ssl/context_base.hpp
+// ~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2005-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2005-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,15 +15,12 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
+#include "asio/detail/config.hpp"
 #include <boost/detail/workaround.hpp>
-#include "asio/detail/pop_options.hpp"
-
 #include "asio/ssl/detail/openssl_types.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 namespace ssl {
 
diff --git a/ext/asio/asio/ssl/context_service.hpp b/ext/asio/asio/ssl/context_service.hpp
index e9cfef7..766bbde 100755
--- a/ext/asio/asio/ssl/context_service.hpp
+++ b/ext/asio/asio/ssl/context_service.hpp
@@ -1,9 +1,9 @@
 //
-// context_service.hpp
-// ~~~~~~~~~~~~~~~~~~~
+// ssl/context_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~
 //
 // Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com
-// Copyright (c) 2005-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2005-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -16,19 +16,16 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 #include <string>
 #include <boost/noncopyable.hpp>
-#include "asio/detail/pop_options.hpp"
-
 #include "asio/error.hpp"
 #include "asio/io_service.hpp"
-#include "asio/detail/service_base.hpp"
 #include "asio/ssl/context_base.hpp"
 #include "asio/ssl/detail/openssl_context_service.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 namespace ssl {
 
diff --git a/ext/asio/asio/ssl/detail/openssl_context_service.hpp b/ext/asio/asio/ssl/detail/openssl_context_service.hpp
index a3d4fdb..7019542 100755
--- a/ext/asio/asio/ssl/detail/openssl_context_service.hpp
+++ b/ext/asio/asio/ssl/detail/openssl_context_service.hpp
@@ -1,9 +1,9 @@
 //
-// openssl_context_service.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// ssl/detail/openssl_context_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
 // Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com
-// Copyright (c) 2005-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2005-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -16,21 +16,18 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 #include <cstring>
 #include <string>
 #include <boost/function.hpp>
-#include "asio/detail/pop_options.hpp"
-
 #include "asio/error.hpp"
 #include "asio/io_service.hpp"
-#include "asio/detail/service_base.hpp"
 #include "asio/ssl/context_base.hpp"
 #include "asio/ssl/detail/openssl_init.hpp"
 #include "asio/ssl/detail/openssl_types.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 namespace ssl {
 namespace detail {
diff --git a/ext/asio/asio/ssl/detail/openssl_init.hpp b/ext/asio/asio/ssl/detail/openssl_init.hpp
index 9ecbb78..dcda50f 100755
--- a/ext/asio/asio/ssl/detail/openssl_init.hpp
+++ b/ext/asio/asio/ssl/detail/openssl_init.hpp
@@ -1,9 +1,9 @@
 //
-// openssl_init.hpp
-// ~~~~~~~~~~~~~~~~
+// ssl/detail/openssl_init.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
 // Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com
-// Copyright (c) 2005-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2005-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -16,20 +16,17 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 #include <cstring>
 #include <vector>
 #include <boost/assert.hpp>
-#include <boost/config.hpp>
 #include <boost/shared_ptr.hpp>
-#include "asio/detail/pop_options.hpp"
-
 #include "asio/detail/mutex.hpp"
 #include "asio/detail/tss_ptr.hpp"
 #include "asio/ssl/detail/openssl_types.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 namespace ssl {
 namespace detail {
diff --git a/ext/asio/asio/ssl/detail/openssl_operation.hpp b/ext/asio/asio/ssl/detail/openssl_operation.hpp
index 8d237e3..c5119a5 100755
--- a/ext/asio/asio/ssl/detail/openssl_operation.hpp
+++ b/ext/asio/asio/ssl/detail/openssl_operation.hpp
@@ -1,6 +1,6 @@
 //
-// openssl_operation.hpp
-// ~~~~~~~~~~~~~~~~~~~~~
+// ssl/detail/openssl_operation.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
 // Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com
 //
@@ -15,19 +15,19 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 #include <boost/function.hpp>
 #include <boost/assert.hpp>
 #include <boost/bind.hpp>
-#include "asio/detail/pop_options.hpp"
-
 #include "asio/buffer.hpp"
-#include "asio/placeholders.hpp"
-#include "asio/write.hpp"
 #include "asio/detail/socket_ops.hpp"
+#include "asio/placeholders.hpp"
 #include "asio/ssl/detail/openssl_types.hpp"
+#include "asio/strand.hpp"
+#include "asio/system_error.hpp"
+#include "asio/write.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 namespace ssl {
@@ -160,7 +160,7 @@ public:
 
     if (error_code == SSL_ERROR_SSL)
       return handler_(asio::error_code(
-            error_code, asio::error::get_ssl_category()), rc);
+            sys_error_code, asio::error::get_ssl_category()), rc);
 
     bool is_read_needed = (error_code == SSL_ERROR_WANT_READ);
     bool is_write_needed = (error_code == SSL_ERROR_WANT_WRITE ||
@@ -195,7 +195,7 @@ public:
       else
       {
         return handler_(asio::error_code(
-              error_code, asio::error::get_ssl_category()), rc); 
+              sys_error_code, asio::error::get_ssl_category()), rc); 
       }
     }
 
diff --git a/ext/asio/asio/ssl/detail/openssl_stream_service.hpp b/ext/asio/asio/ssl/detail/openssl_stream_service.hpp
index d7bb457..aef9e7e 100644
--- a/ext/asio/asio/ssl/detail/openssl_stream_service.hpp
+++ b/ext/asio/asio/ssl/detail/openssl_stream_service.hpp
@@ -1,9 +1,9 @@
 //
-// stream_service.hpp
-// ~~~~~~~~~~~~~~~~~~
+// ssl/detail/stream_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
 // Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com
-// Copyright (c) 2005-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2005-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -16,9 +16,7 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 #include <cstddef>
 #include <climits>
 #include <memory>
@@ -26,17 +24,17 @@
 #include <boost/noncopyable.hpp>
 #include <boost/function.hpp>
 #include <boost/bind.hpp>
-#include "asio/detail/pop_options.hpp"
-
+#include "asio/detail/buffer_sequence_adapter.hpp"
 #include "asio/error.hpp"
 #include "asio/io_service.hpp"
-#include "asio/strand.hpp"
-#include "asio/detail/buffer_sequence_adapter.hpp"
-#include "asio/detail/service_base.hpp"
 #include "asio/ssl/basic_context.hpp"
 #include "asio/ssl/stream_base.hpp"
 #include "asio/ssl/detail/openssl_operation.hpp"
 #include "asio/ssl/detail/openssl_types.hpp"
+#include "asio/strand.hpp"
+#include "asio/system_error.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 namespace ssl {
@@ -92,7 +90,7 @@ private:
       : base_handler<Stream>(io_service)
       , handler_(handler)
     {
-      set_func(boost::bind(
+      this->set_func(boost::bind(
         &io_handler<Stream, Handler>::handler_impl, 
         this, boost::arg<1>(), boost::arg<2>() ));
     }
@@ -116,7 +114,7 @@ private:
       : base_handler<Stream>(io_service)
       , handler_(handler)
     {
-      set_func(boost::bind(
+      this->set_func(boost::bind(
         &handshake_handler<Stream, Handler>::handler_impl, 
         this, boost::arg<1>(), boost::arg<2>() ));
     }
@@ -141,7 +139,7 @@ private:
       : base_handler<Stream>(io_service),
         handler_(handler)
     { 
-      set_func(boost::bind(
+      this->set_func(boost::bind(
         &shutdown_handler<Stream, Handler>::handler_impl, 
         this, boost::arg<1>(), boost::arg<2>() ));
     }
diff --git a/ext/asio/asio/ssl/detail/openssl_types.hpp b/ext/asio/asio/ssl/detail/openssl_types.hpp
index c697d74..fbe1b74 100755
--- a/ext/asio/asio/ssl/detail/openssl_types.hpp
+++ b/ext/asio/asio/ssl/detail/openssl_types.hpp
@@ -1,8 +1,8 @@
 //
-// openssl_types.hpp
-// ~~~~~~~~~~~~~~~~~
+// ssl/detail/openssl_types.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2005-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2005-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,17 +15,11 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/socket_types.hpp"
-
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 #include <openssl/conf.h>
 #include <openssl/ssl.h>
 #include <openssl/engine.h>
 #include <openssl/err.h>
-#include "asio/detail/pop_options.hpp"
-
-#include "asio/detail/pop_options.hpp"
+#include "asio/detail/socket_types.hpp"
 
 #endif // ASIO_SSL_DETAIL_OPENSSL_TYPES_HPP
diff --git a/ext/asio/asio/ssl/stream.hpp b/ext/asio/asio/ssl/stream.hpp
index e800e62..e16cd9a 100644
--- a/ext/asio/asio/ssl/stream.hpp
+++ b/ext/asio/asio/ssl/stream.hpp
@@ -1,9 +1,9 @@
 //
-// stream.hpp
-// ~~~~~~~~~~
+// ssl/stream.hpp
+// ~~~~~~~~~~~~~~
 //
 // Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com
-// Copyright (c) 2005-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2005-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -16,20 +16,17 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 #include <cstddef>
-#include <boost/config.hpp>
 #include <boost/noncopyable.hpp>
 #include <boost/type_traits/remove_reference.hpp>
-#include "asio/detail/pop_options.hpp"
-
+#include "asio/detail/throw_error.hpp"
 #include "asio/error.hpp"
 #include "asio/ssl/basic_context.hpp"
 #include "asio/ssl/stream_base.hpp"
 #include "asio/ssl/stream_service.hpp"
-#include "asio/detail/throw_error.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 namespace ssl {
diff --git a/ext/asio/asio/ssl/stream_base.hpp b/ext/asio/asio/ssl/stream_base.hpp
index d62d386..e1cc0d7 100755
--- a/ext/asio/asio/ssl/stream_base.hpp
+++ b/ext/asio/asio/ssl/stream_base.hpp
@@ -1,8 +1,8 @@
 //
-// stream_base.hpp
-// ~~~~~~~~~~~~~~~
+// ssl/stream_base.hpp
+// ~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2005-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2005-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,11 +15,10 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
+#include <boost/detail/workaround.hpp>
 
 #include "asio/detail/push_options.hpp"
-#include <boost/detail/workaround.hpp>
-#include "asio/detail/pop_options.hpp"
 
 namespace asio {
 namespace ssl {
diff --git a/ext/asio/asio/ssl/stream_service.hpp b/ext/asio/asio/ssl/stream_service.hpp
index 1f1e6ad..d99548e 100644
--- a/ext/asio/asio/ssl/stream_service.hpp
+++ b/ext/asio/asio/ssl/stream_service.hpp
@@ -1,9 +1,9 @@
 //
-// stream_service.hpp
-// ~~~~~~~~~~~~~~~~~~
+// ssl/stream_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~
 //
 // Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com
-// Copyright (c) 2005-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2005-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -16,19 +16,15 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 #include <cstddef>
-#include <boost/config.hpp>
 #include <boost/noncopyable.hpp>
-#include "asio/detail/pop_options.hpp"
-
 #include "asio/io_service.hpp"
-#include "asio/detail/service_base.hpp"
 #include "asio/ssl/basic_context.hpp"
-#include "asio/ssl/stream_base.hpp"
 #include "asio/ssl/detail/openssl_stream_service.hpp"
+#include "asio/ssl/stream_base.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 namespace ssl {
diff --git a/ext/asio/asio/strand.hpp b/ext/asio/asio/strand.hpp
index 6b32151..5a526f2 100644
--- a/ext/asio/asio/strand.hpp
+++ b/ext/asio/asio/strand.hpp
@@ -2,7 +2,7 @@
 // strand.hpp
 // ~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,11 +15,12 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/io_service.hpp"
+#include "asio/detail/config.hpp"
 #include "asio/detail/strand_service.hpp"
 #include "asio/detail/wrapped_handler.hpp"
+#include "asio/io_service.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 
diff --git a/ext/asio/asio/stream_socket_service.hpp b/ext/asio/asio/stream_socket_service.hpp
index 1c4935c..553719e 100644
--- a/ext/asio/asio/stream_socket_service.hpp
+++ b/ext/asio/asio/stream_socket_service.hpp
@@ -2,7 +2,7 @@
 // stream_socket_service.hpp
 // ~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,16 +15,10 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 #include <cstddef>
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
-
 #include "asio/error.hpp"
 #include "asio/io_service.hpp"
-#include "asio/detail/service_base.hpp"
 
 #if defined(ASIO_HAS_IOCP)
 # include "asio/detail/win_iocp_socket_service.hpp"
@@ -32,6 +26,8 @@
 # include "asio/detail/reactive_socket_service.hpp"
 #endif
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 
 /// Default service implementation for a stream socket.
diff --git a/ext/asio/asio/streambuf.hpp b/ext/asio/asio/streambuf.hpp
index 665155b..553da3e 100644
--- a/ext/asio/asio/streambuf.hpp
+++ b/ext/asio/asio/streambuf.hpp
@@ -2,7 +2,7 @@
 // streambuf.hpp
 // ~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,12 +15,12 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/basic_streambuf.hpp"
+#include "asio/detail/config.hpp"
 
 #if !defined(BOOST_NO_IOSTREAM)
 
+#include "asio/basic_streambuf.hpp"
+
 namespace asio {
 
 /// Typedef for the typical usage of basic_streambuf.
@@ -30,6 +30,4 @@ typedef basic_streambuf<> streambuf;
 
 #endif // !defined(BOOST_NO_IOSTREAM)
 
-#include "asio/detail/pop_options.hpp"
-
 #endif // ASIO_STREAMBUF_HPP
diff --git a/ext/asio/asio/system_error.hpp b/ext/asio/asio/system_error.hpp
index e704b3f..60580a1 100644
--- a/ext/asio/asio/system_error.hpp
+++ b/ext/asio/asio/system_error.hpp
@@ -2,7 +2,7 @@
 // system_error.hpp
 // ~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,18 +15,15 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
+#include "asio/detail/config.hpp"
 #include <boost/scoped_ptr.hpp>
 #include <cerrno>
 #include <exception>
 #include <string>
-#include "asio/detail/pop_options.hpp"
-
 #include "asio/error_code.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 
 /// The system_error class is used to represent system conditions that
diff --git a/ext/asio/asio/thread.hpp b/ext/asio/asio/thread.hpp
index 9e578bc..070483e 100644
--- a/ext/asio/asio/thread.hpp
+++ b/ext/asio/asio/thread.hpp
@@ -2,7 +2,7 @@
 // thread.hpp
 // ~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,11 +15,12 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
+#include "asio/detail/config.hpp"
 #include "asio/detail/noncopyable.hpp"
 #include "asio/detail/thread.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 
 /// A simple abstraction for starting threads.
diff --git a/ext/asio/asio/time_traits.hpp b/ext/asio/asio/time_traits.hpp
index 0371373..3b2899b 100644
--- a/ext/asio/asio/time_traits.hpp
+++ b/ext/asio/asio/time_traits.hpp
@@ -2,7 +2,7 @@
 // time_traits.hpp
 // ~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,14 +15,14 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
 #include "asio/detail/socket_types.hpp" // Must come before posix_time.
 
 #include "asio/detail/push_options.hpp"
 #include <boost/date_time/posix_time/posix_time_types.hpp>
 #include "asio/detail/pop_options.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 
 /// Time traits suitable for use with the deadline timer.
diff --git a/ext/asio/asio/version.hpp b/ext/asio/asio/version.hpp
index 198f508..0402d0e 100644
--- a/ext/asio/asio/version.hpp
+++ b/ext/asio/asio/version.hpp
@@ -2,7 +2,7 @@
 // version.hpp
 // ~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -18,6 +18,6 @@
 // ASIO_VERSION % 100 is the sub-minor version
 // ASIO_VERSION / 100 % 1000 is the minor version
 // ASIO_VERSION / 100000 is the major version
-#define ASIO_VERSION 100405 // 1.4.5
+#define ASIO_VERSION 100408 // 1.4.8
 
 #endif // ASIO_VERSION_HPP
diff --git a/ext/asio/asio/windows/basic_handle.hpp b/ext/asio/asio/windows/basic_handle.hpp
index 8c2ee60..f87b3db 100644
--- a/ext/asio/asio/windows/basic_handle.hpp
+++ b/ext/asio/asio/windows/basic_handle.hpp
@@ -1,8 +1,8 @@
 //
-// basic_handle.hpp
-// ~~~~~~~~~~~~~~~~
+// windows/basic_handle.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,15 +15,17 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
+#if defined(ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) \
+  || defined(ASIO_HAS_WINDOWS_STREAM_HANDLE) \
+  || defined(GENERATING_DOCUMENTATION)
 
 #include "asio/basic_io_object.hpp"
-#include "asio/error.hpp"
 #include "asio/detail/throw_error.hpp"
+#include "asio/error.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 namespace windows {
@@ -222,4 +224,8 @@ protected:
 
 #include "asio/detail/pop_options.hpp"
 
+#endif // defined(ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE)
+       //   || defined(ASIO_HAS_WINDOWS_STREAM_HANDLE)
+       //   || defined(GENERATING_DOCUMENTATION)
+
 #endif // ASIO_WINDOWS_BASIC_HANDLE_HPP
diff --git a/ext/asio/asio/windows/basic_random_access_handle.hpp b/ext/asio/asio/windows/basic_random_access_handle.hpp
index 2e6b994..056b175 100644
--- a/ext/asio/asio/windows/basic_random_access_handle.hpp
+++ b/ext/asio/asio/windows/basic_random_access_handle.hpp
@@ -1,8 +1,8 @@
 //
-// basic_random_access_handle.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// windows/basic_random_access_handle.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,20 +15,18 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 
-#include "asio/detail/push_options.hpp"
-#include <cstddef>
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
+#if defined(ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) \
+  || defined(GENERATING_DOCUMENTATION)
 
+#include <cstddef>
+#include "asio/detail/throw_error.hpp"
 #include "asio/error.hpp"
 #include "asio/windows/basic_handle.hpp"
 #include "asio/windows/random_access_handle_service.hpp"
-#include "asio/detail/throw_error.hpp"
 
-#if defined(ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) \
-  || defined(GENERATING_DOCUMENTATION)
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 namespace windows {
@@ -312,9 +310,9 @@ public:
 } // namespace windows
 } // namespace asio
 
+#include "asio/detail/pop_options.hpp"
+
 #endif // defined(ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE)
        //   || defined(GENERATING_DOCUMENTATION)
 
-#include "asio/detail/pop_options.hpp"
-
 #endif // ASIO_WINDOWS_BASIC_RANDOM_ACCESS_HANDLE_HPP
diff --git a/ext/asio/asio/windows/basic_stream_handle.hpp b/ext/asio/asio/windows/basic_stream_handle.hpp
index 48e7153..28149f4 100644
--- a/ext/asio/asio/windows/basic_stream_handle.hpp
+++ b/ext/asio/asio/windows/basic_stream_handle.hpp
@@ -1,8 +1,8 @@
 //
-// basic_stream_handle.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~
+// windows/basic_stream_handle.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,20 +15,18 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 
-#include "asio/detail/push_options.hpp"
-#include <cstddef>
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
+#if defined(ASIO_HAS_WINDOWS_STREAM_HANDLE) \
+  || defined(GENERATING_DOCUMENTATION)
 
+#include <cstddef>
 #include "asio/error.hpp"
 #include "asio/windows/basic_handle.hpp"
 #include "asio/windows/stream_handle_service.hpp"
 #include "asio/detail/throw_error.hpp"
 
-#if defined(ASIO_HAS_WINDOWS_STREAM_HANDLE) \
-  || defined(GENERATING_DOCUMENTATION)
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 namespace windows {
@@ -294,9 +292,9 @@ public:
 } // namespace windows
 } // namespace asio
 
+#include "asio/detail/pop_options.hpp"
+
 #endif // defined(ASIO_HAS_WINDOWS_STREAM_HANDLE)
        //   || defined(GENERATING_DOCUMENTATION)
 
-#include "asio/detail/pop_options.hpp"
-
 #endif // ASIO_WINDOWS_BASIC_STREAM_HANDLE_HPP
diff --git a/ext/asio/asio/windows/overlapped_ptr.hpp b/ext/asio/asio/windows/overlapped_ptr.hpp
index 087170b..8f4d628 100644
--- a/ext/asio/asio/windows/overlapped_ptr.hpp
+++ b/ext/asio/asio/windows/overlapped_ptr.hpp
@@ -1,8 +1,8 @@
 //
-// overlapped_ptr.hpp
-// ~~~~~~~~~~~~~~~~~~
+// windows/overlapped_ptr.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,20 +15,16 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
+
+#if defined(ASIO_HAS_WINDOWS_OVERLAPPED_PTR) \
+  || defined(GENERATING_DOCUMENTATION)
 
-#include "asio/io_service.hpp"
 #include "asio/detail/noncopyable.hpp"
 #include "asio/detail/win_iocp_overlapped_ptr.hpp"
+#include "asio/io_service.hpp"
 
-#if !defined(ASIO_DISABLE_WINDOWS_OVERLAPPED_PTR)
-# if defined(ASIO_HAS_IOCP)
-#  define ASIO_HAS_WINDOWS_OVERLAPPED_PTR 1
-# endif // defined(ASIO_HAS_IOCP)
-#endif // !defined(ASIO_DISABLE_WINDOWS_OVERLAPPED_PTR)
-
-#if defined(ASIO_HAS_WINDOWS_OVERLAPPED_PTR) \
-  || defined(GENERATING_DOCUMENTATION)
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 namespace windows {
@@ -110,9 +106,9 @@ private:
 } // namespace windows
 } // namespace asio
 
+#include "asio/detail/pop_options.hpp"
+
 #endif // defined(ASIO_HAS_WINDOWS_OVERLAPPED_PTR)
        //   || defined(GENERATING_DOCUMENTATION)
 
-#include "asio/detail/pop_options.hpp"
-
 #endif // ASIO_WINDOWS_OVERLAPPED_PTR_HPP
diff --git a/ext/asio/asio/windows/random_access_handle.hpp b/ext/asio/asio/windows/random_access_handle.hpp
index 6e5dd7b..727b084 100644
--- a/ext/asio/asio/windows/random_access_handle.hpp
+++ b/ext/asio/asio/windows/random_access_handle.hpp
@@ -1,8 +1,8 @@
 //
-// random_access_handle.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~
+// windows/random_access_handle.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,13 +15,13 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/windows/basic_random_access_handle.hpp"
+#include "asio/detail/config.hpp"
 
 #if defined(ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) \
   || defined(GENERATING_DOCUMENTATION)
 
+#include "asio/windows/basic_random_access_handle.hpp"
+
 namespace asio {
 namespace windows {
 
@@ -34,6 +34,4 @@ typedef basic_random_access_handle<> random_access_handle;
 #endif // defined(ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE)
        //   || defined(GENERATING_DOCUMENTATION)
 
-#include "asio/detail/pop_options.hpp"
-
 #endif // ASIO_WINDOWS_RANDOM_ACCESS_HANDLE_HPP
diff --git a/ext/asio/asio/windows/random_access_handle_service.hpp b/ext/asio/asio/windows/random_access_handle_service.hpp
index 2e579f8..b2c05ef 100644
--- a/ext/asio/asio/windows/random_access_handle_service.hpp
+++ b/ext/asio/asio/windows/random_access_handle_service.hpp
@@ -1,8 +1,8 @@
 //
-// random_access_handle_service.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// windows/random_access_handle_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,27 +15,19 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
+
+#if defined(ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) \
+  || defined(GENERATING_DOCUMENTATION)
 
-#include "asio/detail/push_options.hpp"
 #include <cstddef>
 #include <boost/config.hpp>
 #include <boost/cstdint.hpp>
-#include "asio/detail/pop_options.hpp"
-
+#include "asio/detail/win_iocp_handle_service.hpp"
 #include "asio/error.hpp"
 #include "asio/io_service.hpp"
-#include "asio/detail/service_base.hpp"
-#include "asio/detail/win_iocp_handle_service.hpp"
 
-#if !defined(ASIO_DISABLE_WINDOWS_RANDOM_ACCESS_HANDLE)
-# if defined(ASIO_HAS_IOCP)
-#  define ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE 1
-# endif // defined(ASIO_HAS_IOCP)
-#endif // !defined(ASIO_DISABLE_WINDOWS_RANDOM_ACCESS_HANDLE)
-
-#if defined(ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) \
-  || defined(GENERATING_DOCUMENTATION)
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 namespace windows {
@@ -172,9 +164,9 @@ private:
 } // namespace windows
 } // namespace asio
 
+#include "asio/detail/pop_options.hpp"
+
 #endif // defined(ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE)
        //   || defined(GENERATING_DOCUMENTATION)
 
-#include "asio/detail/pop_options.hpp"
-
 #endif // ASIO_WINDOWS_RANDOM_ACCESS_HANDLE_SERVICE_HPP
diff --git a/ext/asio/asio/windows/stream_handle.hpp b/ext/asio/asio/windows/stream_handle.hpp
index d55dc31..802d157 100644
--- a/ext/asio/asio/windows/stream_handle.hpp
+++ b/ext/asio/asio/windows/stream_handle.hpp
@@ -1,8 +1,8 @@
 //
-// stream_handle.hpp
-// ~~~~~~~~~~~~~~~~~~
+// windows/stream_handle.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,13 +15,13 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/windows/basic_stream_handle.hpp"
+#include "asio/detail/config.hpp"
 
 #if defined(ASIO_HAS_WINDOWS_STREAM_HANDLE) \
   || defined(GENERATING_DOCUMENTATION)
 
+#include "asio/windows/basic_stream_handle.hpp"
+
 namespace asio {
 namespace windows {
 
@@ -34,6 +34,4 @@ typedef basic_stream_handle<> stream_handle;
 #endif // defined(ASIO_HAS_WINDOWS_STREAM_HANDLE)
        //   || defined(GENERATING_DOCUMENTATION)
 
-#include "asio/detail/pop_options.hpp"
-
 #endif // ASIO_WINDOWS_STREAM_HANDLE_HPP
diff --git a/ext/asio/asio/windows/stream_handle_service.hpp b/ext/asio/asio/windows/stream_handle_service.hpp
index 75eff60..816cfe5 100644
--- a/ext/asio/asio/windows/stream_handle_service.hpp
+++ b/ext/asio/asio/windows/stream_handle_service.hpp
@@ -1,8 +1,8 @@
 //
-// stream_handle_service.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~
+// windows/stream_handle_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,26 +15,17 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 
-#include "asio/detail/push_options.hpp"
-#include <cstddef>
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
+#if defined(ASIO_HAS_WINDOWS_STREAM_HANDLE) \
+  || defined(GENERATING_DOCUMENTATION)
 
+#include <cstddef>
+#include "asio/detail/win_iocp_handle_service.hpp"
 #include "asio/error.hpp"
 #include "asio/io_service.hpp"
-#include "asio/detail/service_base.hpp"
-#include "asio/detail/win_iocp_handle_service.hpp"
 
-#if !defined(ASIO_DISABLE_WINDOWS_STREAM_HANDLE)
-# if defined(ASIO_HAS_IOCP)
-#  define ASIO_HAS_WINDOWS_STREAM_HANDLE 1
-# endif // defined(ASIO_HAS_IOCP)
-#endif // !defined(ASIO_DISABLE_WINDOWS_STREAM_HANDLE)
-
-#if defined(ASIO_HAS_WINDOWS_STREAM_HANDLE) \
-  || defined(GENERATING_DOCUMENTATION)
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 namespace windows {
@@ -170,9 +161,9 @@ private:
 } // namespace windows
 } // namespace asio
 
+#include "asio/detail/pop_options.hpp"
+
 #endif // defined(ASIO_HAS_WINDOWS_STREAM_HANDLE)
        //   || defined(GENERATING_DOCUMENTATION)
 
-#include "asio/detail/pop_options.hpp"
-
 #endif // ASIO_WINDOWS_STREAM_HANDLE_SERVICE_HPP
diff --git a/ext/asio/asio/write.hpp b/ext/asio/asio/write.hpp
index 2b188cd..bd90ecb 100644
--- a/ext/asio/asio/write.hpp
+++ b/ext/asio/asio/write.hpp
@@ -2,7 +2,7 @@
 // write.hpp
 // ~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,16 +15,13 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 #include <cstddef>
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
-
-#include "asio/basic_streambuf.hpp"
+#include "asio/basic_streambuf_fwd.hpp"
 #include "asio/error.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 
 /**
@@ -533,8 +530,8 @@ void async_write(AsyncWriteStream& s, basic_streambuf<Allocator>& b,
 
 } // namespace asio
 
-#include "asio/impl/write.ipp"
-
 #include "asio/detail/pop_options.hpp"
 
+#include "asio/impl/write.hpp"
+
 #endif // ASIO_WRITE_HPP
diff --git a/ext/asio/asio/write_at.hpp b/ext/asio/asio/write_at.hpp
index 5690bcf..37d0cbb 100644
--- a/ext/asio/asio/write_at.hpp
+++ b/ext/asio/asio/write_at.hpp
@@ -2,7 +2,7 @@
 // write_at.hpp
 // ~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,17 +15,14 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 #include <cstddef>
-#include <boost/config.hpp>
 #include <boost/cstdint.hpp>
-#include "asio/detail/pop_options.hpp"
-
-#include "asio/basic_streambuf.hpp"
+#include "asio/basic_streambuf_fwd.hpp"
 #include "asio/error.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 
 /**
@@ -556,8 +553,8 @@ void async_write_at(AsyncRandomAccessWriteDevice& d, boost::uint64_t offset,
 
 } // namespace asio
 
-#include "asio/impl/write_at.ipp"
-
 #include "asio/detail/pop_options.hpp"
 
+#include "asio/impl/write_at.hpp"
+
 #endif // ASIO_WRITE_AT_HPP
diff --git a/src/bin/auth/main.cc b/src/bin/auth/main.cc
index a6db762..480c2f7 100644
--- a/src/bin/auth/main.cc
+++ b/src/bin/auth/main.cc
@@ -176,9 +176,15 @@ main(int argc, char* argv[]) {
         // all initial configurations, but as a short term workaround we
         // handle the traditional "database_file" setup by directly calling
         // updateConfig().
+        // if server load configure failed, we won't exit, give user second chance
+        // to correct the configure.
         auth_server->setConfigSession(config_session);
-        configureAuthServer(*auth_server, config_session->getFullConfig());
-        auth_server->updateConfig(ElementPtr());
+        try {
+            configureAuthServer(*auth_server, config_session->getFullConfig());
+            auth_server->updateConfig(ElementPtr());
+        } catch (const AuthConfigError& ex) {
+            cout << "[bin10-auth] Server load config failed:" << ex.what() << endl;
+        }
 
         if (uid != NULL) {
             changeUser(uid);
diff --git a/src/bin/auth/statistics.cc b/src/bin/auth/statistics.cc
index e68793c..415aa14 100644
--- a/src/bin/auth/statistics.cc
+++ b/src/bin/auth/statistics.cc
@@ -91,10 +91,6 @@ AuthCountersImpl::submitStatistics() const {
         const int seq =
             statistics_session_->group_sendmsg(statistics_element, "Stats");
         isc::data::ConstElementPtr env, answer;
-        if (verbose_mode_) {
-            std::cerr << "[b10-auth] "
-                      << "send statistics data" << std::endl;
-        }
         // TODO: parse and check response from statistics module
         // currently it just returns empty message
         statistics_session_->group_recvmsg(env, answer, false, seq);
diff --git a/src/bin/auth/tests/Makefile.am b/src/bin/auth/tests/Makefile.am
index 026dde3..050373a 100644
--- a/src/bin/auth/tests/Makefile.am
+++ b/src/bin/auth/tests/Makefile.am
@@ -18,7 +18,6 @@ CLEANFILES = *.gcno *.gcda
 TESTS =
 if HAVE_GTEST
 
-BUILT_SOURCES = ../spec_config.h
 TESTS += run_unittests
 run_unittests_SOURCES = $(top_srcdir)/src/lib/dns/tests/unittest_util.h
 run_unittests_SOURCES += $(top_srcdir)/src/lib/dns/tests/unittest_util.cc
@@ -28,7 +27,6 @@ run_unittests_SOURCES += ../change_user.h ../change_user.cc
 run_unittests_SOURCES += ../auth_config.h ../auth_config.cc
 run_unittests_SOURCES += ../command.h ../command.cc
 run_unittests_SOURCES += ../common.h ../common.cc
-run_unittests_SOURCES += ../spec_config.h
 run_unittests_SOURCES += ../statistics.h ../statistics.cc
 run_unittests_SOURCES += auth_srv_unittest.cc
 run_unittests_SOURCES += config_unittest.cc
diff --git a/src/bin/bind10/bind10.py.in b/src/bin/bind10/bind10.py.in
index e6504e1..648d085 100755
--- a/src/bin/bind10/bind10.py.in
+++ b/src/bin/bind10/bind10.py.in
@@ -546,6 +546,9 @@ class BoB:
     def start_stats(self, c_channel_env):
         self.start_simple("b10-stats", c_channel_env)
 
+    def start_stats_httpd(self, c_channel_env):
+        self.start_simple("b10-stats-httpd", c_channel_env)
+
     def start_cmdctl(self, c_channel_env):
         """
             Starts the command control process
@@ -595,6 +598,7 @@ class BoB:
 
         # ... and finally start the remaining processes
         self.start_stats(c_channel_env)
+        self.start_stats_httpd(c_channel_env)
         self.start_cmdctl(c_channel_env)
     
     def startup(self):
@@ -644,6 +648,7 @@ class BoB:
         self.cc_session.group_sendmsg(cmd, "Xfrin", "Xfrin")
         self.cc_session.group_sendmsg(cmd, "Zonemgr", "Zonemgr")
         self.cc_session.group_sendmsg(cmd, "Stats", "Stats")
+        self.cc_session.group_sendmsg(cmd, "StatsHttpd", "StatsHttpd")
 
     def stop_process(self, process, recipient):
         """
diff --git a/src/bin/bind10/run_bind10.sh.in b/src/bin/bind10/run_bind10.sh.in
old mode 100644
new mode 100755
index edc01fe..89301bd
--- a/src/bin/bind10/run_bind10.sh.in
+++ b/src/bin/bind10/run_bind10.sh.in
@@ -23,14 +23,14 @@ BIND10_PATH=@abs_top_builddir@/src/bin/bind10
 PATH=@abs_top_builddir@/src/bin/msgq:@abs_top_builddir@/src/bin/auth:@abs_top_builddir@/src/bin/resolver:@abs_top_builddir@/src/bin/cfgmgr:@abs_top_builddir@/src/bin/cmdctl:@abs_top_builddir@/src/bin/stats:@abs_top_builddir@/src/bin/xfrin:@abs_top_builddir@/src/bin/xfrout:@abs_top_builddir@/src/bin/zonemgr:$PATH
 export PATH
 
-PYTHONPATH=@abs_top_builddir@/src/lib/python:@abs_top_builddir@/src/lib/dns/python/.libs:@abs_top_builddir@/src/lib/xfr/.libs:@abs_top_builddir@/src/lib/log/.libs
+PYTHONPATH=@abs_top_builddir@/src/lib/python:@abs_top_builddir@/src/lib/dns/python/.libs:@abs_top_builddir@/src/lib/xfr/.libs:@abs_top_builddir@/src/lib/log/.libs:@abs_top_builddir@/src/lib/util/io/.libs
 export PYTHONPATH
 
 # If necessary (rare cases), explicitly specify paths to dynamic libraries
 # required by loadable python modules.
 SET_ENV_LIBRARY_PATH=@SET_ENV_LIBRARY_PATH@
 if test $SET_ENV_LIBRARY_PATH = yes; then
-	@ENV_LIBRARY_PATH@=@abs_top_builddir@/src/lib/dns/.libs:@abs_top_builddir@/src/lib/exceptions/.libs:$@ENV_LIBRARY_PATH@
+	@ENV_LIBRARY_PATH@=@abs_top_builddir@/src/lib/dns/.libs:@abs_top_builddir@/src/lib/cryptolink/.libs:@abs_top_builddir@/src/lib/util/.libs:@abs_top_builddir@/src/lib/util/io/.libs:@abs_top_builddir@/src/lib/exceptions/.libs:$@ENV_LIBRARY_PATH@
 	export @ENV_LIBRARY_PATH@
 fi
 
diff --git a/src/bin/bind10/tests/bind10_test.py.in b/src/bin/bind10/tests/bind10_test.py.in
index 8432c89..2ffe2b4 100644
--- a/src/bin/bind10/tests/bind10_test.py.in
+++ b/src/bin/bind10/tests/bind10_test.py.in
@@ -183,6 +183,7 @@ class MockBob(BoB):
         self.xfrin = False
         self.zonemgr = False
         self.stats = False
+        self.stats_httpd = False
         self.cmdctl = False
         self.c_channel_env = {}
         self.processes = { }
@@ -236,10 +237,15 @@ class MockBob(BoB):
         self.processes[10] = ProcessInfo('b10-stats', ['/bin/false'])
         self.processes[10].pid = 10
 
+    def start_stats_httpd(self, c_channel_env):
+        self.stats_httpd = True
+        self.processes[11] = ProcessInfo('b10-stats-httpd', ['/bin/false'])
+        self.processes[11].pid = 11
+
     def start_cmdctl(self, c_channel_env):
         self.cmdctl = True
-        self.processes[11] = ProcessInfo('b10-cmdctl', ['/bin/false'])
-        self.processes[11].pid = 11
+        self.processes[12] = ProcessInfo('b10-cmdctl', ['/bin/false'])
+        self.processes[12].pid = 12
 
     # We don't really use all of these stop_ methods. But it might turn out
     # someone would add some stop_ method to BoB and we want that one overriden
@@ -289,9 +295,14 @@ class MockBob(BoB):
             del self.processes[10]
         self.stats = False
 
+    def stop_stats_httpd(self):
+        if self.stats_httpd:
+            del self.processes[11]
+        self.stats_httpd = False
+
     def stop_cmdctl(self):
         if self.cmdctl:
-            del self.processes[11]
+            del self.processes[12]
         self.cmdctl = False
 
 class TestStartStopProcessesBob(unittest.TestCase):
@@ -316,6 +327,7 @@ class TestStartStopProcessesBob(unittest.TestCase):
         self.assertEqual(bob.xfrin, auth)
         self.assertEqual(bob.zonemgr, auth)
         self.assertEqual(bob.stats, core)
+        self.assertEqual(bob.stats_httpd, core)
         self.assertEqual(bob.cmdctl, core)
 
     def check_preconditions(self, bob):
@@ -544,7 +556,8 @@ class TestBossCmd(unittest.TestCase):
                      [8, 'b10-xfrin'], 
                      [9, 'b10-zonemgr'],
                      [10, 'b10-stats'], 
-                     [11, 'b10-cmdctl']]
+                     [11, 'b10-stats-httpd'], 
+                     [12, 'b10-cmdctl']]
         self.assertEqual(answer, {'result': [0, processes]})
 
 class TestParseArgs(unittest.TestCase):
diff --git a/src/bin/cfgmgr/b10-cfgmgr.py.in b/src/bin/cfgmgr/b10-cfgmgr.py.in
index 607a6dc..16c8f76 100755
--- a/src/bin/cfgmgr/b10-cfgmgr.py.in
+++ b/src/bin/cfgmgr/b10-cfgmgr.py.in
@@ -41,7 +41,7 @@ if "B10_FROM_SOURCE" in os.environ:
         DATA_PATH = os.environ["B10_FROM_SOURCE_LOCALSTATEDIR"]
     else:
         DATA_PATH = os.environ["B10_FROM_SOURCE"]
-    PLUGIN_PATH = [DATA_PATH + '/src/bin/cfgmgr/plugins']
+    PLUGIN_PATHS = [DATA_PATH + '/src/bin/cfgmgr/plugins']
 else:
     PREFIX = "@prefix@"
     DATA_PATH = "@localstatedir@/@PACKAGE@".replace("${prefix}", PREFIX)
diff --git a/src/bin/host/Makefile.am b/src/bin/host/Makefile.am
index 0758cb9..ec34ce7 100644
--- a/src/bin/host/Makefile.am
+++ b/src/bin/host/Makefile.am
@@ -10,17 +10,20 @@ endif
 
 CLEANFILES = *.gcno *.gcda
 
-bin_PROGRAMS = host
-host_SOURCES = host.cc
-host_LDADD = $(top_builddir)/src/lib/dns/libdns++.la
-host_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
-
-#man_MANS = host.1
-#EXTRA_DIST = $(man_MANS) host.xml
-#
-#if ENABLE_MAN
-#
-#host.1: host.xml
-#	xsltproc --novalid --xinclude --nonet -o $@ http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $(srcdir)/host.xml
-#
-#endif
+bin_PROGRAMS = b10-host
+b10_host_SOURCES = host.cc
+b10_host_LDADD = $(top_builddir)/src/lib/dns/libdns++.la
+b10_host_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
+
+man_MANS = b10-host.1
+EXTRA_DIST = $(man_MANS) b10-host.xml
+
+.PHONY: man
+if ENABLE_MAN
+
+man: b10-host.1
+
+b10-host.1: b10-host.xml
+	xsltproc --novalid --xinclude --nonet -o $@ http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $(srcdir)/b10-host.xml
+
+endif
diff --git a/src/bin/host/README b/src/bin/host/README
index d493a95..5cc4068 100644
--- a/src/bin/host/README
+++ b/src/bin/host/README
@@ -1,14 +1,4 @@
-Rewriting host(1) in C++ from scratch using BIND 10's libdns.
+Rewriting host(1) in C++ from scratch using BIND 10's libdns++.
 
-Initial functionality:
-
-  host _hostname_ [server]
-
-By default, it looks up the A, AAAA, and MX record sets.
-
-Note it doesn't use /etc/resolv.conf at this time.
-The default name server used is 127.0.0.1.
-
-  -r	 	disable recursive processing
-  -t _type_	specific query type 
-  -v		enable verbose output mode, including elapsed time
+The bugs and incompatibilities are listed in the manual page
+and in the source code.
diff --git a/src/bin/host/b10-host.1 b/src/bin/host/b10-host.1
new file mode 100644
index 0000000..ed0068b
--- /dev/null
+++ b/src/bin/host/b10-host.1
@@ -0,0 +1,122 @@
+'\" t
+.\"     Title: b10-host
+.\"    Author: [FIXME: author] [see http://docbook.sf.net/el/author]
+.\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
+.\"      Date: May 4, 2011
+.\"    Manual: BIND10
+.\"    Source: BIND10
+.\"  Language: English
+.\"
+.TH "B10\-HOST" "1" "May 4, 2011" "BIND10" "BIND10"
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+b10-host \- DNS lookup utility
+.SH "SYNOPSIS"
+.HP \w'\fBb10\-host\fR\ 'u
+\fBb10\-host\fR [\fB\-a\fR] [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-d\fR] [\fB\-p\ \fR\fB\fIport\fR\fR] [\fB\-r\fR] [\fB\-t\ \fR\fB\fItype\fR\fR] [\fB\-v\fR] [\fIname\fR] [\fB\fIserver\fR\fR]
+.SH "DESCRIPTION"
+.PP
+The
+\fBb10\-host\fR
+utility does DNS lookups\&. Its initial goal is to be a
+\fBhost\fR(1)
+clone, but also add a few features useful for BIND 10 development testing\&.
+.PP
+By default, it looks up the A, AAAA, and MX record sets for the
+\fIname\fR\&. Optionally, you may select a name server to query against by adding the
+\fIserver\fR
+argument\&.
+.SH "OPTIONS"
+.PP
+The arguments are as follows:
+.PP
+\fB\-a\fR
+.RS 4
+Enable verbose mode and do a query for type ANY\&. (If the
+\fB\-t\fR
+option is also set, then the ANY query is not done, but it still uses verbose mode\&.)
+.RE
+.PP
+\fB\-c \fR\fB\fIclass\fR\fR
+.RS 4
+Define the class for the query\&. The default is IN (Internet)\&.
+.RE
+.PP
+\fB\-d\fR
+.RS 4
+Enable verbose output mode, including elapsed time in milliseconds\&. Verbose mode shows the header, question, answer, authority, and additional sections (if provided)\&. (Same as
+\fB\-v\fR\&.)
+.RE
+.PP
+\fB\-p \fR\fB\fIport\fR\fR
+.RS 4
+Select an alternative port for the query\&. This may be a number or a service name\&. The default is 53 (domain)\&. This is not a standard feature of
+\fBhost\fR(1)\&.
+.RE
+.PP
+\fB\-r\fR
+.RS 4
+Disable recursive processing by not setting the Recursion Desired flag in the query\&.
+.RE
+.PP
+\fB\-t \fR\fB\fItype\fR\fR
+.RS 4
+Select a specific resource record type for the query\&. By default, it looks up the A, AAAA, and MX record sets\&.
+(This overrides the
+\fB\-a\fR
+option\&.)
+.RE
+.PP
+\fB\-v\fR
+.RS 4
+Same as
+\fB\-d\fR
+option\&.
+.RE
+.SH "COMPATIBILITY / BUGS"
+.PP
+
+\fBb10\-host\fR
+does not do reverse lookups by default yet (by detecting if name is a IPv4 or IPv6 address)\&.
+.PP
+Unknown
+\fB\-c\fR
+class or
+\fB\-t\fR
+type causes
+\fBb10\-host\fR
+to Abort\&.
+.PP
+Not all types are supported yet for formatting\&. Not all switches are supported yet\&.
+.PP
+It doesn\'t use
+/etc/resolv\&.conf
+at this time\&. The default name server used is 127\&.0\&.0\&.1\&.
+.PP
+
+\fBb10\-host\fR
+does not do reverse lookups by default yet (by detecting if name is a IPv4 or IPv6 address)\&.
+.PP
+
+\fB\-p\fR
+is not a standard feature\&.
+.SH "HISTORY"
+.PP
+The C++ version of
+\fBb10\-host\fR
+was started in October 2009 by Jeremy C\&. Reed of ISC\&. Its usage and output were based on the standard
+\fBhost\fR
+command\&.
+.SH "COPYRIGHT"
+.br
+Copyright \(co 2011 Internet Systems Consortium, Inc. ("ISC")
+.br
diff --git a/src/bin/host/b10-host.xml b/src/bin/host/b10-host.xml
new file mode 100644
index 0000000..7da07dd
--- /dev/null
+++ b/src/bin/host/b10-host.xml
@@ -0,0 +1,201 @@
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+               "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
+	       [<!ENTITY mdash "—">]>
+<!--
+ - Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+ -
+ - Permission to use, copy, modify, and/or distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ - REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ - AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ - INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ - LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ - PERFORMANCE OF THIS SOFTWARE.
+-->
+
+<!-- $Id$ -->
+<refentry>
+
+  <refentryinfo>
+    <date>May 4, 2011</date>
+  </refentryinfo>
+
+  <refmeta>
+    <refentrytitle>b10-host</refentrytitle>
+    <manvolnum>1</manvolnum>
+    <refmiscinfo>BIND10</refmiscinfo>
+  </refmeta>
+
+  <refnamediv>
+    <refname>b10-host</refname>
+    <refpurpose>DNS lookup utility</refpurpose>
+  </refnamediv>
+
+  <docinfo>
+    <copyright>
+      <year>2011</year>
+      <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+    </copyright>
+  </docinfo>
+
+  <refsynopsisdiv>
+    <cmdsynopsis>
+      <command>b10-host</command>
+      <arg><option>-a</option></arg>
+      <arg><option>-c <replaceable>class</replaceable></option></arg>
+      <arg><option>-d</option></arg>
+      <arg><option>-p <replaceable>port</replaceable></option></arg>
+      <arg><option>-r</option></arg>
+      <arg><option>-t <replaceable>type</replaceable></option></arg>
+      <arg><option>-v</option></arg>
+      <arg><replaceable>name</replaceable></arg>
+      <arg><option><replaceable>server</replaceable></option></arg>
+    </cmdsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>DESCRIPTION</title>
+    <para>
+      The <command>b10-host</command> utility does DNS lookups.
+      Its initial goal is to be a
+      <citerefentry><refentrytitle>host</refentrytitle>
+        <manvolnum>1</manvolnum></citerefentry>
+      clone, but also add a few features useful for BIND 10 development
+      testing.
+    </para>
+
+    <para>
+      By default, it looks up the A, AAAA, and MX record sets for the
+      <replaceable>name</replaceable>.
+      Optionally, you may select a name server to query against by adding
+      the <replaceable>server</replaceable> argument.
+    </para>
+  </refsect1>
+
+  <refsect1>
+    <title>OPTIONS</title>
+
+    <para>The arguments are as follows:</para>
+
+    <variablelist>
+
+      <varlistentry>
+        <term><option>-a</option></term>
+        <listitem><para>
+          Enable verbose mode and do a query for type ANY.
+          (If the <option>-t</option> option is also set, then the
+          ANY query is not done, but it still uses verbose mode.)
+        </para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><option>-c <replaceable>class</replaceable></option></term>
+        <listitem><para>
+          Define the class for the query.
+          The default is IN (Internet).
+<!-- TODO: bug if class is unknown causes seg fault and possible core dump -->
+        </para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><option>-d</option></term>
+        <listitem><para>
+	  Enable verbose output mode, including elapsed time in
+	  milliseconds.
+          Verbose mode shows the header, question, answer, authority,
+          and additional sections (if provided).
+          (Same as <option>-v</option>.)
+        </para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><option>-p <replaceable>port</replaceable></option></term>
+        <listitem><para>
+          Select an alternative port for the query.
+          This may be a number or a service name.
+          The default is 53 (domain).
+          This is not a standard feature of
+          <citerefentry><refentrytitle>host</refentrytitle>
+            <manvolnum>1</manvolnum></citerefentry>.
+        </para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><option>-r</option></term>
+        <listitem><para>
+          Disable recursive processing by not setting the
+          Recursion Desired flag in the query.
+        </para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><option>-t <replaceable>type</replaceable></option></term>
+        <listitem><para>
+          Select a specific resource record type for the query.
+          By default, it looks up the A, AAAA, and MX record sets.
+<!-- TODO: bug if class is unknown causes seg fault and possible core dump -->
+          (This overrides the <option>-a</option> option.)
+        </para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><option>-v</option></term>
+        <listitem><para>
+	  Same as <option>-d</option> option.
+        </para></listitem>
+      </varlistentry>
+
+    </variablelist>
+
+  </refsect1>
+
+  <refsect1>
+    <title>COMPATIBILITY / BUGS</title>
+    <para>
+      <command>b10-host</command> does not do reverse lookups by
+      default yet (by detecting if name is a IPv4 or IPv6 address).
+    </para>
+
+    <para>
+      Unknown <option>-c</option> class or <option>-t</option> type
+      causes <command>b10-host</command> to Abort.
+    </para>
+
+    <para>
+      Not all types are supported yet for formatting.
+      Not all switches are supported yet.
+    </para>
+
+    <para>
+      It doesn't use <filename>/etc/resolv.conf</filename> at this time.
+      The default name server used is 127.0.0.1.
+    </para>
+
+    <para>
+      <command>b10-host</command> does not do reverse lookups by
+      default yet (by detecting if name is a IPv4 or IPv6 address).
+    </para>
+
+    <para>
+      <option>-p</option> is not a standard feature.
+    </para>
+  </refsect1>
+
+  <refsect1>
+    <title>HISTORY</title>
+    <para>
+      The C++ version of <command>b10-host</command> was started in
+      October 2009 by Jeremy C. Reed of ISC.
+      Its usage and output were based on the standard <command>host</command>
+      command.
+    </para>
+  </refsect1>
+</refentry><!--
+ - Local variables:
+ - mode: sgml
+ - End:
+-->
diff --git a/src/bin/host/host.cc b/src/bin/host/host.cc
index 973509e..f0df0c8 100644
--- a/src/bin/host/host.cc
+++ b/src/bin/host/host.cc
@@ -1,4 +1,4 @@
-// Copyright (C) 2010  Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2010-2011  Internet Systems Consortium, Inc. ("ISC")
 //
 // Permission to use, copy, modify, and/or distribute this software for any
 // purpose with or without fee is hereby granted, provided that the above
@@ -44,13 +44,16 @@ namespace {
 char* dns_type = NULL;    // not set, so A, AAAA, MX
 const char* server = "127.0.0.1";
 const char* server_port = "53";
-int   verbose = 0;
-int   first_time = 1;
-bool  recursive_bit = true;
+const char* dns_class  = "IN";
+bool verbose = false;
+bool dns_any = false;
+int first_time = 1;
+bool recursive_bit = true;
 struct timeval before_time, after_time;
 
 int
-host_lookup(const char* const name, const char* const type) {
+host_lookup(const char* const name, const char* const dns_class,
+            const char* const type, bool any) {
 
     Message msg(Message::RENDER);
 
@@ -64,8 +67,8 @@ host_lookup(const char* const name, const char* const type) {
     }
 
     msg.addQuestion(Question(Name(name),
-                             RRClass::IN(),    // IN class only for now
-                             RRType(type)));  // if NULL then:
+                             RRClass(dns_class),
+                             any ? RRType::ANY() : RRType(type)));  // if NULL then:
 
     OutputBuffer obuffer(512);
     MessageRenderer renderer(obuffer);
@@ -127,18 +130,29 @@ host_lookup(const char* const name, const char* const type) {
 
             rmsg.fromWire(ibuffer);
             if (!verbose) {
+                string description = "";
                 for (RRsetIterator it =
                          rmsg.beginSection(Message::SECTION_ANSWER);
                      it != rmsg.endSection(Message::SECTION_ANSWER);
                      ++it) {
-                      if ((*it)->getType() != RRType::A()) {
-                          continue;
+
+                      if ((*it)->getType() == RRType::A()) {
+                          description = "has address";
+                      }
+                      else if ((*it)->getType() == RRType::AAAA()) {
+                          description = "has IPv6 address";
+                      }
+                      else if ((*it)->getType() == RRType::MX()) {
+                          description = "mail is handled by";
+                      }
+                      else if ((*it)->getType() == RRType::TXT()) {
+                          description = "descriptive text";
                       }
 
                       RdataIteratorPtr rit = (*it)->getRdataIterator();
                       for (; !rit->isLast(); rit->next()) {
                           // instead of using my name, maybe use returned label?
-                          cout << name << " has address " <<
+                          cout << name << " "  << description << " " <<
                               (*rit).getCurrent().toText() << endl;
                       }
                   }
@@ -159,13 +173,19 @@ host_lookup(const char* const name, const char* const type) {
 
                 // TODO: if NXDOMAIN, host(1) doesn't show HEADER
                 // Host hsdjkfhksjhdfkj not found: 3(NXDOMAIN)
-                // TODO: figure out the new libdns way to test if NXDOMAIN
+                // TODO: test if NXDOMAIN
 
                 std::cout << "Received " << cc <<
                     " bytes in " << elapsed_time << " ms\n";
                 // TODO: " bytes from 127.0.0.1#53 in 0 ms
 
             } //verbose
+/*
+TODO: handle InvalidRRClass
+TODO: handle invalid type exception
+        } catch (InvalidType ivt) {
+            std::cerr << "invalid type:" << ivt.what();
+*/
         } catch (const exception& ex) {
             std::cerr << "parse failed for " <<
                 string(name) << "/" << type << ": " << ex.what() << std::endl;
@@ -184,26 +204,36 @@ int
 main(int argc, char* argv[]) {
     int c;
 
-    while ((c = getopt(argc, argv, "p:rt:v")) != -1)
+    while ((c = getopt(argc, argv, "ac:dp:rt:v")) != -1)
         switch (c) {
+        case 'a':
+            dns_any = true;
+            verbose = true;
+            break;
+        case 'c':
+            dns_class = optarg;
+            break;
+	// p for port is a non-standard switch
+        case 'p':
+            server_port = optarg;
+            break;
         case 'r':
             recursive_bit = false;
             break;
         case 't':
             dns_type = optarg;
             break;
-        case 'p':
-            server_port = optarg;
-            break;
+        case 'd':
+            // drop through to v, because debug and verbose are equivalent
         case 'v':
-            verbose = 1;
+            verbose = true;
             break;
     }
     argc -= optind;
     argv += optind;
 
     if (argc < 1) {
-        cout << "Usage: host [-vr] [-t type] hostname [server]\n";
+        cout << "Usage: host [-adprv] [-c class] [-t type] hostname [server]\n";
         exit(1);
     }
 
@@ -212,12 +242,13 @@ main(int argc, char* argv[]) {
     }
 
     if (dns_type == NULL) {
-        host_lookup(argv[0], "A");
+        host_lookup(argv[0], dns_class, "A", dns_any);
         // TODO: don't do next if A doesn't exist
-        host_lookup(argv[0], "AAAA");
-        host_lookup(argv[0], "MX");
+        host_lookup(argv[0], dns_class, "AAAA", dns_any);
+        host_lookup(argv[0], dns_class, "MX", dns_any);
     } else {
-        host_lookup(argv[0], dns_type); 
+        // -t overrides -a, regardless of order
+        host_lookup(argv[0], dns_class, dns_type, false);
     }
     return (0);
 }
diff --git a/src/bin/msgq/tests/msgq_test.py b/src/bin/msgq/tests/msgq_test.py
index f926845..26878f7 100644
--- a/src/bin/msgq/tests/msgq_test.py
+++ b/src/bin/msgq/tests/msgq_test.py
@@ -132,7 +132,7 @@ class SendNonblock(unittest.TestCase):
             task()
             # If we got here, then everything worked well and in time
             # In that case, we terminate successfully
-            sys.exit(0)	# needs exit code
+            os._exit(0)	# needs exit code
         else:
             (pid, status) = os.waitpid(task_pid, 0)
             self.assertEqual(0, status,
diff --git a/src/bin/resolver/response_scrubber.cc b/src/bin/resolver/response_scrubber.cc
index 93bd808..d35a96f 100644
--- a/src/bin/resolver/response_scrubber.cc
+++ b/src/bin/resolver/response_scrubber.cc
@@ -1,4 +1,3 @@
-
 // Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
 //
 // Permission to use, copy, modify, and/or distribute this software for any
@@ -50,7 +49,7 @@ ResponseScrubber::Category ResponseScrubber::addressCheck(
 unsigned int
 ResponseScrubber::scrubSection(Message& message,
     const vector<const Name*>& names,
-    const NameComparisonResult::NameRelation connection, 
+    const NameComparisonResult::NameRelation connection,
     const Message::Section section)
 {
     unsigned int count = 0;     // Count of RRsets removed
@@ -74,30 +73,32 @@ ResponseScrubber::scrubSection(Message& message,
 
         // Start looking at the remaining entries in the section.
         removed = false;
-        for (; (i != message.endSection(section)) && (!removed); ++i) {
+        for (; i != message.endSection(section); ++i) {
 
             // Loop through the list of names given and see if any are in the
             // given relationship with the QNAME of this RRset
-            bool nomatch = true;
+            bool match = false;
             for (vector<const Name*>::const_iterator n = names.begin();
-                ((n != names.end()) && nomatch); ++n) {
+                 n != names.end(); ++n) {
                 NameComparisonResult result = (*i)->getName().compare(**n);
                 NameComparisonResult::NameRelation relationship =
                     result.getRelation();
                 if ((relationship == NameComparisonResult::EQUAL) ||
                    (relationship == connection)) {
-                    
+
                     // RRset in the specified relationship, so a match has
                     // been found
-                    nomatch = false;
+                    match = true;
+                    break;
                 }
             }
 
             // Remove the RRset if there was no match to one of the given names.
-            if (nomatch) {
+            if (!match) {
                 message.removeRRset(section, i);
                 ++count;            // One more RRset removed
                 removed = true;     // Something was removed
+                break; // It invalidated the iterators, start again
              } else {
 
                 // There was a match so this is one more entry we can skip next
@@ -107,7 +108,7 @@ ResponseScrubber::scrubSection(Message& message,
         }
     }
 
-    return count;
+    return (count);
 }
 
 // Perform the scrubbing of all sections of the message.
@@ -126,7 +127,7 @@ ResponseScrubber::scrubAllSections(Message& message, const Name& bailiwick) {
     count += scrubSection(message, bailiwick_names,
             NameComparisonResult::SUBDOMAIN, Message::SECTION_ADDITIONAL);
 
-    return count;
+    return (count);
 }
 
 // Scrub across sections.
@@ -171,7 +172,6 @@ ResponseScrubber::scrubCrossSections(isc::dns::Message& message) {
     // superdomain of the names in the question/answer section.
     return (scrubSection(message, source,
         NameComparisonResult::SUPERDOMAIN, Message::SECTION_AUTHORITY));
-
 }
 
 // Scrub a message
@@ -183,7 +183,7 @@ ResponseScrubber::scrub(const isc::dns::MessagePtr& message,
     unsigned int sections_removed = scrubAllSections(*message, bailiwick);
     sections_removed += scrubCrossSections(*message);
 
-    return sections_removed;
+    return (sections_removed);
 }
 
 
diff --git a/src/bin/stats/Makefile.am b/src/bin/stats/Makefile.am
index b173813..485bc05 100644
--- a/src/bin/stats/Makefile.am
+++ b/src/bin/stats/Makefile.am
@@ -2,35 +2,36 @@ SUBDIRS = tests
 
 pkglibexecdir = $(libexecdir)/@PACKAGE@
 
-pkglibexec_SCRIPTS = b10-stats
-noinst_SCRIPTS = b10-stats_stub
+pkglibexec_SCRIPTS = b10-stats b10-stats-httpd
 
 b10_statsdir = $(pkgdatadir)
-b10_stats_DATA = stats.spec
+b10_stats_DATA = stats.spec stats-httpd.spec
+b10_stats_DATA += stats-httpd-xml.tpl stats-httpd-xsd.tpl stats-httpd-xsl.tpl
 
-CLEANFILES = stats.spec b10-stats stats.pyc stats.pyo b10-stats_stub stats_stub.pyc stats_stub.pyo
+CLEANFILES = b10-stats stats.pyc
+CLEANFILES += b10-stats-httpd stats_httpd.pyc
 
-man_MANS = b10-stats.8
-EXTRA_DIST = $(man_MANS) b10-stats.xml
+man_MANS = b10-stats.8 b10-stats-httpd.8
+EXTRA_DIST = $(man_MANS) b10-stats.xml b10-stats-httpd.xml
+EXTRA_DIST += stats.spec stats-httpd.spec
+EXTRA_DIST += stats-httpd-xml.tpl stats-httpd-xsd.tpl stats-httpd-xsl.tpl
 
 if ENABLE_MAN
 
 b10-stats.8: b10-stats.xml
 	xsltproc --novalid --xinclude --nonet -o $@ http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $(srcdir)/b10-stats.xml
 
-endif
+b10-stats-httpd.8: b10-stats-httpd.xml
+	xsltproc --novalid --xinclude --nonet -o $@ http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $(srcdir)/b10-stats-httpd.xml
 
-stats.spec: stats.spec.pre
-	$(SED) -e "s|@@LOCALSTATEDIR@@|$(localstatedir)|" stats.spec.pre >$@
+endif
 
 # this is done here since configure.ac AC_OUTPUT doesn't expand exec_prefix
 b10-stats: stats.py
 	$(SED) -e "s|@@PYTHONPATH@@|@pyexecdir@|" \
-	       -e "s|@@LOCALSTATEDIR@@|$(localstatedir)|" \
 	       -e "s|.*#@@REMOVED@@$$||"  stats.py >$@
 	chmod a+x $@
 
-b10-stats_stub: stats_stub.py stats.py
-	$(SED) -e "s|@@PYTHONPATH@@|@pyexecdir@|" \
-	       -e "s|@@LOCALSTATEDIR@@|$(localstatedir)|" stats_stub.py >$@
+b10-stats-httpd: stats_httpd.py
+	$(SED) -e "s|@@PYTHONPATH@@|@pyexecdir@|" stats_httpd.py >$@
 	chmod a+x $@
diff --git a/src/bin/stats/b10-stats-httpd.8 b/src/bin/stats/b10-stats-httpd.8
new file mode 100644
index 0000000..c066f91
--- /dev/null
+++ b/src/bin/stats/b10-stats-httpd.8
@@ -0,0 +1,132 @@
+'\" t
+.\"     Title: b10-stats-httpd
+.\"    Author: [FIXME: author] [see http://docbook.sf.net/el/author]
+.\" Generator: DocBook XSL Stylesheets v1.76.1 <http://docbook.sf.net/>
+.\"      Date: Mar 8, 2011
+.\"    Manual: BIND10
+.\"    Source: BIND10
+.\"  Language: English
+.\"
+.TH "B10\-STATS\-HTTPD" "8" "Mar 8, 2011" "BIND10" "BIND10"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el       .ds Aq '
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+b10-stats-httpd \- BIND 10 HTTP server for HTTP/XML interface of statistics
+.SH "SYNOPSIS"
+.HP \w'\fBb10\-stats\-httpd\fR\ 'u
+\fBb10\-stats\-httpd\fR [\fB\-v\fR]| [\fB\-\-verbose\fR]
+.SH "DESCRIPTION"
+.PP
+
+\fBb10\-stats\-httpd\fR
+is a standalone HTTP server\&. It is intended for HTTP/XML interface for statistics module\&. This server process runs as a process separated from the process of the BIND 10 Stats daemon (\fBb10\-stats\fR)\&. The server is initially executed by the BIND 10 boss process (\fBbind10\fR) and eventually exited by it\&. The server is intended to be server requests by HTTP clients like web browsers and third\-party modules\&. When the server is asked, it requests BIND 10 statistics data from
+\fBb10\-stats\fR, and it sends the data back in Python dictionary format and the server converts it into XML format\&. The server sends it to the HTTP client\&. The server can send three types of document, which are XML (Extensible Markup Language), XSD (XML Schema definition) and XSL (Extensible Stylesheet Language)\&. The XML document is the statistics data of BIND 10, The XSD document is the data schema of it, and The XSL document is the style sheet to be showed for the web browsers\&. There is different URL for each document\&. But please note that you would be redirected to the URL of XML document if you request the URL of the root document\&. For example, you would be redirected to http://127\&.0\&.0\&.1:8000/bind10/statistics/xml if you request http://127\&.0\&.0\&.1:8000/\&. Please see the manual and the spec file of
+\fBb10\-stats\fR
+for more details about the items of BIND 10 statistics\&. The server uses CC session in communication with
+\fBb10\-stats\fR\&. CC session is provided by
+\fBb10\-msgq\fR
+which is started by
+\fBbind10\fR
+in advance\&. The server is implemented by HTTP\-server libraries included in Python 3\&. The server obtains the configuration from the config manager (\fBb10\-cfgmgr\fR) in runtime\&. Please see below for more details about this spec file and configuration of the server\&.
+.SH "OPTIONS"
+.PP
+The argument is as follow:
+.PP
+\fB\-v\fR, \fB\-\-verbose\fR
+.RS 4
+
+\fBb10\-stats\-httpd\fR
+switches to verbose mode and sends verbose messages to STDOUT\&.
+.RE
+.SH "FILES"
+.PP
+
+/usr/local/share/bind10\-devel/stats\-httpd\&.spec
+\(em the spec file of
+\fBb10\-stats\-httpd\fR\&. This file contains configurable settings of
+\fBb10\-stats\-httpd\fR\&. This setting can be configured in runtime via
+bindctl(1)\&. Please see the manual of
+bindctl(1)
+about how to configure the settings\&.
+.PP
+
+/usr/local/share/bind10\-devel/stats\-httpd\-xml\&.tpl
+\(em the template file of XML document\&.
+.PP
+
+/usr/local/share/bind10\-devel/stats\-httpd\-xsd\&.tpl
+\(em the template file of XSD document\&.
+.PP
+
+/usr/local/share/bind10\-devel/stats\-httpd\-xsl\&.tpl
+\(em the template file of XSL document\&.
+.SH "CONFIGURATION AND COMMANDS"
+.PP
+The configurable setting in
+stats\-httpd\&.spec
+is:
+.PP
+\fIlisten_on\fR
+.RS 4
+a list of pairs of address and port for
+\fBb10\-stats\-httpd\fR
+to listen HTTP requests on\&. The pair consists of the
+\fIaddress\fR
+string and
+\fIport\fR
+number\&. The default setting is the list of address 127\&.0\&.0\&.1 port 8000\&. If the server is started by the default setting being left, for example, the URL for XML document is http://127\&.0\&.0\&.1:8000/bind10/statistics/xml\&. And also IPv6 addresses can be configured and they works in the runtime environment for dual stack\&. You can change the settings through
+bindctl(8)\&.
+.RE
+.PP
+The commands in
+stats\-httpd\&.spec
+are:
+.PP
+\fBstatus\fR
+.RS 4
+shows the status of
+\fBb10\-stats\-httpd\fR
+with its PID\&.
+.RE
+.PP
+\fBshutdown\fR
+.RS 4
+exits the
+\fBb10\-stats\-httpd\fR
+process\&. (Note that the BIND 10 boss process will restart this service\&.)
+.RE
+.SH "SEE ALSO"
+.PP
+
+\fBb10-stats\fR(8),
+\fBb10-msgq\fR(8),
+\fBb10-cfgmgr\fR(8),
+\fBbind10\fR(8),
+\fBbindctl\fR(1),
+BIND 10 Guide\&.
+.SH "HISTORY"
+.PP
+
+\fBb10\-stats\-httpd\fR
+was designed and implemented by Naoki Kambe of JPRS in Mar 2011\&.
+.SH "COPYRIGHT"
+.br
+Copyright \(co 2011 Internet Systems Consortium, Inc. ("ISC")
+.br
diff --git a/src/bin/stats/b10-stats-httpd.xml b/src/bin/stats/b10-stats-httpd.xml
new file mode 100644
index 0000000..5cf3b4b
--- /dev/null
+++ b/src/bin/stats/b10-stats-httpd.xml
@@ -0,0 +1,215 @@
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+               "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
+	       [<!ENTITY mdash "—">]>
+<!--
+ - Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+ -
+ - Permission to use, copy, modify, and/or distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ - REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ - AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ - INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ - LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ - PERFORMANCE OF THIS SOFTWARE.
+-->
+
+<refentry>
+
+  <refentryinfo>
+    <date>Mar 8, 2011</date>
+  </refentryinfo>
+
+  <refmeta>
+    <refentrytitle>b10-stats-httpd</refentrytitle>
+    <manvolnum>8</manvolnum>
+    <refmiscinfo>BIND10</refmiscinfo>
+  </refmeta>
+
+  <refnamediv>
+    <refname>b10-stats-httpd</refname>
+    <refpurpose>BIND 10 HTTP server for HTTP/XML interface of statistics</refpurpose>
+  </refnamediv>
+
+  <docinfo>
+    <copyright>
+      <year>2011</year>
+      <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+    </copyright>
+  </docinfo>
+
+  <refsynopsisdiv>
+    <cmdsynopsis>      <command>b10-stats-httpd</command>
+      <arg><option>-v</option></arg>|<arg><option>--verbose</option></arg>
+    </cmdsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>DESCRIPTION</title>
+    <para>
+      <command>b10-stats-httpd</command> is a standalone HTTP server. It is
+      intended for HTTP/XML interface for statistics module. This server
+      process runs as a process separated from the process of the BIND 10 Stats
+      daemon (<command>b10-stats</command>). The server is initially executed
+      by the BIND 10 boss process (<command>bind10</command>) and eventually
+      exited by it.  The server is intended to be server requests by HTTP
+      clients like web browsers and third-party modules. When the server is
+      asked, it requests BIND 10 statistics data from
+      <command>b10-stats</command>, and it sends the data back in Python
+      dictionary format and the server converts it into XML format. The server
+      sends it to the HTTP client. The server can send three types of document,
+      which are XML (Extensible Markup Language), XSD (XML Schema definition)
+      and XSL (Extensible Stylesheet Language). The XML document is the
+      statistics data of BIND 10, The XSD document is the data schema of it,
+      and The XSL document is the style sheet to be showed for the web
+      browsers. There is different URL for each document. But please note that
+      you would be redirected to the URL of XML document if you request the URL
+      of the root document. For example, you would be redirected to
+      http://127.0.0.1:8000/bind10/statistics/xml if you request
+      http://127.0.0.1:8000/. Please see the manual and the spec file
+      of <command>b10-stats</command> for more details about the items of BIND
+      10 statistics. The server uses CC session in communication
+      with <command>b10-stats</command>. CC session is provided
+      by <command>b10-msgq</command> which is started
+      by <command>bind10</command> in advance. The server is implemented by
+      HTTP-server libraries included in Python 3. The server obtains the
+      configuration from the config manager (<command>b10-cfgmgr</command>) in
+      runtime. Please see below for more details about this spec file and
+      configuration of the server.
+    </para>
+  </refsect1>
+
+  <refsect1>
+    <title>OPTIONS</title>
+    <para>The argument is as follow:</para>
+    <variablelist>
+      <varlistentry>
+        <term><option>-v</option>, <option>--verbose</option></term>
+        <listitem>
+	  <para>
+          <command>b10-stats-httpd</command> switches to verbose mode and sends
+          verbose messages to STDOUT.
+	  </para>
+        </listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+
+  <refsect1>
+    <title>FILES</title>
+    <para>
+      <filename>/usr/local/share/bind10-devel/stats-httpd.spec</filename>
+      <!--TODO: The filename should be computed from prefix-->
+      — the spec file of <command>b10-stats-httpd</command>. This file
+      contains configurable settings
+      of <command>b10-stats-httpd</command>. This setting can be configured in
+      runtime via
+      <refentrytitle>bindctl</refentrytitle><manvolnum>1</manvolnum>. Please
+      see the manual
+      of <refentrytitle>bindctl</refentrytitle><manvolnum>1</manvolnum> about
+      how to configure the settings.
+    </para>
+    <para>
+      <filename>/usr/local/share/bind10-devel/stats-httpd-xml.tpl</filename>
+      <!--TODO: The filename should be computed from prefix-->
+      — the template file of XML document.
+    </para>
+    <para>
+      <filename>/usr/local/share/bind10-devel/stats-httpd-xsd.tpl</filename>
+      <!--TODO: The filename should be computed from prefix-->
+      — the template file of XSD document.
+    </para>
+    <para>
+      <filename>/usr/local/share/bind10-devel/stats-httpd-xsl.tpl</filename>
+      <!--TODO: The filename should be computed from prefix-->
+      — the template file of XSL document.
+    </para>
+  </refsect1>
+
+  <refsect1>
+    <title>CONFIGURATION AND COMMANDS</title>
+    <para>
+      The configurable setting in 
+      <filename>stats-httpd.spec</filename> is:
+    </para>
+    <variablelist>
+      <varlistentry>
+        <term><varname>listen_on</varname></term>
+        <listitem>
+	  <para>
+      	    a list of pairs of address and port for
+	    <command>b10-stats-httpd</command> to listen HTTP requests on. The
+	    pair consists of the <varname>address</varname> string
+	    and <varname>port</varname> number. The default setting is the list
+	    of address 127.0.0.1 port 8000. If the server is started by the
+	    default setting being left, for example, the URL for XML document
+	    is http://127.0.0.1:8000/bind10/statistics/xml. And also IPv6
+	    addresses can be configured and they works in the runtime
+	    environment for dual stack. You can change the settings
+	    through <refentrytitle>bindctl</refentrytitle><manvolnum>8</manvolnum>.
+	  </para>
+        </listitem>
+      </varlistentry>
+    </variablelist>
+    <para>
+      The commands in <filename>stats-httpd.spec</filename> are:
+    </para>
+    <variablelist>
+      <varlistentry>
+        <term><command>status</command></term>
+        <listitem>
+	  <para>
+	    shows the status of <command>b10-stats-httpd</command> with its
+	    PID.
+	  </para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><command>shutdown</command></term>
+        <listitem>
+	  <para>
+	    exits the <command>b10-stats-httpd</command> process. (Note that
+	    the BIND 10 boss process will restart this service.)
+	  </para>
+        </listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+
+  <refsect1>
+    <title>SEE ALSO</title>
+    <para>
+      <citerefentry>
+        <refentrytitle>b10-stats</refentrytitle><manvolnum>8</manvolnum>
+      </citerefentry>,
+      <citerefentry>
+        <refentrytitle>b10-msgq</refentrytitle><manvolnum>8</manvolnum>
+      </citerefentry>,
+      <citerefentry>
+        <refentrytitle>b10-cfgmgr</refentrytitle><manvolnum>8</manvolnum>
+      </citerefentry>,
+      <citerefentry>
+        <refentrytitle>bind10</refentrytitle><manvolnum>8</manvolnum>
+      </citerefentry>,
+      <citerefentry>
+	<refentrytitle>bindctl</refentrytitle><manvolnum>1</manvolnum>
+      </citerefentry>,
+      <citetitle>BIND 10 Guide</citetitle>.
+    </para>
+  </refsect1>
+
+  <refsect1>
+    <title>HISTORY</title>
+    <para>
+      <command>b10-stats-httpd</command> was designed and implemented by Naoki
+      Kambe of JPRS in Mar 2011.
+    </para>
+  </refsect1>
+</refentry><!--
+ - Local variables:
+ - mode: sgml
+ - End:
+-->
diff --git a/src/bin/stats/run_b10-stats.sh.in b/src/bin/stats/run_b10-stats.sh.in
deleted file mode 100644
index 65b9737..0000000
--- a/src/bin/stats/run_b10-stats.sh.in
+++ /dev/null
@@ -1,33 +0,0 @@
-#! /bin/sh
-
-# Copyright (C) 2010  Internet Systems Consortium.
-#
-# Permission to use, copy, modify, and distribute this software for any
-# purpose with or without fee is hereby granted, provided that the above
-# copyright notice and this permission notice appear in all copies.
-#
-# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SYSTEMS CONSORTIUM
-# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
-# INTERNET SYSTEMS CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
-# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
-# FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
-# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
-# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-PYTHON_EXEC=${PYTHON_EXEC:- at PYTHON@}
-export PYTHON_EXEC
-
-PYTHONPATH=@abs_top_builddir@/src/lib/python
-export PYTHONPATH
-
-BIND10_MSGQ_SOCKET_FILE=@abs_top_builddir@/msgq_socket
-export BIND10_MSGQ_SOCKET_FILE
-
-B10_FROM_BUILD=@abs_top_builddir@
-export B10_FROM_BUILD
-
-STATS_PATH=@abs_top_builddir@/src/bin/stats
-
-cd ${STATS_PATH}
-exec ${PYTHON_EXEC} -O b10-stats "$@"
diff --git a/src/bin/stats/run_b10-stats_stub.sh.in b/src/bin/stats/run_b10-stats_stub.sh.in
deleted file mode 100644
index 19ade5c..0000000
--- a/src/bin/stats/run_b10-stats_stub.sh.in
+++ /dev/null
@@ -1,33 +0,0 @@
-#! /bin/sh
-
-# Copyright (C) 2010  Internet Systems Consortium.
-#
-# Permission to use, copy, modify, and distribute this software for any
-# purpose with or without fee is hereby granted, provided that the above
-# copyright notice and this permission notice appear in all copies.
-#
-# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SYSTEMS CONSORTIUM
-# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
-# INTERNET SYSTEMS CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
-# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
-# FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
-# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
-# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-PYTHON_EXEC=${PYTHON_EXEC:- at PYTHON@}
-export PYTHON_EXEC
-
-PYTHONPATH=@abs_top_builddir@/src/lib/python
-export PYTHONPATH
-
-B10_FROM_BUILD=@abs_top_srcdir@
-export B10_FROM_BUILD
-
-BIND10_MSGQ_SOCKET_FILE=@abs_top_builddir@/msgq_socket
-export BIND10_MSGQ_SOCKET_FILE
-
-STATS_PATH=@abs_top_builddir@/src/bin/stats
-
-cd ${STATS_PATH}
-exec ${PYTHON_EXEC} -O b10-stats_stub "$@"
diff --git a/src/bin/stats/stats-httpd-xml.tpl.in b/src/bin/stats/stats-httpd-xml.tpl.in
new file mode 100644
index 0000000..d5846ad
--- /dev/null
+++ b/src/bin/stats/stats-httpd-xml.tpl.in
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?xml-stylesheet type="text/xsl" href="$xsl_url_path"?>
+<!--
+ - Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+ -
+ - Permission to use, copy, modify, and/or distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ - REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ - AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ - INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ - LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ - PERFORMANCE OF THIS SOFTWARE.
+-->
+
+<stats:stats_data version="1.0"
+  xmlns:stats="$xsd_namespace"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="$xsd_namespace $xsd_url_path">
+  $xml_string
+</stats:stats_data>
diff --git a/src/bin/stats/stats-httpd-xsd.tpl.in b/src/bin/stats/stats-httpd-xsd.tpl.in
new file mode 100644
index 0000000..6ad1280
--- /dev/null
+++ b/src/bin/stats/stats-httpd-xsd.tpl.in
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ - Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+ -
+ - Permission to use, copy, modify, and/or distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ - REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ - AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ - INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ - LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ - PERFORMANCE OF THIS SOFTWARE.
+-->
+
+<schema targetNamespace="$xsd_namespace"
+  xmlns="http://www.w3.org/2001/XMLSchema"
+  xmlns:stats="$xsd_namespace">
+  <annotation>
+    <documentation xml:lang="en">XML schema of the statistics
+      data in BIND 10</documentation>
+  </annotation>
+  <element name="stats_data">
+    <annotation>
+      <documentation>A set of statistics data</documentation>
+    </annotation>
+    <complexType>
+      $xsd_string
+      <attribute name="version" type="token" use="optional" default="1.0">
+        <annotation>
+          <documentation>Version number of syntax</documentation>
+        </annotation>
+      </attribute>
+    </complexType>
+  </element>
+</schema>
diff --git a/src/bin/stats/stats-httpd-xsl.tpl.in b/src/bin/stats/stats-httpd-xsl.tpl.in
new file mode 100644
index 0000000..01ffdc6
--- /dev/null
+++ b/src/bin/stats/stats-httpd-xsl.tpl.in
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ - Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+ -
+ - Permission to use, copy, modify, and/or distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ - REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ - AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ - INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ - LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ - PERFORMANCE OF THIS SOFTWARE.
+-->
+
+<xsl:stylesheet version="1.0"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml"
+  xmlns:stats="$xsd_namespace">
+  <xsl:output method="html" encoding="UTF-8"
+    doctype-public="-//W3C//DTD HTML 4.01 Transitional//EN"
+    doctype-system=" http://www.w3.org/TR/html4/loose.dtd " />
+  <xsl:template match="/">
+    <html lang="en">
+      <head>
+        <title>BIND 10 Statistics</title>
+        <style type="text/css"><![CDATA[
+table {
+  border: 1px #000000 solid;
+  border-collapse: collapse;
+}
+td, th {
+  padding: 3px 20px;
+  border: 1px #000000 solid;
+}
+td.title {
+  text-decoration:underline;
+}
+]]>
+        </style>
+      </head>
+      <body>
+        <h1>BIND 10 Statistics</h1>
+        <table>
+          <tr>
+            <th>Title</th>
+            <th>Value</th>
+          </tr>
+          <xsl:apply-templates />
+        </table>
+      </body>
+    </html>
+  </xsl:template>
+  $xsl_string
+</xsl:stylesheet>
diff --git a/src/bin/stats/stats-httpd.spec.in b/src/bin/stats/stats-httpd.spec.in
new file mode 100644
index 0000000..6307135
--- /dev/null
+++ b/src/bin/stats/stats-httpd.spec.in
@@ -0,0 +1,54 @@
+{
+  "module_spec": {
+    "module_name": "StatsHttpd",
+    "module_description": "Stats HTTP daemon",
+    "config_data": [
+      {
+        "item_name": "listen_on",
+        "item_type": "list",
+        "item_optional": false,
+        "item_default": [
+          {
+            "address": "127.0.0.1",
+            "port": 8000
+          }
+        ],
+        "list_item_spec": {
+          "item_name": "address",
+          "item_type": "map",
+          "item_optional": false,
+          "item_default": {},
+          "map_item_spec": [
+            {
+              "item_name": "address",
+              "item_type": "string",
+              "item_optional": true,
+              "item_default": "127.0.0.1",
+              "item_description": "listen-on address for HTTP"
+            },
+            {
+              "item_name": "port",
+              "item_type": "integer",
+              "item_optional": true,
+              "item_default": 8000,
+              "item_description": "listen-on port for HTTP"
+            }
+          ]
+        },
+        "item_description": "http listen-on address and port"
+      }
+    ],
+    "commands": [
+      {
+        "command_name": "status",
+        "command_description": "Status of the stats httpd",
+        "command_args": []
+      },
+      {
+        "command_name": "shutdown",
+        "command_description": "Shut down the stats httpd",
+        "command_args": []
+      }
+    ]
+  }
+}
diff --git a/src/bin/stats/stats.py.in b/src/bin/stats/stats.py.in
old mode 100755
new mode 100644
index eeddd92..821a719
--- a/src/bin/stats/stats.py.in
+++ b/src/bin/stats/stats.py.in
@@ -35,15 +35,17 @@ if __name__ == 'stats':					#@@REMOVED@@
 import isc.util.process
 isc.util.process.rename()
 
-# If B10_FROM_BUILD is set in the environment, we use data files
+# If B10_FROM_SOURCE is set in the environment, we use data files
 # from a directory relative to that, otherwise we use the ones
 # installed on the system
-if "B10_FROM_BUILD" in os.environ:
-    SPECFILE_LOCATION = os.environ["B10_FROM_BUILD"] + "/src/bin/stats/stats.spec"
+if "B10_FROM_SOURCE" in os.environ:
+    SPECFILE_LOCATION = os.environ["B10_FROM_SOURCE"] + os.sep + \
+        "src" + os.sep + "bin" + os.sep + "stats" + os.sep + "stats.spec"
 else:
     PREFIX = "@prefix@"
     DATAROOTDIR = "@datarootdir@"
-    SPECFILE_LOCATION = "@datadir@/@PACKAGE@/stats.spec".replace("${datarootdir}", DATAROOTDIR).replace("${prefix}", PREFIX)
+    SPECFILE_LOCATION = "@datadir@" + os.sep + "@PACKAGE@" + os.sep + "stats.spec"
+    SPECFILE_LOCATION = SPECFILE_LOCATION.replace("${datarootdir}", DATAROOTDIR).replace("${prefix}", PREFIX)
 
 class Singleton(type):
     """
@@ -274,9 +276,6 @@ class CCSessionListener(Listener):
         """
         handle set command
         """
-        if self.verbose:
-            sys.stdout.write("[b10-stats] 'set' command received, args: "+str(args)+"\n")
-
         # 'args' must be dictionary type
         self.stats_data.update(args['stats_data'])
 
diff --git a/src/bin/stats/stats.spec.in b/src/bin/stats/stats.spec.in
new file mode 100644
index 0000000..4d42ebf
--- /dev/null
+++ b/src/bin/stats/stats.spec.in
@@ -0,0 +1,140 @@
+{
+  "module_spec": {
+    "module_name": "Stats",
+    "module_description": "Stats daemon",
+    "config_data": [
+      {
+        "item_name": "report_time",
+        "item_type": "string",
+        "item_optional": false,
+        "item_default": "1970-01-01T00:00:00Z",
+        "item_title": "Report time",
+        "item_description": "A date time when stats module reports",
+        "item_format": "date-time"
+      },
+      {
+        "item_name": "bind10.boot_time",
+        "item_type": "string",
+        "item_optional": false,
+        "item_default": "1970-01-01T00:00:00Z",
+        "item_title": "bind10.BootTime",
+        "item_description": "A date time when bind10 process starts initially",
+        "item_format": "date-time"
+      },
+      {
+        "item_name": "stats.boot_time",
+        "item_type": "string",
+        "item_optional": false,
+        "item_default": "1970-01-01T00:00:00Z",
+        "item_title": "stats.BootTime",
+        "item_description": "A date time when the stats module starts initially or when the stats module restarts",
+        "item_format": "date-time"
+      },
+      {
+        "item_name": "stats.start_time",
+        "item_type": "string",
+        "item_optional": false,
+        "item_default": "1970-01-01T00:00:00Z",
+        "item_title": "stats.StartTime",
+        "item_description": "A date time when the stats module starts collecting data or resetting values last time",
+        "item_format": "date-time"
+      },
+      {
+        "item_name": "stats.last_update_time",
+        "item_type": "string",
+        "item_optional": false,
+        "item_default": "1970-01-01T00:00:00Z",
+        "item_title": "stats.LastUpdateTime",
+        "item_description": "The latest date time when the stats module receives from other modules like auth server or boss process and so on",
+        "item_format": "date-time"
+      },
+      {
+        "item_name": "stats.timestamp",
+        "item_type": "real",
+        "item_optional": false,
+        "item_default": 0.0,
+        "item_title": "stats.Timestamp",
+        "item_description": "A current time stamp since epoch time (1970-01-01T00:00:00Z)",
+        "item_format": "second"
+      },
+      {
+        "item_name": "stats.lname",
+        "item_type": "string",
+        "item_optional": false,
+        "item_default": "",
+        "item_title": "stats.LocalName",
+        "item_description": "A localname of stats module given via CC protocol"
+      },
+      {
+        "item_name": "auth.queries.tcp",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "auth.queries.tcp",
+        "item_description": "A number of total query counts which all auth servers receive over TCP since they started initially"
+      },
+      {
+        "item_name": "auth.queries.udp",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "auth.queries.udp",
+        "item_description": "A number of total query counts which all auth servers receive over UDP since they started initially"
+      }
+    ],
+    "commands": [
+      {
+        "command_name": "status",
+        "command_description": "identify whether stats module is alive or not",
+        "command_args": []
+      },
+      {
+        "command_name": "show",
+        "command_description": "show the specified/all statistics data",
+        "command_args": [
+          {
+            "item_name": "stats_item_name",
+            "item_type": "string",
+            "item_optional": true,
+            "item_default": ""
+          }
+        ]
+      },
+      {
+        "command_name": "set",
+        "command_description": "set the value of specified name in statistics data",
+        "command_args": [
+          {
+            "item_name": "stats_data",
+            "item_type": "map",
+            "item_optional": false,
+            "item_default": {},
+            "map_item_spec": []
+          }
+        ]
+      },
+      {
+        "command_name": "remove",
+        "command_description": "remove the specified name from statistics data",
+        "command_args": [
+          {
+            "item_name": "stats_item_name",
+            "item_type": "string",
+            "item_optional": false,
+            "item_default": ""
+          }
+        ]
+      },
+      {
+        "command_name": "reset",
+        "command_description": "reset all statistics data to default values except for several constant names",
+        "command_args": []
+      },
+      {
+        "command_name": "shutdown",
+        "command_description": "Shut down the stats module",
+        "command_args": []
+      }
+    ]
+  }
+}
diff --git a/src/bin/stats/stats.spec.pre.in b/src/bin/stats/stats.spec.pre.in
deleted file mode 100644
index 6970250..0000000
--- a/src/bin/stats/stats.spec.pre.in
+++ /dev/null
@@ -1,140 +0,0 @@
-{
-  "module_spec": {
-    "module_name": "Stats",
-    "module_description": "Stats daemon",
-    "config_data": [
-      {
-        "item_name": "report_time",
-        "item_type": "string",
-        "item_optional": false,
-        "item_default": "1970-01-01T00:00:00Z",
-        "item_title": "Report time",
-        "item_description": "A date time when stats module reports",
-        "item_format": "date-time"
-      },
-      {
-        "item_name": "bind10.boot_time",
-        "item_type": "string",
-        "item_optional": false,
-        "item_default": "1970-01-01T00:00:00Z",
-        "item_title": "stats.BootTime",
-        "item_description": "A date time when bind10 process starts initially",
-        "item_format": "date-time"
-      },
-      {
-        "item_name": "stats.boot_time",
-        "item_type": "string",
-        "item_optional": false,
-        "item_default": "1970-01-01T00:00:00Z",
-        "item_title": "stats.BootTime",
-        "item_description": "A date time when the stats module starts initially or when the stats module restarts",
-        "item_format": "date-time"
-      },
-      {
-        "item_name": "stats.start_time",
-        "item_type": "string",
-        "item_optional": false,
-        "item_default": "1970-01-01T00:00:00Z",
-        "item_title": "stats.StartTime",
-        "item_description": "A date time when the stats module starts collecting data or resetting values last time",
-        "item_format": "date-time"
-      },
-      {
-        "item_name": "stats.last_update_time",
-        "item_type": "string",
-        "item_optional": false,
-        "item_default": "1970-01-01T00:00:00Z",
-        "item_title": "stats.LastUpdateTime",
-        "item_description": "The latest date time when the stats module receives from other modules like auth server or boss process and so on",
-        "item_format": "date-time"
-      },
-      {
-        "item_name": "stats.timestamp",
-        "item_type": "real",
-        "item_optional": false,
-        "item_default": 0.0,
-        "item_title": "stats.Timestamp",
-        "item_description": "A current time stamp since epoch time (1970-01-01T00:00:00Z)",
-        "item_format": "second"
-      },
-      {
-        "item_name": "stats.lname",
-        "item_type": "string",
-        "item_optional": false,
-        "item_default": "",
-        "item_title": "stats.LocalName",
-        "item_description": "A localname of stats module given via CC protocol"
-      },
-      {
-        "item_name": "auth.queries.tcp",
-        "item_type": "integer",
-        "item_optional": false,
-        "item_default": 0,
-        "item_title": "auth.queries.tcp",
-        "item_description": "A number of total query counts which all auth servers receive over TCP since they started initially"
-      },
-      {
-        "item_name": "auth.queries.udp",
-        "item_type": "integer",
-        "item_optional": false,
-        "item_default": 0,
-        "item_title": "auth.queries.udp",
-        "item_description": "A number of total query counts which all auth servers receive over UDP since they started initially"
-      }
-    ],
-    "commands": [
-      {
-        "command_name": "status",
-        "command_description": "identify whether stats module is alive or not",
-        "command_args": []
-      },
-      {
-        "command_name": "show",
-        "command_description": "show the specified/all statistics data",
-        "command_args": [
-          {
-            "item_name": "stats_item_name",
-            "item_type": "string",
-            "item_optional": true,
-            "item_default": ""
-          }
-        ]
-      },
-      {
-        "command_name": "set",
-        "command_description": "set the value of specified name in statistics data",
-        "command_args": [
-          {
-            "item_name": "stats_data",
-            "item_type": "map",
-            "item_optional": false,
-            "item_default": {},
-            "map_item_spec": []
-          }
-        ]
-      },
-      {
-        "command_name": "remove",
-        "command_description": "remove the specified name from statistics data",
-        "command_args": [
-          {
-            "item_name": "stats_item_name",
-            "item_type": "string",
-            "item_optional": false,
-            "item_default": ""
-          }
-        ]
-      },
-      {
-        "command_name": "reset",
-        "command_description": "reset all statistics data to default values except for several constant names",
-        "command_args": []
-      },
-      {
-        "command_name": "shutdown",
-        "command_description": "Shut down the stats module",
-        "command_args": []
-      }
-    ]
-  }
-}
diff --git a/src/bin/stats/stats_httpd.py.in b/src/bin/stats/stats_httpd.py.in
new file mode 100644
index 0000000..dd9220e
--- /dev/null
+++ b/src/bin/stats/stats_httpd.py.in
@@ -0,0 +1,485 @@
+#!@PYTHON@
+
+# Copyright (C) 2011  Internet Systems Consortium.
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SYSTEMS CONSORTIUM
+# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+# INTERNET SYSTEMS CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+# FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+"""
+A standalone HTTP server for HTTP/XML interface of statistics in BIND 10
+
+"""
+import sys; sys.path.append ('@@PYTHONPATH@@')
+import os
+import time
+import errno
+import select
+from optparse import OptionParser, OptionValueError
+import http.server
+import socket
+import string
+import xml.etree.ElementTree
+
+import isc.cc
+import isc.config
+import isc.util.process
+
+# If B10_FROM_SOURCE is set in the environment, we use data files
+# from a directory relative to that, otherwise we use the ones
+# installed on the system
+if "B10_FROM_SOURCE" in os.environ:
+    BASE_LOCATION = os.environ["B10_FROM_SOURCE"] + os.sep + \
+        "src" + os.sep + "bin" + os.sep + "stats"
+else:
+    PREFIX = "@prefix@"
+    DATAROOTDIR = "@datarootdir@"
+    BASE_LOCATION = "@datadir@" + os.sep + "@PACKAGE@"
+    BASE_LOCATION = BASE_LOCATION.replace("${datarootdir}", DATAROOTDIR).replace("${prefix}", PREFIX)
+SPECFILE_LOCATION = BASE_LOCATION + os.sep + "stats-httpd.spec"
+STATS_SPECFILE_LOCATION = BASE_LOCATION + os.sep + "stats.spec"
+XML_TEMPLATE_LOCATION = BASE_LOCATION + os.sep + "stats-httpd-xml.tpl"
+XSD_TEMPLATE_LOCATION = BASE_LOCATION + os.sep + "stats-httpd-xsd.tpl"
+XSL_TEMPLATE_LOCATION = BASE_LOCATION + os.sep + "stats-httpd-xsl.tpl"
+
+# These variables are paths part of URL.
+# eg. "http://${address}" + XXX_URL_PATH
+XML_URL_PATH = '/bind10/statistics/xml'
+XSD_URL_PATH = '/bind10/statistics/xsd'
+XSL_URL_PATH = '/bind10/statistics/xsl'
+# TODO: This should be considered later.
+XSD_NAMESPACE = 'http://bind10.isc.org' + XSD_URL_PATH
+DEFAULT_CONFIG = dict(listen_on=[('127.0.0.1', 8000)])
+
+# Assign this process name
+isc.util.process.rename()
+
+class HttpHandler(http.server.BaseHTTPRequestHandler):
+    """HTTP handler class for HttpServer class. The class inhrits the super
+    class http.server.BaseHTTPRequestHandler. It implemets do_GET()
+    and do_HEAD() and orverrides log_message()"""
+    def do_GET(self):
+        body = self.send_head()
+        if body is not None:
+            self.wfile.write(body.encode())
+
+    def do_HEAD(self):
+        self.send_head()
+
+    def send_head(self):
+        try:
+            if self.path == XML_URL_PATH:
+                body = self.server.xml_handler()
+            elif self.path == XSD_URL_PATH:
+                body = self.server.xsd_handler()
+            elif self.path == XSL_URL_PATH:
+                body = self.server.xsl_handler()
+            else:
+                if self.path == '/' and 'Host' in self.headers.keys():
+                    # redirect to XML URL only when requested with '/'
+                    self.send_response(302)
+                    self.send_header(
+                        "Location",
+                        "http://" + self.headers.get('Host') + XML_URL_PATH)
+                    self.end_headers()
+                    return None
+                else:
+                    # Couldn't find HOST
+                    self.send_error(404)
+                    return None
+        except StatsHttpdError as err:
+            self.send_error(500)
+            if self.server.verbose:
+                self.server.log_writer(
+                    "[b10-stats-httpd] %s\n" % err)
+            return None
+        else:
+            self.send_response(200)
+            self.send_header("Content-type", "text/xml")
+            self.send_header("Content-Length", len(body))
+            self.end_headers()
+            return body
+
+    def log_message(self, format, *args):
+        """Change the default log format"""
+        if self.server.verbose:
+            self.server.log_writer(
+                "[b10-stats-httpd] %s - - [%s] %s\n" %
+                (self.address_string(),
+                 self.log_date_time_string(),
+                 format%args))
+
+class HttpServerError(Exception):
+    """Exception class for HttpServer class. It is intended to be
+    passed from the HttpServer object to the StatsHttpd object."""
+    pass
+
+class HttpServer(http.server.HTTPServer):
+    """HTTP Server class. The class inherits the super
+    http.server.HTTPServer. Some parameters are specified as
+    arguments, which are xml_handler, xsd_handler, xsl_handler, and
+    log_writer. These all are parameters which the StatsHttpd object
+    has. The handler parameters are references of functions which
+    return body of each document. The last parameter log_writer is
+    reference of writer function to just write to
+    sys.stderr.write. They are intended to be referred by HttpHandler
+    object."""
+    def __init__(self, server_address, handler,
+                 xml_handler, xsd_handler, xsl_handler, log_writer, verbose=False):
+        self.server_address = server_address
+        self.xml_handler = xml_handler
+        self.xsd_handler = xsd_handler
+        self.xsl_handler = xsl_handler
+        self.log_writer = log_writer
+        self.verbose = verbose
+        http.server.HTTPServer.__init__(self, server_address, handler)
+
+class StatsHttpdError(Exception):
+    """Exception class for StatsHttpd class. It is intended to be
+    thrown from the the StatsHttpd object to the HttpHandler object or
+    main routine."""
+    pass
+
+class StatsHttpd:
+    """The main class of HTTP server of HTTP/XML interface for
+    statistics module. It handles HTTP requests, and command channel
+    and config channel CC session. It uses select.select function
+    while waiting for clients requests."""
+    def __init__(self, verbose=False):
+        self.verbose = verbose
+        self.running = False
+        self.poll_intval = 0.5
+        self.write_log = sys.stderr.write
+        self.mccs = None
+        self.httpd = []
+        self.open_mccs()
+        self.load_config()
+        self.load_templates()
+        self.open_httpd()
+
+    def open_mccs(self):
+        """Opens a ModuleCCSession object"""
+        # create ModuleCCSession
+        if self.verbose:
+            self.write_log("[b10-stats-httpd] Starting CC Session\n")
+        self.mccs = isc.config.ModuleCCSession(
+            SPECFILE_LOCATION, self.config_handler, self.command_handler)
+        self.cc_session = self.mccs._session
+        # read spec file of stats module and subscribe 'Stats'
+        self.stats_module_spec = isc.config.module_spec_from_file(STATS_SPECFILE_LOCATION)
+        self.stats_config_spec = self.stats_module_spec.get_config_spec()
+        self.stats_module_name = self.stats_module_spec.get_module_name()
+
+    def close_mccs(self):
+        """Closes a ModuleCCSession object"""
+        if self.mccs is None:
+            return
+        if self.verbose:
+            self.write_log("[b10-stats-httpd] Closing CC Session\n")
+        self.mccs.close()
+        self.mccs = None
+
+    def load_config(self, new_config={}):
+        """Loads configuration from spec file or new configuration
+        from the config manager"""
+        # load config
+        if len(new_config) > 0:
+            self.config.update(new_config)
+        else:
+            self.config = DEFAULT_CONFIG
+            self.config.update(
+                dict([
+                        (itm['item_name'], self.mccs.get_value(itm['item_name'])[0])
+                        for itm in self.mccs.get_module_spec().get_config_spec()
+                        ])
+                )
+        # set addresses and ports for HTTP
+        self.http_addrs = [ (cf['address'], cf['port']) for cf in self.config['listen_on'] ]
+
+    def open_httpd(self):
+        """Opens sockets for HTTP. Iterating each HTTP address to be
+        configured in spec file"""
+        for addr in self.http_addrs:
+            self.httpd.append(self._open_httpd(addr))
+
+    def _open_httpd(self, server_address, address_family=None):
+        try:
+            # try IPv6 at first
+            if address_family is not None:
+                HttpServer.address_family = address_family
+            elif socket.has_ipv6:
+                HttpServer.address_family = socket.AF_INET6
+            httpd = HttpServer(
+                server_address, HttpHandler,
+                self.xml_handler, self.xsd_handler, self.xsl_handler,
+                self.write_log, self.verbose)
+        except (socket.gaierror, socket.error,
+                OverflowError, TypeError) as err:
+            # try IPv4 next
+            if HttpServer.address_family == socket.AF_INET6:
+                httpd = self._open_httpd(server_address, socket.AF_INET)
+            else:
+                raise HttpServerError(
+                    "Invalid address %s, port %s: %s: %s" %
+                    (server_address[0], server_address[1],
+                     err.__class__.__name__, err))
+        else:
+            if self.verbose:
+                self.write_log(
+                    "[b10-stats-httpd] Started on address %s, port %s\n" %
+                    server_address)
+        return httpd
+
+    def close_httpd(self):
+        """Closes sockets for HTTP"""
+        if len(self.httpd) == 0:
+            return
+        for ht in self.httpd:
+            if self.verbose:
+                self.write_log(
+                    "[b10-stats-httpd] Closing address %s, port %s\n" %
+                    (ht.server_address[0], ht.server_address[1])
+                    )
+            ht.server_close()
+        self.httpd = []
+
+    def start(self):
+        """Starts StatsHttpd objects to run. Waiting for client
+        requests by using select.select functions"""
+        self.mccs.start()
+        self.running = True
+        while self.running:
+            try:
+                (rfd, wfd, xfd) = select.select(
+                    self.get_sockets(), [], [], self.poll_intval)
+            except select.error as err:
+                # select.error exception is caught only in the case of
+                # EINTR, or in other cases it is just thrown.
+                if err.args[0] == errno.EINTR:
+                    (rfd, wfd, xfd) = ([], [], [])
+                else:
+                    raise
+            # FIXME: This module can handle only one request at a
+            # time. If someone sends only part of the request, we block
+            # waiting for it until we time out.
+            # But it isn't so big issue for administration purposes.
+            for fd in rfd + xfd:
+                if fd == self.mccs.get_socket():
+                    self.mccs.check_command(nonblock=False)
+                    continue
+                for ht in self.httpd:
+                    if fd == ht.socket:
+                        ht.handle_request()
+                        break
+        self.stop()
+
+    def stop(self):
+        """Stops the running StatsHttpd objects. Closes CC session and
+        HTTP handling sockets"""
+        if self.verbose:
+            self.write_log("[b10-stats-httpd] Shutting down\n")
+        self.close_httpd()
+        self.close_mccs()
+
+    def get_sockets(self):
+        """Returns sockets to select.select"""
+        sockets = []
+        if self.mccs is not None:
+            sockets.append(self.mccs.get_socket())
+        if len(self.httpd) > 0:
+            for ht in self.httpd:
+                sockets.append(ht.socket)
+        return sockets
+
+    def config_handler(self, new_config):
+        """Config handler for the ModuleCCSession object. It resets
+        addresses and ports to listen HTTP requests on."""
+        if self.verbose:
+            self.write_log("[b10-stats-httpd] Loading config : %s\n" % str(new_config))
+        for key in new_config.keys():
+            if key not in DEFAULT_CONFIG:
+                if self.verbose:
+                    self.write_log(
+                        "[b10-stats-httpd] Unknown known config: %s" % key)
+                return isc.config.ccsession.create_answer(
+                    1, "Unknown known config: %s" % key)
+        # backup old config
+        old_config = self.config.copy()
+        self.close_httpd()
+        self.load_config(new_config)
+        try:
+            self.open_httpd()
+        except HttpServerError as err:
+            if self.verbose:
+                self.write_log("[b10-stats-httpd] %s\n" % err)
+                self.write_log("[b10-stats-httpd] Restoring old config\n")
+            # restore old config
+            self.config_handler(old_config)
+            return isc.config.ccsession.create_answer(
+                1, "[b10-stats-httpd] %s" % err)
+        else:
+            return isc.config.ccsession.create_answer(0)
+
+    def command_handler(self, command, args):
+        """Command handler for the ModuleCCSesson object. It handles
+        "status" and "shutdown" commands."""
+        if command == "status":
+            if self.verbose:
+                self.write_log("[b10-stats-httpd] Received 'status' command\n")
+            return isc.config.ccsession.create_answer(
+                0, "Stats Httpd is up. (PID " + str(os.getpid()) + ")")
+        elif command == "shutdown":
+            if self.verbose:
+                self.write_log("[b10-stats-httpd] Received 'shutdown' command\n")
+            self.running = False
+            return isc.config.ccsession.create_answer(
+                0, "Stats Httpd is shutting down.")
+        else:
+            if self.verbose:
+                self.write_log("[b10-stats-httpd] Received unknown command\n")
+            return isc.config.ccsession.create_answer(
+                1, "Unknown command: " + str(command))
+
+    def get_stats_data(self):
+        """Requests statistics data to the Stats daemon and returns
+        the data which obtains from it"""
+        try:
+            seq = self.cc_session.group_sendmsg(
+                isc.config.ccsession.create_command('show'),
+                self.stats_module_name)
+            (answer, env) = self.cc_session.group_recvmsg(False, seq)
+            if answer:
+                (rcode, value) = isc.config.ccsession.parse_answer(answer)
+        except (isc.cc.session.SessionTimeout,
+                isc.cc.session.SessionError) as err:
+            raise StatsHttpdError("%s: %s" %
+                                  (err.__class__.__name__, err))
+        else:
+            if rcode == 0:
+                return value
+            else:
+                raise StatsHttpdError("Stats module: %s" % str(value))
+
+    def get_stats_spec(self):
+        """Just returns spec data"""
+        return self.stats_config_spec
+
+    def load_templates(self):
+        """Setup the bodies of XSD and XSL documents to be responds to
+        HTTP clients. Before that it also creates XML tag structures by
+        using xml.etree.ElementTree.Element class and substitutes
+        concrete strings with parameters embed in the string.Template
+        object."""
+        # for XSD
+        xsd_root = xml.etree.ElementTree.Element("all") # started with "all" tag
+        for item in self.get_stats_spec():
+            element = xml.etree.ElementTree.Element(
+                "element",
+                dict( name=item["item_name"],
+                      type=item["item_type"] if item["item_type"].lower() != 'real' else 'float',
+                      minOccurs="1",
+                      maxOccurs="1" ),
+                )
+            annotation = xml.etree.ElementTree.Element("annotation")
+            appinfo = xml.etree.ElementTree.Element("appinfo")
+            documentation = xml.etree.ElementTree.Element("documentation")
+            appinfo.text = item["item_title"]
+            documentation.text = item["item_description"]
+            annotation.append(appinfo)
+            annotation.append(documentation)
+            element.append(annotation)
+            xsd_root.append(element)
+        xsd_string = xml.etree.ElementTree.tostring(xsd_root)
+        self.xsd_body = self.open_template(XSD_TEMPLATE_LOCATION).substitute(
+            xsd_string=xsd_string,
+            xsd_namespace=XSD_NAMESPACE
+            )
+        assert self.xsd_body is not None
+
+        # for XSL
+        xsd_root = xml.etree.ElementTree.Element(
+            "xsl:template",
+            dict(match="*")) # started with xml:template tag
+        for item in self.get_stats_spec():
+            tr = xml.etree.ElementTree.Element("tr")
+            td1 = xml.etree.ElementTree.Element(
+                "td", { "class" : "title",
+                        "title" : item["item_description"] })
+            td1.text = item["item_title"]
+            td2 = xml.etree.ElementTree.Element("td")
+            xsl_valueof = xml.etree.ElementTree.Element(
+                "xsl:value-of",
+                dict(select=item["item_name"]))
+            td2.append(xsl_valueof)
+            tr.append(td1)
+            tr.append(td2)
+            xsd_root.append(tr)
+        xsl_string = xml.etree.ElementTree.tostring(xsd_root)
+        self.xsl_body = self.open_template(XSL_TEMPLATE_LOCATION).substitute(
+            xsl_string=xsl_string,
+            xsd_namespace=XSD_NAMESPACE)
+        assert self.xsl_body is not None
+
+    def xml_handler(self):
+        """Handler which requests to Stats daemon to obtain statistics
+        data and returns the body of XML document"""
+        xml_list=[]
+        for (k, v) in self.get_stats_data().items():
+            (k, v) = (str(k), str(v))
+            elem = xml.etree.ElementTree.Element(k)
+            elem.text = v
+            xml_list.append(
+                xml.etree.ElementTree.tostring(elem))
+        xml_string = "".join(xml_list)
+        self.xml_body = self.open_template(XML_TEMPLATE_LOCATION).substitute(
+            xml_string=xml_string,
+            xsd_namespace=XSD_NAMESPACE,
+            xsd_url_path=XSD_URL_PATH,
+            xsl_url_path=XSL_URL_PATH)
+        assert self.xml_body is not None
+        return self.xml_body
+
+    def xsd_handler(self):
+        """Handler which just returns the body of XSD document"""
+        return self.xsd_body
+
+    def xsl_handler(self):
+        """Handler which just returns the body of XSL document"""
+        return self.xsl_body
+
+    def open_template(self, file_name):
+        """It opens a template file, and it loads all lines to a
+        string variable and returns string. Template object includes
+        the variable. Limitation of a file size isn't needed there."""
+        lines = "".join(
+            open(file_name, 'r').readlines())
+        assert lines is not None
+        return string.Template(lines)
+
+if __name__ == "__main__":
+    try:
+        parser = OptionParser()
+        parser.add_option(
+            "-v", "--verbose", dest="verbose", action="store_true",
+            help="display more about what is going on")
+        (options, args) = parser.parse_args()
+        stats_httpd = StatsHttpd(verbose=options.verbose)
+        stats_httpd.start()
+    except OptionValueError:
+        sys.exit("[b10-stats-httpd] Error parsing options")
+    except isc.cc.session.SessionError as se:
+        sys.exit("[b10-stats-httpd] Error creating module, "
+                 + "is the command channel daemon running?")
+    except HttpServerError as hse:
+        sys.exit("[b10-stats-httpd] %s" % hse)
+    except KeyboardInterrupt as kie:
+        sys.exit("[b10-stats-httpd] Interrupted, exiting")
diff --git a/src/bin/stats/stats_stub.py.in b/src/bin/stats/stats_stub.py.in
deleted file mode 100755
index 4a4a641..0000000
--- a/src/bin/stats/stats_stub.py.in
+++ /dev/null
@@ -1,154 +0,0 @@
-#!@PYTHON@
-
-# Copyright (C) 2010  Internet Systems Consortium.
-#
-# Permission to use, copy, modify, and distribute this software for any
-# purpose with or without fee is hereby granted, provided that the above
-# copyright notice and this permission notice appear in all copies.
-#
-# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SYSTEMS CONSORTIUM
-# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
-# INTERNET SYSTEMS CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
-# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
-# FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
-# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
-# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-__version__ = "$Revision$"
-
-import sys; sys.path.append ('@@PYTHONPATH@@')
-import os
-import time
-from optparse import OptionParser, OptionValueError
-from isc.config.ccsession import ModuleCCSession, create_command, parse_answer, parse_command, create_answer
-from isc.cc import Session, SessionError
-from stats import get_datetime
-
-# for setproctitle
-import isc.util.process
-isc.util.process.rename()
-
-# If B10_FROM_BUILD is set in the environment, we use data files
-# from a directory relative to that, otherwise we use the ones
-# installed on the system
-if "B10_FROM_BUILD" in os.environ:
-    SPECFILE_LOCATION = os.environ["B10_FROM_BUILD"] + "/src/bin/stats/stats.spec"
-else:
-    PREFIX = "@prefix@"
-    DATAROOTDIR = "@datarootdir@"
-    SPECFILE_LOCATION = "@datadir@/@PACKAGE@/stats.spec".replace("${datarootdir}", DATAROOTDIR).replace("${prefix}", PREFIX)
-
-class CCSessionStub:
-    """
-    This class is intended to behaves as a sender to Stats module. It
-    creates MoudleCCSession object and send specified command.
-    """
-    def __init__(self, session=None, verbose=False):
-        # create ModuleCCSession object
-        self.verbose = verbose
-        self.cc_session = ModuleCCSession(SPECFILE_LOCATION,
-                                          self.__dummy, self.__dummy, session)
-        self.module_name = self.cc_session._module_name
-        self.session = self.cc_session._session
-
-    def __dummy(self, *args):
-        pass
-
-    def send_command(self, command, args):
-        """
-        send command to stats module with args
-        """
-        cmd = create_command(command, args)
-        if self.verbose:
-            sys.stdout.write("[b10-stats_stub] send command : " + str(cmd) + "\n")
-        seq = self.session.group_sendmsg(cmd, self.module_name)
-        msg, env = self.session.group_recvmsg(False, seq) # non-blocking is False
-        if self.verbose:
-            sys.stdout.write("[b10-stats_stub] received env : " + str(env) + "\n")
-            sys.stdout.write("[b10-stats_stub] received message : " + str(msg) + "\n")
-        (ret, arg) = (None, None)
-        if 'result' in msg:
-            ret, arg = parse_answer(msg)
-        elif 'command' in msg:
-            ret, arg = parse_command(msg)
-        self.session.group_reply(env, create_answer(0))
-        return ret, arg, env
-        
-class BossModuleStub:
-    """
-    This class is customized from CCSessionStub and is intended to behaves
-    as a virtual Boss module to send to Stats Module.
-    """
-    def __init__(self, session=None, verbose=False):
-        self.stub = CCSessionStub(session=session, verbose=verbose)
-    
-    def send_boottime(self):
-        return self.stub.send_command("set", {"stats_data": {"bind10.boot_time": get_datetime()}})
-
-class AuthModuleStub:
-    """
-    This class is customized CCSessionStub and is intended to behaves
-    as a virtual Auth module to send to Stats Module.
-    """
-    def __init__(self, session=None, verbose=False):
-        self.stub = CCSessionStub(session=session, verbose=verbose)
-        self.count = { "udp": 0, "tcp": 0 }
-    
-    def send_udp_query_count(self, cmd="set", cnt=0):
-        """
-        count up udp query count
-        """
-        prt = "udp"
-        self.count[prt] = 1
-        if cnt > 0:
-            self.count[prt] = cnt
-        return self.stub.send_command(cmd,
-                                      {"stats_data":
-                                           {"auth.queries."+prt: self.count[prt]}
-                                       })
-
-    def send_tcp_query_count(self, cmd="set", cnt=0):
-        """
-        set udp query count
-        """
-        prt = "tcp"
-        self.count[prt] = self.count[prt] + 1
-        if cnt > 0:
-            self.count[prt] = cnt
-        return self.stub.send_command(cmd,
-                                      {"stats_data":
-                                           {"auth.queries."+prt: self.count[prt]}
-                                       })
-
-def main(session=None):
-    try:
-        parser=OptionParser()
-        parser.add_option("-v", "--verbose", dest="verbose", action="store_true",
-                      help="display more about what is going on")
-        (options, args) = parser.parse_args()
-        stub = CCSessionStub(session=session, verbose=options.verbose)
-        boss = BossModuleStub(session=stub.session, verbose=options.verbose)
-        auth = AuthModuleStub(session=stub.session, verbose=options.verbose)
-        stub.send_command("status", None)
-        boss.send_boottime()
-        t_cnt=0
-        u_cnt=81120
-        auth.send_udp_query_count(cnt=u_cnt) # This is an example.
-        while True:
-            u_cnt = u_cnt + 1
-            t_cnt = t_cnt + 1
-            auth.send_udp_query_count(cnt=u_cnt)
-            auth.send_tcp_query_count(cnt=t_cnt)
-            time.sleep(1)
-
-    except OptionValueError:
-        sys.stderr.write("[b10-stats_stub] Error parsing options\n")
-    except SessionError as se:
-        sys.stderr.write("[b10-stats_stub] Error creating Stats module, "
-              + "is the command channel daemon running?\n")
-    except KeyboardInterrupt as kie:
-        sys.stderr.write("[b10-stats_stub] Interrupted, exiting\n")
-
-if __name__ == "__main__":
-    main()
diff --git a/src/bin/stats/tests/Makefile.am b/src/bin/stats/tests/Makefile.am
index 9e94050..5a13277 100644
--- a/src/bin/stats/tests/Makefile.am
+++ b/src/bin/stats/tests/Makefile.am
@@ -1,8 +1,8 @@
-SUBDIRS = isc testdata
+SUBDIRS = isc http testdata
 PYCOVERAGE_RUN = @PYCOVERAGE_RUN@
-PYTESTS = b10-stats_test.py b10-stats_stub_test.py
-EXTRA_DIST = $(PYTESTS) fake_time.py
-CLEANFILES = fake_time.pyc
+PYTESTS = b10-stats_test.py b10-stats-httpd_test.py
+EXTRA_DIST = $(PYTESTS) fake_time.py fake_socket.py fake_select.py
+CLEANFILES = fake_time.pyc fake_socket.pyc fake_select.pyc
 
 # test using command-line arguments, so use check-local target instead of TESTS
 check-local:
@@ -14,6 +14,6 @@ endif
 	for pytest in $(PYTESTS) ; do \
 	echo Running test: $$pytest ; \
 	env PYTHONPATH=$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python:$(abs_top_builddir)/src/bin/stats:$(abs_top_builddir)/src/bin/stats/tests \
-	B10_FROM_BUILD=$(abs_top_builddir) \
+	B10_FROM_SOURCE=$(abs_top_srcdir) \
 	$(PYCOVERAGE_RUN) $(abs_srcdir)/$$pytest || exit ; \
 	done
diff --git a/src/bin/stats/tests/b10-stats-httpd_test.py b/src/bin/stats/tests/b10-stats-httpd_test.py
new file mode 100644
index 0000000..07999ea
--- /dev/null
+++ b/src/bin/stats/tests/b10-stats-httpd_test.py
@@ -0,0 +1,444 @@
+# Copyright (C) 2011  Internet Systems Consortium.
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SYSTEMS CONSORTIUM
+# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+# INTERNET SYSTEMS CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+# FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+import unittest
+import os
+import http.server
+import string
+import fake_select
+import imp
+import sys
+import fake_socket
+
+import isc.cc
+
+import stats_httpd
+stats_httpd.socket = fake_socket
+stats_httpd.select = fake_select
+
+DUMMY_DATA = {
+    "auth.queries.tcp": 10000,
+    "auth.queries.udp": 12000,
+    "bind10.boot_time": "2011-03-04T11:59:05Z",
+    "report_time": "2011-03-04T11:59:19Z",
+    "stats.boot_time": "2011-03-04T11:59:06Z",
+    "stats.last_update_time": "2011-03-04T11:59:07Z",
+    "stats.lname": "4d70d40a_c at host",
+    "stats.start_time": "2011-03-04T11:59:06Z",
+    "stats.timestamp": 1299239959.560846
+    }
+
+def push_answer(stats_httpd):
+    stats_httpd.cc_session.group_sendmsg(
+        { 'result': 
+          [ 0, DUMMY_DATA ] }, "Stats")
+
+def pull_query(stats_httpd):
+    (msg, env) = stats_httpd.cc_session.group_recvmsg()
+    if 'result' in msg:
+        (ret, arg) = isc.config.ccsession.parse_answer(msg)
+    else:
+        (ret, arg) = isc.config.ccsession.parse_command(msg)
+    return (ret, arg, env)
+
+class TestHttpHandler(unittest.TestCase):
+    """Tests for HttpHandler class"""
+
+    def setUp(self):
+        self.verbose = True
+        self.stats_httpd = stats_httpd.StatsHttpd(self.verbose)
+        self.assertTrue(type(self.stats_httpd.httpd) is list)
+        self.httpd = self.stats_httpd.httpd
+        for ht in self.httpd:
+            self.assertTrue(ht.verbose)
+        self.stats_httpd.cc_session.verbose = False
+
+    def test_do_GET(self):
+        for ht in self.httpd:
+            self._test_do_GET(ht._handler)
+
+    def _test_do_GET(self, handler):
+
+        # URL is '/bind10/statistics/xml'
+        handler.path = stats_httpd.XML_URL_PATH
+        push_answer(self.stats_httpd)
+        handler.do_GET()
+        (ret, arg, env) = pull_query(self.stats_httpd)
+        self.assertEqual(ret, "show")
+        self.assertIsNone(arg)
+        self.assertTrue('group' in env)
+        self.assertEqual(env['group'], 'Stats')
+        self.assertEqual(handler.response.code, 200)
+        self.assertEqual(handler.response.headers["Content-type"], "text/xml")
+        self.assertTrue(handler.response.headers["Content-Length"] > 0)
+        self.assertTrue(handler.response.wrote_headers)
+        self.assertTrue(handler.response.body.find(stats_httpd.XSD_NAMESPACE)>0)
+        self.assertTrue(handler.response.body.find(stats_httpd.XSD_URL_PATH)>0)
+        for (k, v) in DUMMY_DATA.items():
+            self.assertTrue(handler.response.body.find(str(k))>0)
+            self.assertTrue(handler.response.body.find(str(v))>0)
+
+        # URL is '/bind10/statitics/xsd'
+        handler.path = stats_httpd.XSD_URL_PATH
+        handler.do_GET()
+        self.assertEqual(handler.response.code, 200)
+        self.assertEqual(handler.response.headers["Content-type"], "text/xml")
+        self.assertTrue(handler.response.headers["Content-Length"] > 0)
+        self.assertTrue(handler.response.wrote_headers)
+        self.assertTrue(handler.response.body.find(stats_httpd.XSD_NAMESPACE)>0)
+        for (k, v) in DUMMY_DATA.items():
+            self.assertTrue(handler.response.body.find(str(k))>0)
+
+        # URL is '/bind10/statitics/xsl'
+        handler.path = stats_httpd.XSL_URL_PATH
+        handler.do_GET()
+        self.assertEqual(handler.response.code, 200)
+        self.assertEqual(handler.response.headers["Content-type"], "text/xml")
+        self.assertTrue(handler.response.headers["Content-Length"] > 0)
+        self.assertTrue(handler.response.wrote_headers)
+        self.assertTrue(handler.response.body.find(stats_httpd.XSD_NAMESPACE)>0)
+        for (k, v) in DUMMY_DATA.items():
+            self.assertTrue(handler.response.body.find(str(k))>0)
+
+        # 302 redirect
+        handler.path = '/'
+        handler.headers = {'Host': 'my.host.domain'}
+        handler.do_GET()
+        self.assertEqual(handler.response.code, 302)
+        self.assertEqual(handler.response.headers["Location"],
+                         "http://my.host.domain%s" % stats_httpd.XML_URL_PATH)
+
+        # 404 NotFound
+        handler.path = '/path/to/foo/bar'
+        handler.headers = {}
+        handler.do_GET()
+        self.assertEqual(handler.response.code, 404)
+
+        # failure case(connection with Stats is down)
+        handler.path = stats_httpd.XML_URL_PATH
+        push_answer(self.stats_httpd)
+        self.assertFalse(self.stats_httpd.cc_session._socket._closed)
+        self.stats_httpd.cc_session._socket._closed = True
+        handler.do_GET()
+        self.stats_httpd.cc_session._socket._closed = False
+        self.assertEqual(handler.response.code, 500)
+        self.stats_httpd.cc_session._clear_queues()
+
+        # failure case(Stats module returns err)
+        handler.path = stats_httpd.XML_URL_PATH
+        self.stats_httpd.cc_session.group_sendmsg(
+            { 'result': [ 1, "I have an error." ] }, "Stats")
+        self.assertFalse(self.stats_httpd.cc_session._socket._closed)
+        self.stats_httpd.cc_session._socket._closed = False
+        handler.do_GET()
+        self.assertEqual(handler.response.code, 500)
+        self.stats_httpd.cc_session._clear_queues()
+
+    def test_do_HEAD(self):
+        for ht in self.httpd:
+            self._test_do_HEAD(ht._handler)
+
+    def _test_do_HEAD(self, handler):
+        handler.path = '/path/to/foo/bar'
+        handler.do_HEAD()
+        self.assertEqual(handler.response.code, 404)
+
+    def test_log_message(self):
+        for ht in self.httpd:
+            self._test_log_message(ht._handler)
+
+    def _test_log_message(self, handler):
+        # switch write_log function
+        handler.server.log_writer = handler.response._write_log
+        log_message = 'ABCDEFG'
+        handler.log_message("%s", log_message)
+        self.assertEqual(handler.response.log, 
+                         "[b10-stats-httpd] %s - - [%s] %s\n" %
+                         (handler.address_string(),
+                          handler.log_date_time_string(),
+                          log_message))
+
+class TestHttpServerError(unittest.TestCase):
+    """Tests for HttpServerError exception"""
+
+    def test_raises(self):
+        try:
+            raise stats_httpd.HttpServerError('Nothing')
+        except stats_httpd.HttpServerError as err:
+            self.assertEqual(str(err), 'Nothing')
+
+class TestHttpServer(unittest.TestCase):
+    """Tests for HttpServer class"""
+
+    def test_httpserver(self):
+        self.verbose = True
+        self.stats_httpd = stats_httpd.StatsHttpd(self.verbose)
+        self.stats_httpd.cc_session.verbose = False
+        for ht in self.stats_httpd.httpd:
+            self.assertTrue(ht.server_address in self.stats_httpd.http_addrs)
+            self.assertEqual(ht.verbose, self.verbose)
+            self.assertEqual(ht.xml_handler, self.stats_httpd.xml_handler)
+            self.assertEqual(ht.xsd_handler, self.stats_httpd.xsd_handler)
+            self.assertEqual(ht.xsl_handler, self.stats_httpd.xsl_handler)
+            self.assertEqual(ht.log_writer, self.stats_httpd.write_log)
+            self.assertTrue(isinstance(ht._handler, stats_httpd.HttpHandler))
+            self.assertTrue(isinstance(ht.socket, fake_socket.socket))
+
+class TestStatsHttpdError(unittest.TestCase):
+    """Tests for StatsHttpdError exception"""
+
+    def test_raises(self):
+        try:
+            raise stats_httpd.StatsHttpdError('Nothing')
+        except stats_httpd.StatsHttpdError as err:
+            self.assertEqual(str(err), 'Nothing')
+
+class TestStatsHttpd(unittest.TestCase):
+    """Tests for StatsHttpd class"""
+
+    def setUp(self):
+        self.verbose = True
+        fake_socket._CLOSED = False
+        fake_socket.has_ipv6 = True
+        self.stats_httpd = stats_httpd.StatsHttpd(self.verbose)
+        self.stats_httpd.cc_session.verbose = False
+
+    def tearDown(self):
+        self.stats_httpd.stop()
+
+    def test_init(self):
+        self.assertTrue(self.stats_httpd.verbose)
+        self.assertFalse(self.stats_httpd.mccs.get_socket()._closed)
+        self.assertEqual(self.stats_httpd.mccs.get_socket().fileno(),
+                         id(self.stats_httpd.mccs.get_socket()))
+        for ht in self.stats_httpd.httpd:
+            self.assertFalse(ht.socket._closed)
+            self.assertEqual(ht.socket.fileno(), id(ht.socket))
+        fake_socket._CLOSED = True
+        self.assertRaises(isc.cc.session.SessionError,
+                          stats_httpd.StatsHttpd)
+        fake_socket._CLOSED = False
+
+    def test_mccs(self):
+        self.stats_httpd.open_mccs()
+        self.assertTrue(
+            isinstance(self.stats_httpd.mccs.get_socket(), fake_socket.socket))
+        self.assertTrue(
+            isinstance(self.stats_httpd.cc_session, isc.cc.session.Session))
+        self.assertTrue(
+            isinstance(self.stats_httpd.stats_module_spec, isc.config.ModuleSpec))
+        for cfg in self.stats_httpd.stats_config_spec:
+            self.assertTrue('item_name' in cfg)
+            self.assertTrue(cfg['item_name'] in DUMMY_DATA)
+        self.assertTrue(len(self.stats_httpd.stats_config_spec), len(DUMMY_DATA))
+
+    def test_load_config(self):
+        self.stats_httpd.load_config()
+        self.assertTrue(('127.0.0.1', 8000) in set(self.stats_httpd.http_addrs))
+
+    def test_httpd(self):
+        # dual stack (addresses is ipv4 and ipv6)
+        fake_socket.has_ipv6 = True
+        self.assertTrue(('127.0.0.1', 8000) in set(self.stats_httpd.http_addrs))
+        self.stats_httpd.http_addrs = [ ('::1', 8000), ('127.0.0.1', 8000) ]
+        self.assertTrue(
+            stats_httpd.HttpServer.address_family in set([fake_socket.AF_INET, fake_socket.AF_INET6]))
+        self.stats_httpd.open_httpd()
+        for ht in self.stats_httpd.httpd:
+            self.assertTrue(isinstance(ht.socket, fake_socket.socket))
+        self.stats_httpd.close_httpd()
+
+        # dual stack (address is ipv6)
+        fake_socket.has_ipv6 = True
+        self.stats_httpd.http_addrs = [ ('::1', 8000) ]
+        self.stats_httpd.open_httpd()
+        for ht in self.stats_httpd.httpd:
+            self.assertTrue(isinstance(ht.socket, fake_socket.socket))
+        self.stats_httpd.close_httpd()
+
+        # dual stack (address is ipv4)
+        fake_socket.has_ipv6 = True
+        self.stats_httpd.http_addrs = [ ('127.0.0.1', 8000) ]
+        self.stats_httpd.open_httpd()
+        for ht in self.stats_httpd.httpd:
+            self.assertTrue(isinstance(ht.socket, fake_socket.socket))
+        self.stats_httpd.close_httpd()
+
+        # only-ipv4 single stack
+        fake_socket.has_ipv6 = False
+        self.stats_httpd.http_addrs = [ ('127.0.0.1', 8000) ]
+        self.stats_httpd.open_httpd()
+        for ht in self.stats_httpd.httpd:
+            self.assertTrue(isinstance(ht.socket, fake_socket.socket))
+        self.stats_httpd.close_httpd()
+
+        # only-ipv4 single stack (force set ipv6 )
+        fake_socket.has_ipv6 = False
+        self.stats_httpd.http_addrs = [ ('::1', 8000) ]
+        self.assertRaises(stats_httpd.HttpServerError,
+            self.stats_httpd.open_httpd)
+
+        # hostname
+        self.stats_httpd.http_addrs = [ ('localhost', 8000) ]
+        self.stats_httpd.open_httpd()
+        for ht in self.stats_httpd.httpd:
+            self.assertTrue(isinstance(ht.socket, fake_socket.socket))
+        self.stats_httpd.close_httpd()
+
+        self.stats_httpd.http_addrs = [ ('my.host.domain', 8000) ]
+        self.stats_httpd.open_httpd()
+        for ht in self.stats_httpd.httpd:
+            self.assertTrue(isinstance(ht.socket, fake_socket.socket))
+        self.stats_httpd.close_httpd()
+
+        # over flow of port number
+        self.stats_httpd.http_addrs = [ ('', 80000) ]
+        self.assertRaises(stats_httpd.HttpServerError, self.stats_httpd.open_httpd)
+        # negative
+        self.stats_httpd.http_addrs = [ ('', -8000) ]
+        self.assertRaises(stats_httpd.HttpServerError, self.stats_httpd.open_httpd)
+        # alphabet
+        self.stats_httpd.http_addrs = [ ('', 'ABCDE') ]
+        self.assertRaises(stats_httpd.HttpServerError, self.stats_httpd.open_httpd)
+
+    def test_start(self):
+        self.stats_httpd.cc_session.group_sendmsg(
+            { 'command': [ "shutdown" ] }, "StatsHttpd")
+        self.stats_httpd.start()
+        self.stats_httpd = stats_httpd.StatsHttpd(self.verbose)
+        self.stats_httpd.cc_session.verbose = False
+        self.assertRaises(
+            fake_select.error, self.stats_httpd.start)
+
+    def test_stop(self):
+        # success case
+        fake_socket._CLOSED = False
+        self.stats_httpd.stop()
+        self.assertFalse(self.stats_httpd.running)
+        self.assertIsNone(self.stats_httpd.mccs)
+        for ht in self.stats_httpd.httpd:
+            self.assertTrue(ht.socket._closed)
+        self.assertTrue(self.stats_httpd.cc_session._socket._closed)
+        # failure case
+        self.stats_httpd.cc_session._socket._closed = False
+        self.stats_httpd.open_mccs()
+        self.stats_httpd.cc_session._socket._closed = True
+        self.stats_httpd.stop() # No excetion raises
+        self.stats_httpd.cc_session._socket._closed = False
+
+    def test_open_template(self):
+        # successful conditions
+        tmpl = self.stats_httpd.open_template(stats_httpd.XML_TEMPLATE_LOCATION)
+        self.assertTrue(isinstance(tmpl, string.Template))
+        opts = dict(
+            xml_string="<dummy></dummy>",
+            xsd_namespace="http://host/path/to/",
+            xsd_url_path="/path/to/",
+            xsl_url_path="/path/to/")
+        lines = tmpl.substitute(opts)
+        for n in opts:
+            self.assertTrue(lines.find(opts[n])>0)
+        tmpl = self.stats_httpd.open_template(stats_httpd.XSD_TEMPLATE_LOCATION)
+        self.assertTrue(isinstance(tmpl, string.Template))
+        opts = dict(
+            xsd_string="<dummy></dummy>",
+            xsd_namespace="http://host/path/to/")
+        lines = tmpl.substitute(opts)
+        for n in opts:
+            self.assertTrue(lines.find(opts[n])>0)
+        tmpl = self.stats_httpd.open_template(stats_httpd.XSL_TEMPLATE_LOCATION)
+        self.assertTrue(isinstance(tmpl, string.Template))
+        opts = dict(
+            xsl_string="<dummy></dummy>",
+            xsd_namespace="http://host/path/to/")
+        lines = tmpl.substitute(opts)
+        for n in opts:
+            self.assertTrue(lines.find(opts[n])>0)
+        # unsuccessful condition
+        self.assertRaises(
+            IOError,
+            self.stats_httpd.open_template, '/path/to/foo/bar')
+
+    def test_commands(self):
+        self.assertEqual(self.stats_httpd.command_handler("status", None),
+                         isc.config.ccsession.create_answer(
+                0, "Stats Httpd is up. (PID " + str(os.getpid()) + ")"))
+        self.stats_httpd.running = True
+        self.assertEqual(self.stats_httpd.command_handler("shutdown", None),
+                         isc.config.ccsession.create_answer(
+                0, "Stats Httpd is shutting down."))
+        self.assertFalse(self.stats_httpd.running)
+        self.assertEqual(
+            self.stats_httpd.command_handler("__UNKNOWN_COMMAND__", None),
+            isc.config.ccsession.create_answer(
+                1, "Unknown command: __UNKNOWN_COMMAND__"))
+
+    def test_config(self):
+        self.assertEqual(
+            self.stats_httpd.config_handler(dict(_UNKNOWN_KEY_=None)),
+            isc.config.ccsession.create_answer(
+                    1, "Unknown known config: _UNKNOWN_KEY_"))
+        self.assertEqual(
+            self.stats_httpd.config_handler(
+                        dict(listen_on=[dict(address="::2",port=8000)])),
+            isc.config.ccsession.create_answer(0))
+        self.assertTrue("listen_on" in self.stats_httpd.config)
+        for addr in self.stats_httpd.config["listen_on"]:
+            self.assertTrue("address" in addr)
+            self.assertTrue("port" in addr)
+            self.assertTrue(addr["address"] == "::2")
+            self.assertTrue(addr["port"] == 8000)
+
+        self.assertEqual(
+            self.stats_httpd.config_handler(
+                        dict(listen_on=[dict(address="::1",port=80)])),
+            isc.config.ccsession.create_answer(0))
+        self.assertTrue("listen_on" in self.stats_httpd.config)
+        for addr in self.stats_httpd.config["listen_on"]:
+            self.assertTrue("address" in addr)
+            self.assertTrue("port" in addr)
+            self.assertTrue(addr["address"] == "::1")
+            self.assertTrue(addr["port"] == 80)
+
+        self.assertEqual(
+            self.stats_httpd.config_handler(
+                        dict(listen_on=[dict(address="1.2.3.4",port=54321)])),
+            isc.config.ccsession.create_answer(0))
+        self.assertTrue("listen_on" in self.stats_httpd.config)
+        for addr in self.stats_httpd.config["listen_on"]:
+            self.assertTrue("address" in addr)
+            self.assertTrue("port" in addr)
+            self.assertTrue(addr["address"] == "1.2.3.4")
+            self.assertTrue(addr["port"] == 54321)
+        (ret, arg) = isc.config.ccsession.parse_answer(
+            self.stats_httpd.config_handler(
+                dict(listen_on=[dict(address="1.2.3.4",port=543210)]))
+            )
+        self.assertEqual(ret, 1)
+
+    def test_for_without_B10_FROM_SOURCE(self):
+        # just lets it go through the code without B10_FROM_SOURCE env
+        # variable
+        if "B10_FROM_SOURCE" in os.environ:
+            tmppath = os.environ["B10_FROM_SOURCE"]
+            os.environ.pop("B10_FROM_SOURCE")
+            imp.reload(stats_httpd)
+            os.environ["B10_FROM_SOURCE"] = tmppath
+            imp.reload(stats_httpd)
+            stats_httpd.socket = fake_socket
+            stats_httpd.select = fake_select
+
+if __name__ == "__main__":
+    unittest.main()
diff --git a/src/bin/stats/tests/b10-stats_stub_test.py b/src/bin/stats/tests/b10-stats_stub_test.py
deleted file mode 100644
index b8983c5..0000000
--- a/src/bin/stats/tests/b10-stats_stub_test.py
+++ /dev/null
@@ -1,115 +0,0 @@
-# Copyright (C) 2010  Internet Systems Consortium.
-#
-# Permission to use, copy, modify, and distribute this software for any
-# purpose with or without fee is hereby granted, provided that the above
-# copyright notice and this permission notice appear in all copies.
-#
-# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SYSTEMS CONSORTIUM
-# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
-# INTERNET SYSTEMS CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
-# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
-# FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
-# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
-# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-__version__ = "$Revision$"
-
-#
-# Tests for the stats stub module
-#
-import unittest
-import time
-import os
-import imp
-import stats_stub
-from isc.cc.session import Session
-from stats_stub import CCSessionStub, BossModuleStub, AuthModuleStub
-from stats import get_datetime
-
-class TestStats(unittest.TestCase):
-
-    def setUp(self):
-        self.session = Session()
-        self.stub = CCSessionStub(session=self.session, verbose=True)
-        self.boss = BossModuleStub(session=self.session, verbose=True)
-        self.auth = AuthModuleStub(session=self.session, verbose=True)
-        self.env = {'from': self.session.lname, 'group': 'Stats',
-                    'instance': '*', 'to':'*',
-                    'type':'send','seq':0}
-        self.result_ok = {'result': [0]}
-
-    def tearDown(self):
-        self.session.close()
-
-    def test_stub(self):
-        """
-        Test for send_command of CCSessionStub object
-        """
-        env = self.env
-        result_ok = self.result_ok
-        self.assertEqual(('status', None, env),
-                         self.stub.send_command('status', None))
-        self.assertEqual(result_ok, self.session.get_message("Stats", None))
-        self.assertEqual(('shutdown', None, env),
-                         self.stub.send_command('shutdown', None))
-        self.assertEqual(result_ok, self.session.get_message("Stats", None))
-        self.assertEqual(('show', None, env),
-                         self.stub.send_command('show', None))
-        self.assertEqual(result_ok, self.session.get_message("Stats", None))
-        self.assertEqual(('set', {'atest': 100.0}, env),
-                         self.stub.send_command('set', {'atest': 100.0}))
-        self.assertEqual(result_ok, self.session.get_message("Stats", None))
-
-    def test_boss_stub(self):
-        """
-        Test for send_command of BossModuleStub object
-        """
-        env = self.env
-        result_ok = self.result_ok
-        self.assertEqual(('set', {"stats_data":
-                                      {"bind10.boot_time": get_datetime()}
-                                  }, env), self.boss.send_boottime())
-        self.assertEqual(result_ok, self.session.get_message("Stats", None))
-
-    def test_auth_stub(self):
-        """
-        Test for send_command of AuthModuleStub object
-        """
-        env = self.env
-        result_ok = self.result_ok
-        self.assertEqual(
-            ('set', {"stats_data": {"auth.queries.udp": 1}}, env),
-            self.auth.send_udp_query_count())
-        self.assertEqual(result_ok, self.session.get_message("Stats", None))
-        self.assertEqual(
-            ('set', {"stats_data": {"auth.queries.tcp": 1}}, env),
-            self.auth.send_tcp_query_count())
-        self.assertEqual(result_ok, self.session.get_message("Stats", None))
-        self.assertEqual(
-            ('set', {"stats_data": {"auth.queries.udp": 100}}, env),
-            self.auth.send_udp_query_count(cmd='set', cnt=100))
-        self.assertEqual(result_ok, self.session.get_message("Stats", None))
-        self.assertEqual(
-            ('set', {"stats_data": {"auth.queries.tcp": 99}}, env),
-            self.auth.send_tcp_query_count(cmd='set', cnt=99))
-        self.assertEqual(result_ok, self.session.get_message("Stats", None))
-
-    def test_func_main(self):
-        # explicitly make failed
-        self.session.close()
-        stats_stub.main(session=self.session)
-
-    def test_osenv(self):
-        """
-        test for not having environ "B10_FROM_BUILD"
-        """
-        if "B10_FROM_BUILD" in os.environ:
-            path = os.environ["B10_FROM_BUILD"]
-            os.environ.pop("B10_FROM_BUILD")
-            imp.reload(stats_stub)
-            os.environ["B10_FROM_BUILD"] = path
-            imp.reload(stats_stub)
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/src/bin/stats/tests/b10-stats_test.py b/src/bin/stats/tests/b10-stats_test.py
index 3566bc4..818b67a 100644
--- a/src/bin/stats/tests/b10-stats_test.py
+++ b/src/bin/stats/tests/b10-stats_test.py
@@ -1,4 +1,4 @@
-# Copyright (C) 2010,2011  Internet Systems Consortium.
+# Copyright (C) 2010, 2011  Internet Systems Consortium.
 #
 # Permission to use, copy, modify, and distribute this software for any
 # purpose with or without fee is hereby granted, provided that the above
@@ -535,9 +535,11 @@ class TestStats2(unittest.TestCase):
         Test for specfile
         
         """
-        if "B10_FROM_BUILD" in os.environ:
+        if "B10_FROM_SOURCE" in os.environ:
             self.assertEqual(stats.SPECFILE_LOCATION,
-                             os.environ["B10_FROM_BUILD"] + "/src/bin/stats/stats.spec")
+                             os.environ["B10_FROM_SOURCE"] + os.sep + \
+                                 "src" + os.sep + "bin" + os.sep + "stats" + \
+                                 os.sep + "stats.spec")
         imp.reload(stats)
         # change path of SPECFILE_LOCATION
         stats.SPECFILE_LOCATION = TEST_SPECFILE_LOCATION
@@ -631,13 +633,13 @@ class TestStats2(unittest.TestCase):
 
     def test_osenv(self):
         """
-        test for not having environ "B10_FROM_BUILD"
+        test for not having environ "B10_FROM_SOURCE"
         """
-        if "B10_FROM_BUILD" in os.environ:
-            path = os.environ["B10_FROM_BUILD"]
-            os.environ.pop("B10_FROM_BUILD")
+        if "B10_FROM_SOURCE" in os.environ:
+            path = os.environ["B10_FROM_SOURCE"]
+            os.environ.pop("B10_FROM_SOURCE")
             imp.reload(stats)
-            os.environ["B10_FROM_BUILD"] = path
+            os.environ["B10_FROM_SOURCE"] = path
             imp.reload(stats)
 
 def result_ok(*args):
diff --git a/src/bin/stats/tests/fake_select.py b/src/bin/stats/tests/fake_select.py
new file mode 100644
index 0000000..ca0ca82
--- /dev/null
+++ b/src/bin/stats/tests/fake_select.py
@@ -0,0 +1,43 @@
+# Copyright (C) 2011  Internet Systems Consortium.
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SYSTEMS CONSORTIUM
+# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+# INTERNET SYSTEMS CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+# FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+"""
+A mock-up module of select
+
+*** NOTE ***
+It is only for testing stats_httpd module and not reusable for
+external module.
+"""
+
+import fake_socket
+import errno
+
+class error(Exception):
+    pass
+
+def select(rlst, wlst, xlst, timeout):
+    if type(timeout) != int and type(timeout) != float:
+            raise TypeError("Error: %s must be integer or float"
+                            % timeout.__class__.__name__)
+    for s in rlst + wlst + xlst:
+        if type(s) != fake_socket.socket:
+            raise TypeError("Error: %s must be a dummy socket"
+                            % s.__class__.__name__)
+        s._called = s._called + 1
+        if s._called > 3:
+            raise error("Something is happened!")
+        elif s._called > 2:
+            raise error(errno.EINTR)
+    return (rlst, wlst, xlst)
diff --git a/src/bin/stats/tests/fake_socket.py b/src/bin/stats/tests/fake_socket.py
new file mode 100644
index 0000000..4e3a458
--- /dev/null
+++ b/src/bin/stats/tests/fake_socket.py
@@ -0,0 +1,70 @@
+# Copyright (C) 2011  Internet Systems Consortium.
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SYSTEMS CONSORTIUM
+# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+# INTERNET SYSTEMS CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+# FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+"""
+A mock-up module of socket
+
+*** NOTE ***
+It is only for testing stats_httpd module and not reusable for
+external module.
+"""
+
+import re
+
+AF_INET = 'AF_INET'
+AF_INET6 = 'AF_INET6'
+_ADDRFAMILY = AF_INET
+has_ipv6 = True
+_CLOSED = False
+
+class gaierror(Exception):
+    pass
+
+class error(Exception):
+    pass
+
+class socket:
+
+    def __init__(self, family=None):
+        if family is None:
+            self.address_family = _ADDRFAMILY
+        else:
+            self.address_family = family
+        self._closed = _CLOSED
+        if self._closed:
+            raise error('socket is already closed!')
+        self._called = 0
+
+    def close(self):
+        self._closed = True
+
+    def fileno(self):
+        return id(self)
+
+    def bind(self, server_class):
+        (self.server_address, self.server_port) = server_class
+        if self.address_family not in set([AF_INET, AF_INET6]):
+            raise error("Address family not supported by protocol: %s" % self.address_family)
+        if self.address_family == AF_INET6 and not has_ipv6:
+            raise error("Address family not supported in this machine: %s has_ipv6: %s"
+                        % (self.address_family, str(has_ipv6)))
+        if self.address_family == AF_INET and re.search(':', self.server_address) is not None:
+            raise gaierror("Address family for hostname not supported : %s %s" % (self.server_address, self.address_family))
+        if self.address_family == AF_INET6 and re.search(':', self.server_address) is None:
+            raise error("Cannot assign requested address : %s" % str(self.server_address))
+        if type(self.server_port) is not int:
+            raise TypeError("an integer is required: %s" % str(self.server_port))
+        if self.server_port < 0 or self.server_port > 65535:
+            raise OverflowError("port number must be 0-65535.: %s" % str(self.server_port))
diff --git a/src/bin/stats/tests/http/Makefile.am b/src/bin/stats/tests/http/Makefile.am
new file mode 100644
index 0000000..879e8a8
--- /dev/null
+++ b/src/bin/stats/tests/http/Makefile.am
@@ -0,0 +1,2 @@
+EXTRA_DIST = __init__.py server.py
+CLEANFILES = __init__.pyc server.pyc
diff --git a/src/bin/stats/tests/http/__init__.py b/src/bin/stats/tests/http/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/src/bin/stats/tests/http/server.py b/src/bin/stats/tests/http/server.py
new file mode 100644
index 0000000..70ed6fa
--- /dev/null
+++ b/src/bin/stats/tests/http/server.py
@@ -0,0 +1,96 @@
+# Copyright (C) 2011  Internet Systems Consortium.
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SYSTEMS CONSORTIUM
+# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+# INTERNET SYSTEMS CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+# FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+"""
+A mock-up module of http.server
+
+*** NOTE ***
+It is only for testing stats_httpd module and not reusable for
+external module.
+"""
+
+import fake_socket
+
+class DummyHttpResponse:
+    def __init__(self, path):
+        self.path = path
+        self.headers={}
+        self.log = ""
+
+    def _write_log(self, msg):
+        self.log = self.log + msg
+
+class HTTPServer:
+    """
+    A mock-up class of http.server.HTTPServer
+    """
+    address_family = fake_socket.AF_INET
+    def __init__(self, server_class, handler_class):
+        self.socket = fake_socket.socket(self.address_family)
+        self.server_class = server_class
+        self.socket.bind(self.server_class)
+        self._handler = handler_class(None, None, self)
+
+    def handle_request(self):
+        pass
+
+    def server_close(self):
+        self.socket.close()
+
+class BaseHTTPRequestHandler:
+    """
+    A mock-up class of http.server.BaseHTTPRequestHandler
+    """
+
+    def __init__(self, request, client_address, server):
+        self.path = "/path/to"
+        self.headers = {}
+        self.server = server
+        self.response = DummyHttpResponse(path=self.path)
+        self.response.write = self._write
+        self.wfile = self.response
+
+    def send_response(self, code=0):
+        if self.path != self.response.path:
+            self.response = DummyHttpResponse(path=self.path)
+        self.response.code = code
+
+    def send_header(self, key, value):
+        if self.path != self.response.path:
+            self.response = DummyHttpResponse(path=self.path)
+        self.response.headers[key] = value
+
+    def end_headers(self):
+        if self.path != self.response.path:
+            self.response = DummyHttpResponse(path=self.path)
+        self.response.wrote_headers = True
+
+    def send_error(self, code, message=None):
+        if self.path != self.response.path:
+            self.response = DummyHttpResponse(path=self.path)
+        self.response.code = code
+        self.response.body = message
+
+    def address_string(self):
+        return 'dummyhost'
+
+    def log_date_time_string(self):
+        return '[DD/MM/YYYY HH:MI:SS]'
+
+    def _write(self, obj):
+        if self.path != self.response.path:
+            self.response = DummyHttpResponse(path=self.path)
+        self.response.body = obj.decode()
+
diff --git a/src/bin/stats/tests/isc/cc/session.py b/src/bin/stats/tests/isc/cc/session.py
index 4d12adc..e16d6a9 100644
--- a/src/bin/stats/tests/isc/cc/session.py
+++ b/src/bin/stats/tests/isc/cc/session.py
@@ -1,4 +1,4 @@
-# Copyright (C) 2010  Internet Systems Consortium.
+# Copyright (C) 2010,2011  Internet Systems Consortium.
 #
 # Permission to use, copy, modify, and distribute this software for any
 # purpose with or without fee is hereby granted, provided that the above
@@ -13,11 +13,16 @@
 # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
 # WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
-# This module is a mock-up class of isc.cc.session
+"""
+A mock-up module of isc.cc.session
 
-__version__ = "$Revision$"
+*** NOTE ***
+It is only for testing stats_httpd module and not reusable for
+external module.
+"""
 
 import sys
+import fake_socket
 
 # set a dummy lname
 _TEST_LNAME = '123abc at xxxx'
@@ -33,12 +38,18 @@ class Queue():
 class SessionError(Exception):
     pass
 
+class SessionTimeout(Exception):
+    pass
+
 class Session:
     def __init__(self, socket_file=None, verbose=False):
         self._lname = _TEST_LNAME
         self.message_queue = []
         self.old_message_queue = []
-        self._socket = True
+        try:
+            self._socket = fake_socket.socket()
+        except fake_socket.error as se:
+            raise SessionError(se)
         self.verbose = verbose
 
     @property
@@ -46,13 +57,17 @@ class Session:
         return self._lname
 
     def close(self):
-        self._socket = False
+        self._socket.close()
+
+    def _clear_queues(self):
+        while len(self.message_queue) > 0:
+            self.dequeue()
 
     def _next_sequence(self, que=None):
         return len(self.message_queue)
 
     def enqueue(self, msg=None, env={}):
-        if not self._socket:
+        if self._socket._closed:
             raise SessionError("Session has been closed.")
         seq = self._next_sequence()
         env.update({"seq": 0}) # fixed here
@@ -62,12 +77,12 @@ class Session:
             sys.stdout.write("[Session] enqueue: " + str(que.dump()) + "\n")
         return seq
 
-    def dequeue(self, seq=0):
-        if not self._socket:
+    def dequeue(self):
+        if self._socket._closed:
             raise SessionError("Session has been closed.")
         que = None
         try:
-            que = self.message_queue.pop(seq)
+            que = self.message_queue.pop(0) # always pop at index 0
             self.old_message_queue.append(que)
         except IndexError:
             que = Queue()
@@ -76,7 +91,7 @@ class Session:
         return que
 
     def get_queue(self, seq=None):
-        if not self._socket:
+        if self._socket._closed:
             raise SessionError("Session has been closed.")
         if seq is None:
             seq = len(self.message_queue) - 1
@@ -99,7 +114,7 @@ class Session:
                 "instance": instance })
 
     def group_recvmsg(self, nonblock=True, seq=0):
-        que = self.dequeue(seq)
+        que = self.dequeue()
         return que.msg, que.env
         
     def group_reply(self, routing, msg):
@@ -112,7 +127,7 @@ class Session:
                 "reply": routing["seq"] })
 
     def get_message(self, group, to='*'):
-        if not self._socket:
+        if self._socket._closed:
             raise SessionError("Session has been closed.")
         que = Queue()
         for q in self.message_queue:
@@ -124,3 +139,10 @@ class Session:
             sys.stdout.write("[Session] get_message: " + str(que.dump()) + "\n")
         return q.msg
 
+    def group_subscribe(self, group, instance = "*"):
+        if self._socket._closed:
+            raise SessionError("Session has been closed.")
+
+    def group_unsubscribe(self, group, instance = "*"):
+        if self._socket._closed:
+            raise SessionError("Session has been closed.")
diff --git a/src/bin/stats/tests/isc/config/ccsession.py b/src/bin/stats/tests/isc/config/ccsession.py
index fc285a7..a4e9c37 100644
--- a/src/bin/stats/tests/isc/config/ccsession.py
+++ b/src/bin/stats/tests/isc/config/ccsession.py
@@ -1,4 +1,4 @@
-# Copyright (C) 2010  Internet Systems Consortium.
+# Copyright (C) 2010,2011  Internet Systems Consortium.
 #
 # Permission to use, copy, modify, and distribute this software for any
 # purpose with or without fee is hereby granted, provided that the above
@@ -13,16 +13,22 @@
 # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
 # WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
-# This module is a mock-up class of isc.cc.session
+"""
+A mock-up module of isc.cc.session
 
-__version__ = "$Revision$"
+*** NOTE ***
+It is only for testing stats_httpd module and not reusable for
+external module.
+"""
 
 import json
+import os
 from isc.cc.session import Session
 
 COMMAND_CONFIG_UPDATE = "config_update"
 
 def parse_answer(msg):
+    assert 'result' in msg
     try:
         return msg['result'][0], msg['result'][1]
     except IndexError:
@@ -35,6 +41,7 @@ def create_answer(rcode, arg = None):
         return { 'result': [ rcode, arg ] }
 
 def parse_command(msg):
+    assert 'command' in msg
     try:
         return msg['command'][0], msg['command'][1]
     except IndexError:
@@ -47,9 +54,21 @@ def create_command(command_name, params = None):
         return {"command": [command_name, params]}
 
 def module_spec_from_file(spec_file, check = True):
-    file = open(spec_file)
-    module_spec = json.loads(file.read())
-    return ModuleSpec(module_spec['module_spec'], check)
+    try:
+        file = open(spec_file)
+        json_str = file.read()
+        module_spec = json.loads(json_str)
+        file.close()
+        return ModuleSpec(module_spec['module_spec'], check)
+    except IOError as ioe:
+        raise ModuleSpecError("JSON read error: " + str(ioe))
+    except ValueError as ve:
+        raise ModuleSpecError("JSON parse error: " + str(ve))
+    except KeyError as err:
+        raise ModuleSpecError("Data definition has no module_spec element")
+
+class ModuleSpecError(Exception):
+    pass
 
 class ModuleSpec:
     def __init__(self, module_spec, check = True):
@@ -67,10 +86,34 @@ class ModuleSpec:
 class ModuleCCSessionError(Exception):
     pass
 
+class DataNotFoundError(Exception):
+    pass
+
 class ConfigData:
     def __init__(self, specification):
         self.specification = specification
 
+    def get_value(self, identifier):
+        """Returns a tuple where the first item is the value at the
+           given identifier, and the second item is absolutely False
+           even if the value is an unset default or not. Raises an
+           DataNotFoundError if the identifier is not found in the
+           specification file.
+           *** NOTE ***
+           There are some differences from the original method. This
+           method never handles local settings like the original
+           method. But these different behaviors aren't so big issues
+           for a mock-up method of stats_httpd because stats_httpd
+           calls this method at only first."""
+        for config_map in self.get_module_spec().get_config_spec():
+            if config_map['item_name'] == identifier:
+                if 'item_default' in config_map:
+                    return config_map['item_default'], False
+        raise DataNotFoundError("item_name %s is not found in the specfile" % identifier)
+
+    def get_module_spec(self):
+        return self.specification
+
 class ModuleCCSession(ConfigData):
     def __init__(self, spec_file_name, config_handler, command_handler, cc_session = None):
         module_spec = module_spec_from_file(spec_file_name)
@@ -111,3 +154,7 @@ class ModuleCCSession(ConfigData):
 
     def get_module_spec(self):
         return self.specification
+
+    def get_socket(self):
+        return self._session._socket
+
diff --git a/src/bin/stats/tests/isc/util/process.py b/src/bin/stats/tests/isc/util/process.py
index 7274a48..0f764c1 100644
--- a/src/bin/stats/tests/isc/util/process.py
+++ b/src/bin/stats/tests/isc/util/process.py
@@ -13,6 +13,9 @@
 # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
 # WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
-# A dummy function of isc.util.process.rename()
+"""
+A dummy function of isc.util.process.rename()
+"""
+
 def rename(name=None):
     pass
diff --git a/src/bin/stats/tests/isc/utils/Makefile.am b/src/bin/stats/tests/isc/utils/Makefile.am
deleted file mode 100644
index b09fdee..0000000
--- a/src/bin/stats/tests/isc/utils/Makefile.am
+++ /dev/null
@@ -1,2 +0,0 @@
-EXTRA_DIST = __init__.py process.py
-CLEANFILES = __init__.pyc process.pyc
diff --git a/src/bin/stats/tests/isc/utils/__init__.py b/src/bin/stats/tests/isc/utils/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/src/bin/stats/tests/isc/utils/process.py b/src/bin/stats/tests/isc/utils/process.py
deleted file mode 100644
index 4c0cf8c..0000000
--- a/src/bin/stats/tests/isc/utils/process.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# Copyright (C) 2010  Internet Systems Consortium.
-#
-# Permission to use, copy, modify, and distribute this software for any
-# purpose with or without fee is hereby granted, provided that the above
-# copyright notice and this permission notice appear in all copies.
-#
-# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SYSTEMS CONSORTIUM
-# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
-# INTERNET SYSTEMS CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
-# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
-# FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
-# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
-# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-# A dummy function of isc.utils.process.rename()
-def rename(name=None):
-    pass
diff --git a/src/bin/stats/tests/stats_test.in b/src/bin/stats/tests/stats_test.in
deleted file mode 100644
index a3279a7..0000000
--- a/src/bin/stats/tests/stats_test.in
+++ /dev/null
@@ -1,31 +0,0 @@
-#! /bin/sh
-
-# Copyright (C) 2010  Internet Systems Consortium.
-#
-# Permission to use, copy, modify, and distribute this software for any
-# purpose with or without fee is hereby granted, provided that the above
-# copyright notice and this permission notice appear in all copies.
-#
-# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SYSTEMS CONSORTIUM
-# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
-# INTERNET SYSTEMS CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
-# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
-# FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
-# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
-# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-PYTHON_EXEC=${PYTHON_EXEC:- at PYTHON@}
-export PYTHON_EXEC
-
-PYTHONPATH=@abs_top_builddir@/src/lib/python:@abs_top_srcdir@/src/bin/stats:@abs_top_srcdir@/src/bin/stats/tests
-export PYTHONPATH
-
-B10_FROM_BUILD=@abs_top_builddir@
-export B10_FROM_BUILD
-
-TEST_PATH=@abs_top_srcdir@/src/bin/stats/tests
-
-cd ${TEST_PATH}
-${PYTHON_EXEC} -O b10-stats_test.py $*
-${PYTHON_EXEC} -O b10-stats_stub_test.py $*
diff --git a/src/bin/xfrin/tests/Makefile.am b/src/bin/xfrin/tests/Makefile.am
index dfa7714..d4efbc7 100644
--- a/src/bin/xfrin/tests/Makefile.am
+++ b/src/bin/xfrin/tests/Makefile.am
@@ -6,7 +6,7 @@ EXTRA_DIST = $(PYTESTS)
 # required by loadable python modules.
 LIBRARY_PATH_PLACEHOLDER =
 if SET_ENV_LIBRARY_PATH
-LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/dns/.libs:$(abs_top_builddir)/src/lib/util/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs:$(abs_top_builddir)/src/lib/xfr/.libs:$$$(ENV_LIBRARY_PATH)
+LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/dns/.libs:$(abs_top_builddir)/src/lib/cryptolink/.libs:$(abs_top_builddir)/src/lib/util/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs:$(abs_top_builddir)/src/lib/xfr/.libs:$$$(ENV_LIBRARY_PATH)
 endif
 
 # test using command-line arguments, so use check-local target instead of TESTS
diff --git a/src/bin/xfrin/tests/xfrin_test.py b/src/bin/xfrin/tests/xfrin_test.py
index 04d04a6..0ccbbb8 100644
--- a/src/bin/xfrin/tests/xfrin_test.py
+++ b/src/bin/xfrin/tests/xfrin_test.py
@@ -35,6 +35,8 @@ TEST_MASTER_IPV6_ADDRINFO = (socket.AF_INET6, socket.SOCK_STREAM,
 # If some other process uses this port test will fail.
 TEST_MASTER_PORT = '53535'
 
+TSIG_KEY = TSIGKey("example.com:SFuWd/q99SzF8Yzd1QbB9g==")
+
 soa_rdata = Rdata(RRType.SOA(), TEST_RRCLASS,
                   'master.example.com. admin.example.com ' +
                   '1234 3600 1800 2419200 7200')
@@ -51,6 +53,13 @@ default_answers = [soa_rrset]
 class XfrinTestException(Exception):
     pass
 
+def strip_mutable_tsig_data(data):
+    # Unfortunately we cannot easily compare TSIG RR because we can't tweak
+    # current time.  As a work around this helper function strips off the time
+    # dependent part of TSIG RDATA, i.e., the MAC (assuming HMAC-MD5) and
+    # Time Signed.
+    return data[0:-32] + data[-26:-22] + data[-6:]
+
 class MockXfrin(Xfrin):
     # This is a class attribute of a callable object that specifies a non
     # default behavior triggered in _cc_check_command().  Specific test methods
@@ -60,6 +69,7 @@ class MockXfrin(Xfrin):
     check_command_hook = None
 
     def _cc_setup(self):
+        self._tsig_key_str = None
         pass
 
     def _get_db_file(self):
@@ -196,10 +206,46 @@ class TestXfrinConnection(unittest.TestCase):
                          RRClass.CH())
         c.close()
 
+    def test_send_query(self):
+        def create_msg(query_type):
+            msg = Message(Message.RENDER)
+            query_id = 0x1035
+            msg.set_qid(query_id)
+            msg.set_opcode(Opcode.QUERY())
+            msg.set_rcode(Rcode.NOERROR())
+            query_question = Question(Name("example.com."), RRClass.IN(), query_type)
+            msg.add_question(query_question)
+            return msg
+        self.conn._create_query = create_msg
+        # soa request
+        self.conn._send_query(RRType.SOA())
+        self.assertEqual(self.conn.query_data, b'\x00\x1d\x105\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x07example\x03com\x00\x00\x06\x00\x01')
+        # axfr request
+        self.conn._send_query(RRType.AXFR())
+        self.assertEqual(self.conn.query_data, b'\x00\x1d\x105\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x07example\x03com\x00\x00\xfc\x00\x01')
+
+        # soa request with tsig
+        self.conn._tsig_ctx = TSIGContext(TSIG_KEY)
+        self.conn._send_query(RRType.SOA())
+        tsig_soa_data = strip_mutable_tsig_data(self.conn.query_data)
+        self.assertEqual(tsig_soa_data, b'\x00n\x105\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x07example\x03com\x00\x00\x06\x00\x01\x07example\x03com\x00\x00\xfa\x00\xff\x00\x00\x00\x00\x00:\x08hmac-md5\x07sig-alg\x03reg\x03int\x00\x01,\x00\x10\x105\x00\x00\x00\x00')
+
+        # axfr request with tsig
+        self.conn._send_query(RRType.AXFR())
+        tsig_axfr_data = strip_mutable_tsig_data(self.conn.query_data)
+        self.assertEqual(tsig_axfr_data, b'\x00n\x105\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x07example\x03com\x00\x00\xfc\x00\x01\x07example\x03com\x00\x00\xfa\x00\xff\x00\x00\x00\x00\x00:\x08hmac-md5\x07sig-alg\x03reg\x03int\x00\x01,\x00\x10\x105\x00\x00\x00\x00')
+
     def test_response_with_invalid_msg(self):
         self.conn.reply_data = b'aaaxxxx'
         self.assertRaises(XfrinTestException, self._handle_xfrin_response)
 
+    def test_response_with_tsig(self):
+        self.conn._tsig_ctx = TSIGContext(TSIG_KEY)
+        # server tsig check fail, return with RCODE 9 (NOTAUTH)
+        self.conn._send_query(RRType.SOA())
+        self.conn.reply_data = self.conn.create_response_data(rcode=Rcode.NOTAUTH())
+        self.assertRaises(XfrinException, self._handle_xfrin_response)
+
     def test_response_without_end_soa(self):
         self.conn._send_query(RRType.AXFR())
         self.conn.reply_data = self.conn.create_response_data()
@@ -399,15 +445,20 @@ class TestXfrinRecorder(unittest.TestCase):
 
 class TestXfrin(unittest.TestCase):
     def setUp(self):
+        # redirect output
+        self.stderr_backup = sys.stderr
+        sys.stderr = open(os.devnull, 'w')
         self.xfr = MockXfrin()
         self.args = {}
         self.args['zone_name'] = TEST_ZONE_NAME
         self.args['port'] = TEST_MASTER_PORT
         self.args['master'] = TEST_MASTER_IPV4_ADDRESS
         self.args['db_file'] = TEST_DB_FILE
+        self.args['tsig_key'] = ''
 
     def tearDown(self):
         self.xfr.shutdown()
+        sys.stderr= self.stderr_backup
 
     def _do_parse_zone_name_class(self):
         return self.xfr._parse_zone_name_and_class(self.args)
diff --git a/src/bin/xfrin/xfrin.py.in b/src/bin/xfrin/xfrin.py.in
index 10a866e..1bf46c1 100755
--- a/src/bin/xfrin/xfrin.py.in
+++ b/src/bin/xfrin/xfrin.py.in
@@ -67,15 +67,16 @@ DEFAULT_MASTER = '127.0.0.1'
 def log_error(msg):
     sys.stderr.write("[b10-xfrin] %s\n" % str(msg))
 
-class XfrinException(Exception): 
+class XfrinException(Exception):
     pass
 
 class XfrinConnection(asyncore.dispatcher):
-    '''Do xfrin in this class. '''    
+    '''Do xfrin in this class. '''
 
     def __init__(self,
                  sock_map, zone_name, rrclass, db_file, shutdown_event,
-                 master_addrinfo, verbose = False, idle_timeout = 60): 
+                 master_addrinfo, tsig_key_str = None, verbose = False,
+                 idle_timeout = 60):
         ''' idle_timeout: max idle time for read data from socket.
             db_file: specify the data source file.
             check_soa: when it's true, check soa first before sending xfr query
@@ -93,6 +94,9 @@ class XfrinConnection(asyncore.dispatcher):
         self._shutdown_event = shutdown_event
         self._verbose = verbose
         self._master_address = master_addrinfo[2]
+        self._tsig_ctx = None
+        if tsig_key_str is not None:
+            self._tsig_ctx = TSIGContext(TSIGKey(tsig_key_str))
 
     def connect_to_master(self):
         '''Connect to master in TCP.'''
@@ -130,9 +134,14 @@ class XfrinConnection(asyncore.dispatcher):
 
         msg = self._create_query(query_type)
         render = MessageRenderer()
-        msg.to_wire(render)
-        header_len = struct.pack('H', socket.htons(render.get_length()))
+        # XXX Currently, python wrapper doesn't accept 'None' parameter in this case,
+        # we should remove the if statement and use a universal interface later.
+        if self._tsig_ctx is not None:
+            msg.to_wire(render, self._tsig_ctx)
+        else:
+            msg.to_wire(render)
 
+        header_len = struct.pack('H', socket.htons(render.get_length()))
         self._send_data(header_len)
         self._send_data(render.get_data())
 
@@ -142,7 +151,7 @@ class XfrinConnection(asyncore.dispatcher):
         _get_request_response so that we can test the rest of the code without
         involving actual communication with a remote server.'''
         asyncore.loop(self._idle_timeout, map=self._sock_map, count=1)
-    
+
     def _get_request_response(self, size):
         recv_size = 0
         data = b''
@@ -176,7 +185,7 @@ class XfrinConnection(asyncore.dispatcher):
         # strict we should be (see the comment in _check_response_header())
         self._check_response_header(msg)
 
-        # TODO, need select soa record from data source then compare the two 
+        # TODO, need select soa record from data source then compare the two
         # serial, current just return OK, since this function hasn't been used
         # now.
         return XFRIN_OK
@@ -290,14 +299,14 @@ class XfrinConnection(asyncore.dispatcher):
             msg = Message(Message.PARSE)
             msg.from_wire(recvdata)
             self._check_response_status(msg)
-            
+
             answer_section = msg.get_section(Message.SECTION_ANSWER)
             for rr in self._handle_answer_section(answer_section):
                 yield rr
 
             if self._soa_rr_count == 2:
                 break
-            
+
             if self._shutdown_event.is_set():
                 raise XfrinException('xfrin is forced to stop')
 
@@ -322,16 +331,18 @@ class XfrinConnection(asyncore.dispatcher):
             sys.stdout.write('[b10-xfrin] %s\n' % str(msg))
 
 
-def process_xfrin(server, xfrin_recorder, zone_name, rrclass, db_file, 
-                  shutdown_event, master_addrinfo, check_soa, verbose):
+def process_xfrin(server, xfrin_recorder, zone_name, rrclass, db_file,
+                  shutdown_event, master_addrinfo, check_soa, verbose,
+                  tsig_key_str):
     xfrin_recorder.increment(zone_name)
     sock_map = {}
     conn = XfrinConnection(sock_map, zone_name, rrclass, db_file,
-                           shutdown_event, master_addrinfo, verbose)
+                           shutdown_event, master_addrinfo,
+                           tsig_key_str, verbose)
     ret = XFRIN_FAIL
     if conn.connect_to_master():
         ret = conn.do_xfrin(check_soa)
-    
+
     # Publish the zone transfer result news, so zonemgr can reset the
     # zone timer, and xfrout can notify the zone's slaves if the result
     # is success.
@@ -379,11 +390,11 @@ class Xfrin:
         self._verbose = verbose
 
     def _cc_setup(self):
-        '''This method is used only as part of initialization, but is 
-        implemented separately for convenience of unit tests; by letting 
-        the test code override this method we can test most of this class 
+        '''This method is used only as part of initialization, but is
+        implemented separately for convenience of unit tests; by letting
+        the test code override this method we can test most of this class
         without requiring a command channel.'''
-        # Create one session for sending command to other modules, because the 
+        # Create one session for sending command to other modules, because the
         # listening session will block the send operation.
         self._send_cc_session = isc.cc.Session()
         self._module_cc = isc.config.ModuleCCSession(SPECFILE_LOCATION,
@@ -394,15 +405,17 @@ class Xfrin:
         self._max_transfers_in = config_data.get("transfers_in")
         self._master_addr = config_data.get('master_addr') or self._master_addr
         self._master_port = config_data.get('master_port') or self._master_port
+        self._tsig_key_str = config_data.get('tsig_key') or None
 
     def _cc_check_command(self):
-        '''This is a straightforward wrapper for cc.check_command, 
-        but provided as a separate method for the convenience 
+        '''This is a straightforward wrapper for cc.check_command,
+        but provided as a separate method for the convenience
         of unit tests.'''
         self._module_cc.check_command(False)
 
     def config_handler(self, new_config):
         self._max_transfers_in = new_config.get("transfers_in") or self._max_transfers_in
+        self._tsig_key_str = new_config.get('tsig_key') or None
         if ('master_addr' in new_config) or ('master_port' in new_config):
             # User should change the port and address together.
             try:
@@ -420,7 +433,7 @@ class Xfrin:
         return create_answer(0)
 
     def shutdown(self):
-        ''' shutdown the xfrin process. the thread which is doing xfrin should be 
+        ''' shutdown the xfrin process. the thread which is doing xfrin should be
         terminated.
         '''
         self._shutdown_event.set()
@@ -436,30 +449,32 @@ class Xfrin:
             if command == 'shutdown':
                 self._shutdown_event.set()
             elif command == 'notify' or command == REFRESH_FROM_ZONEMGR:
-                # Xfrin receives the refresh/notify command from zone manager. 
-                # notify command maybe has the parameters which 
+                # Xfrin receives the refresh/notify command from zone manager.
+                # notify command maybe has the parameters which
                 # specify the notifyfrom address and port, according the RFC1996, zone
                 # transfer should starts first from the notifyfrom, but now, let 'TODO' it.
                 (zone_name, rrclass) = self._parse_zone_name_and_class(args)
                 (master_addr) = build_addr_info(self._master_addr, self._master_port)
-                ret = self.xfrin_start(zone_name, 
-                                       rrclass, 
+                ret = self.xfrin_start(zone_name,
+                                       rrclass,
                                        self._get_db_file(),
                                        master_addr,
+                                       self._tsig_key_str,
                                        True)
                 answer = create_answer(ret[0], ret[1])
 
             elif command == 'retransfer' or command == 'refresh':
                 # Xfrin receives the retransfer/refresh from cmdctl(sent by bindctl).
-                # If the command has specified master address, do transfer from the 
-                # master address, or else do transfer from the configured masters.                
+                # If the command has specified master address, do transfer from the
+                # master address, or else do transfer from the configured masters.
                 (zone_name, rrclass) = self._parse_zone_name_and_class(args)
                 master_addr = self._parse_master_and_port(args)
                 db_file = args.get('db_file') or self._get_db_file()
-                ret = self.xfrin_start(zone_name, 
-                                       rrclass, 
-                                       db_file, 
+                ret = self.xfrin_start(zone_name,
+                                       rrclass,
+                                       db_file,
                                        master_addr,
+                                       self._tsig_key_str,
                                        (False if command == 'retransfer' else True))
                 answer = create_answer(ret[0], ret[1])
 
@@ -483,14 +498,14 @@ class Xfrin:
                 rrclass = RRClass(rrclass)
             except InvalidRRClass as e:
                 raise XfrinException('invalid RRClass: ' + rrclass)
-        
+
         return zone_name, rrclass
 
     def _parse_master_and_port(self, args):
         port = args.get('port') or self._master_port
         master = args.get('master') or self._master_addr
         return build_addr_info(master, port)
- 
+
     def _get_db_file(self):
         #TODO, the db file path should be got in auth server's configuration
         # if we need access to this configuration more often, we
@@ -506,12 +521,12 @@ class Xfrin:
             db_file = os.environ["B10_FROM_BUILD"] + os.sep + "bind10_zones.sqlite3"
         self._module_cc.remove_remote_config(AUTH_SPECFILE_LOCATION)
         return db_file
-       
+
     def publish_xfrin_news(self, zone_name, zone_class,  xfr_result):
         '''Send command to xfrout/zone manager module.
-        If xfrin has finished successfully for one zone, tell the good 
+        If xfrin has finished successfully for one zone, tell the good
         news(command: zone_new_data_ready) to zone manager and xfrout.
-        if xfrin failed, just tell the bad news to zone manager, so that 
+        if xfrin failed, just tell the bad news to zone manager, so that
         it can reset the refresh timer for that zone. '''
         param = {'zone_name': zone_name, 'zone_class': zone_class.to_text()}
         if xfr_result == XFRIN_OK:
@@ -531,8 +546,8 @@ class Xfrin:
                                                                       seq)
                 except isc.cc.session.SessionTimeout:
                     pass        # for now we just ignore the failure
-            except socket.error as err: 
-                log_error("Fail to send message to %s and %s, msgq may has been killed" 
+            except socket.error as err:
+                log_error("Fail to send message to %s and %s, msgq may has been killed"
                           % (XFROUT_MODULE_NAME, ZONE_MANAGER_MODULE_NAME))
         else:
             msg = create_command(ZONE_XFRIN_FAILED, param)
@@ -545,14 +560,14 @@ class Xfrin:
                 except isc.cc.session.SessionTimeout:
                     pass        # for now we just ignore the failure
             except socket.error as err:
-                log_error("Fail to send message to %s, msgq may has been killed" 
+                log_error("Fail to send message to %s, msgq may has been killed"
                           % ZONE_MANAGER_MODULE_NAME)
 
     def startup(self):
         while not self._shutdown_event.is_set():
             self._cc_check_command()
 
-    def xfrin_start(self, zone_name, rrclass, db_file, master_addrinfo,
+    def xfrin_start(self, zone_name, rrclass, db_file, master_addrinfo, tsig_key_str,
                     check_soa = True):
         if "pydnspp" not in sys.modules:
             return (1, "xfrin failed, can't load dns message python library: 'pydnspp'")
@@ -571,7 +586,8 @@ class Xfrin:
                                                 db_file,
                                                 self._shutdown_event,
                                                 master_addrinfo, check_soa,
-                                                self._verbose))
+                                                self._verbose,
+                                                tsig_key_str))
 
         xfrin_thread.start()
         return (0, 'zone xfrin is started')
diff --git a/src/bin/xfrin/xfrin.spec b/src/bin/xfrin/xfrin.spec
index 61ddaad..46bad69 100644
--- a/src/bin/xfrin/xfrin.spec
+++ b/src/bin/xfrin/xfrin.spec
@@ -19,6 +19,11 @@
         "item_type": "integer",
         "item_optional": false,
         "item_default": 53
+      },
+      { "item_name": "tsig_key",
+        "item_type": "string",
+        "item_optional": true,
+        "item_default": ""
       }
     ],
     "commands": [
diff --git a/src/bin/xfrout/tests/Makefile.am b/src/bin/xfrout/tests/Makefile.am
index 1ec3c06..11916af 100644
--- a/src/bin/xfrout/tests/Makefile.am
+++ b/src/bin/xfrout/tests/Makefile.am
@@ -6,7 +6,7 @@ EXTRA_DIST = $(PYTESTS)
 # required by loadable python modules.
 LIBRARY_PATH_PLACEHOLDER =
 if SET_ENV_LIBRARY_PATH
-LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/dns/.libs:$(abs_top_builddir)/src/lib/util/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs:$(abs_top_builddir)/src/lib/util/io/.libs:$$$(ENV_LIBRARY_PATH)
+LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/dns/.libs:$(abs_top_builddir)/src/lib/cryptolink/.libs:$(abs_top_builddir)/src/lib/util/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs:$(abs_top_builddir)/src/lib/util/io/.libs:$$$(ENV_LIBRARY_PATH)
 endif
 
 # test using command-line arguments, so use check-local target instead of TESTS
diff --git a/src/bin/zonemgr/tests/zonemgr_test.py b/src/bin/zonemgr/tests/zonemgr_test.py
index 2e9f685..c6d151d 100644
--- a/src/bin/zonemgr/tests/zonemgr_test.py
+++ b/src/bin/zonemgr/tests/zonemgr_test.py
@@ -29,8 +29,9 @@ ZONE_NAME_CLASS2_IN = ("tw.cn.", "IN")
 
 MAX_TRANSFER_TIMEOUT = 14400
 LOWERBOUND_REFRESH = 10
-LOWERBOUND_RETRY = 5 
-JITTER_SCOPE = 0.10
+LOWERBOUND_RETRY = 5
+REFRESH_JITTER = 0.10
+RELOAD_JITTER = 0.75
 
 class ZonemgrTestException(Exception):
     pass
@@ -60,8 +61,10 @@ class FakeConfig:
             return LOWERBOUND_RETRY
         elif name == 'max_transfer_timeout':
             return MAX_TRANSFER_TIMEOUT
-        elif name == 'jitter_scope':
-            return JITTER_SCOPE
+        elif name == 'refresh_jitter':
+            return REFRESH_JITTER
+        elif name == 'reload_jitter':
+            return RELOAD_JITTER
         elif name == 'secondary_zones':
             return self.zone_list
         else:
@@ -71,6 +74,10 @@ class MyZonemgrRefresh(ZonemgrRefresh):
     def __init__(self):
         self._master_socket, self._slave_socket = socket.socketpair()
         self._zonemgr_refresh_info = {}
+        self._lowerbound_refresh = 10
+        self._lowerbound_retry = 5
+        self._reload_jitter = 0.75
+        self._refresh_jitter = 0.25
 
         def get_zone_soa(zone_name, db_file):
             if zone_name == 'sd.cn.':
@@ -86,18 +93,18 @@ class MyZonemgrRefresh(ZonemgrRefresh):
         ZonemgrRefresh.__init__(self, MySession(), "initdb.file",
             self._slave_socket, FakeConfig())
         current_time = time.time()
-        self._zonemgr_refresh_info = { 
+        self._zonemgr_refresh_info = {
          ('sd.cn.', 'IN'): {
          'last_refresh_time': current_time,
-         'next_refresh_time': current_time + 6500, 
-         'zone_soa_rdata': 'a.dns.cn. root.cnnic.cn. 2009073105 7200 3600 2419200 21600', 
+         'next_refresh_time': current_time + 6500,
+         'zone_soa_rdata': 'a.dns.cn. root.cnnic.cn. 2009073105 7200 3600 2419200 21600',
          'zone_state': 0},
          ('tw.cn.', 'CH'): {
-         'last_refresh_time': current_time, 
-         'next_refresh_time': current_time + 6900, 
-         'zone_soa_rdata': 'a.dns.cn. root.cnnic.cn. 2009073112 7200 3600 2419200 21600', 
+         'last_refresh_time': current_time,
+         'next_refresh_time': current_time + 6900,
+         'zone_soa_rdata': 'a.dns.cn. root.cnnic.cn. 2009073112 7200 3600 2419200 21600',
          'zone_state': 0}
-        } 
+        }
 
 class TestZonemgrRefresh(unittest.TestCase):
     def setUp(self):
@@ -109,10 +116,10 @@ class TestZonemgrRefresh(unittest.TestCase):
         max = 100025.120
         jitter = 0
         self.assertEqual(max, self.zone_refresh._random_jitter(max, jitter))
-        jitter = max / 4
+        jitter = 0.3 * max
         for i in range (0, 150):
-            self.assertTrue((3 * max / 4) <= self.zone_refresh._random_jitter(max, jitter)) 
-            self.assertTrue(self.zone_refresh._random_jitter(max, jitter) <= max) 
+            self.assertTrue((max - jitter) <= self.zone_refresh._random_jitter(max, jitter))
+            self.assertTrue(self.zone_refresh._random_jitter(max, jitter) <= max)
             i += 1;
 
     def test_get_current_time(self):
@@ -133,7 +140,7 @@ class TestZonemgrRefresh(unittest.TestCase):
         self.zone_refresh._set_zone_refresh_timer(ZONE_NAME_CLASS1_IN)
         zone_timeout = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["next_refresh_time"]
         time2 = time.time()
-        self.assertTrue((time1 + 7200 * 3 / 4) <= zone_timeout)
+        self.assertTrue((time1 + 7200 * (1 - self.zone_refresh._refresh_jitter)) <= zone_timeout)
         self.assertTrue(zone_timeout <= time2 + 7200)
 
     def test_set_zone_retry_timer(self):
@@ -141,7 +148,7 @@ class TestZonemgrRefresh(unittest.TestCase):
         self.zone_refresh._set_zone_retry_timer(ZONE_NAME_CLASS1_IN)
         zone_timeout = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["next_refresh_time"]
         time2 = time.time()
-        self.assertTrue((time1 + 3600 * 3 / 4) <= zone_timeout)
+        self.assertTrue((time1 + 3600 * (1 - self.zone_refresh._refresh_jitter)) <= zone_timeout)
         self.assertTrue(zone_timeout <= time2 + 3600)
 
     def test_zone_not_exist(self):
@@ -172,19 +179,19 @@ class TestZonemgrRefresh(unittest.TestCase):
         self.assertTrue(self.zone_refresh._zone_is_expired(ZONE_NAME_CLASS1_IN))
 
     def test_get_zone_soa_rdata(self):
-        soa_rdata1  = 'a.dns.cn. root.cnnic.cn. 2009073105 7200 3600 2419200 21600' 
-        soa_rdata2  = 'a.dns.cn. root.cnnic.cn. 2009073112 7200 3600 2419200 21600' 
+        soa_rdata1  = 'a.dns.cn. root.cnnic.cn. 2009073105 7200 3600 2419200 21600'
+        soa_rdata2  = 'a.dns.cn. root.cnnic.cn. 2009073112 7200 3600 2419200 21600'
         self.assertEqual(soa_rdata1, self.zone_refresh._get_zone_soa_rdata(ZONE_NAME_CLASS1_IN))
         self.assertRaises(KeyError, self.zone_refresh._get_zone_soa_rdata, ZONE_NAME_CLASS1_CH)
         self.assertEqual(soa_rdata2, self.zone_refresh._get_zone_soa_rdata(ZONE_NAME_CLASS2_CH))
         self.assertRaises(KeyError, self.zone_refresh._get_zone_soa_rdata, ZONE_NAME_CLASS2_IN)
-         
+
     def test_zonemgr_reload_zone(self):
         soa_rdata = 'a.dns.cn. root.cnnic.cn. 2009073106 1800 900 2419200 21600'
         # We need to restore this not to harm other tests
         old_get_zone_soa = sqlite3_ds.get_zone_soa
         def get_zone_soa(zone_name, db_file):
-            return (1, 2, 'sd.cn.', 'cn.sd.', 21600, 'SOA', None, 
+            return (1, 2, 'sd.cn.', 'cn.sd.', 21600, 'SOA', None,
                     'a.dns.cn. root.cnnic.cn. 2009073106 1800 900 2419200 21600')
         sqlite3_ds.get_zone_soa = get_zone_soa
 
@@ -234,7 +241,7 @@ class TestZonemgrRefresh(unittest.TestCase):
         current_time = time.time()
         self.zone_refresh._set_zone_refresh_timeout(ZONE_NAME_CLASS1_IN, current_time)
         refresh_time = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["refresh_timeout"]
-        self.assertEqual(current_time, refresh_time) 
+        self.assertEqual(current_time, refresh_time)
 
     def test_get_zone_next_refresh_time(self):
         current_time = time.time()
@@ -256,14 +263,14 @@ class TestZonemgrRefresh(unittest.TestCase):
         current_time = time.time()
         self.zone_refresh._set_zone_last_refresh_time(ZONE_NAME_CLASS1_IN, current_time)
         last_refresh_time = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["last_refresh_time"]
-        self.assertEqual(current_time, last_refresh_time) 
+        self.assertEqual(current_time, last_refresh_time)
 
     def test_send_command(self):
         self.assertRaises(ZonemgrTestException, self.zone_refresh._send_command, "Unknown", "Notify", None)
 
     def test_zone_mgr_is_empty(self):
         self.assertFalse(self.zone_refresh._zone_mgr_is_empty())
-        self.zone_refresh._zonemgr_refresh_info = {} 
+        self.zone_refresh._zonemgr_refresh_info = {}
         self.assertTrue(self.zone_refresh._zone_mgr_is_empty())
 
     def test_zonemgr_add_zone(self):
@@ -271,9 +278,10 @@ class TestZonemgrRefresh(unittest.TestCase):
         # This needs to be restored. The following test actually failed if we left
         # this unclean
         old_get_zone_soa = sqlite3_ds.get_zone_soa
+        time1 = time.time()
 
         def get_zone_soa(zone_name, db_file):
-            return (1, 2, 'sd.cn.', 'cn.sd.', 21600, 'SOA', None, 
+            return (1, 2, 'sd.cn.', 'cn.sd.', 21600, 'SOA', None,
                     'a.dns.cn. root.cnnic.cn. 2009073106 1800 900 2419200 21600')
 
         sqlite3_ds.get_zone_soa = get_zone_soa
@@ -282,10 +290,14 @@ class TestZonemgrRefresh(unittest.TestCase):
         self.zone_refresh.zonemgr_add_zone(ZONE_NAME_CLASS1_IN)
         self.assertEqual(1, len(self.zone_refresh._zonemgr_refresh_info))
         zone_soa_rdata = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["zone_soa_rdata"]
-        self.assertEqual(soa_rdata, zone_soa_rdata) 
+        self.assertEqual(soa_rdata, zone_soa_rdata)
         self.assertEqual(ZONE_OK, self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["zone_state"])
         self.assertTrue("last_refresh_time" in self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN].keys())
         self.assertTrue("next_refresh_time" in self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN].keys())
+        time2 = time.time()
+        zone_timeout = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["next_refresh_time"]
+        self.assertTrue((time1 + 900 * (1 - self.zone_refresh._reload_jitter)) <= zone_timeout)
+        self.assertTrue(zone_timeout <= time2 + 900)
 
         def get_zone_soa2(zone_name, db_file):
             return None
@@ -297,7 +309,7 @@ class TestZonemgrRefresh(unittest.TestCase):
     def test_zone_handle_notify(self):
         self.zone_refresh.zone_handle_notify(ZONE_NAME_CLASS1_IN,"127.0.0.1")
         notify_master = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["notify_master"]
-        self.assertEqual("127.0.0.1", notify_master) 
+        self.assertEqual("127.0.0.1", notify_master)
         zone_timeout = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["next_refresh_time"]
         current_time = time.time()
         self.assertTrue(zone_timeout <= current_time)
@@ -309,7 +321,7 @@ class TestZonemgrRefresh(unittest.TestCase):
     def test_zone_refresh_success(self):
         soa_rdata = 'a.dns.cn. root.cnnic.cn. 2009073106 1800 900 2419200 21600'
         def get_zone_soa(zone_name, db_file):
-            return (1, 2, 'sd.cn.', 'cn.sd.', 21600, 'SOA', None, 
+            return (1, 2, 'sd.cn.', 'cn.sd.', 21600, 'SOA', None,
                     'a.dns.cn. root.cnnic.cn. 2009073106 1800 900 2419200 21600')
         sqlite3_ds.get_zone_soa = get_zone_soa
         time1 = time.time()
@@ -317,19 +329,19 @@ class TestZonemgrRefresh(unittest.TestCase):
         self.zone_refresh.zone_refresh_success(ZONE_NAME_CLASS1_IN)
         time2 = time.time()
         zone_soa_rdata = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["zone_soa_rdata"]
-        self.assertEqual(soa_rdata, zone_soa_rdata) 
+        self.assertEqual(soa_rdata, zone_soa_rdata)
         next_refresh_time = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["next_refresh_time"]
-        self.assertTrue((time1 + 3 * 1800 / 4) <= next_refresh_time) 
+        self.assertTrue((time1 + 1800 * (1 - self.zone_refresh._refresh_jitter)) <= next_refresh_time)
         self.assertTrue(next_refresh_time <= time2 + 1800)
         self.assertEqual(ZONE_OK, self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["zone_state"])
         last_refresh_time = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["last_refresh_time"]
         self.assertTrue(time1 <= last_refresh_time)
         self.assertTrue(last_refresh_time <= time2)
         self.assertRaises(ZonemgrException, self.zone_refresh.zone_refresh_success, ("org.cn.", "CH"))
-        self.assertRaises(ZonemgrException, self.zone_refresh.zone_refresh_success, ZONE_NAME_CLASS3_IN) 
+        self.assertRaises(ZonemgrException, self.zone_refresh.zone_refresh_success, ZONE_NAME_CLASS3_IN)
 
     def test_zone_refresh_fail(self):
-        soa_rdata = 'a.dns.cn. root.cnnic.cn. 2009073105 7200 3600 2419200 21600' 
+        soa_rdata = 'a.dns.cn. root.cnnic.cn. 2009073105 7200 3600 2419200 21600'
         time1 = time.time()
         self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["zone_state"] = ZONE_REFRESHING
         self.zone_refresh.zone_refresh_fail(ZONE_NAME_CLASS1_IN)
@@ -337,36 +349,36 @@ class TestZonemgrRefresh(unittest.TestCase):
         zone_soa_rdata = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["zone_soa_rdata"]
         self.assertEqual(soa_rdata, zone_soa_rdata)
         next_refresh_time = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["next_refresh_time"]
-        self.assertTrue((time1 + 3 * 3600 / 4) <= next_refresh_time)
+        self.assertTrue(((time1 + 3600 * (1 - self.zone_refresh._refresh_jitter))) <= next_refresh_time)
         self.assertTrue(next_refresh_time <= time2 + 3600)
         self.assertEqual(ZONE_OK, self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["zone_state"])
 
-        self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["last_refresh_time"] = time1 - 2419200 
+        self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["last_refresh_time"] = time1 - 2419200
         self.zone_refresh.zone_refresh_fail(ZONE_NAME_CLASS1_IN)
         self.assertEqual(ZONE_EXPIRED, self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["zone_state"])
 
         self.assertRaises(ZonemgrException, self.zone_refresh.zone_refresh_fail, ("org.cn.", "CH"))
-        self.assertRaises(ZonemgrException, self.zone_refresh.zone_refresh_fail, ZONE_NAME_CLASS3_IN) 
+        self.assertRaises(ZonemgrException, self.zone_refresh.zone_refresh_fail, ZONE_NAME_CLASS3_IN)
 
     def test_find_need_do_refresh_zone(self):
         time1 = time.time()
-        self.zone_refresh._zonemgr_refresh_info = { 
+        self.zone_refresh._zonemgr_refresh_info = {
                 ("sd.cn.","IN"):{
                     'last_refresh_time': time1,
-                    'next_refresh_time': time1 + 7200, 
-                    'zone_soa_rdata': 'a.dns.cn. root.cnnic.cn. 2009073105 7200 3600 2419200 21600', 
+                    'next_refresh_time': time1 + 7200,
+                    'zone_soa_rdata': 'a.dns.cn. root.cnnic.cn. 2009073105 7200 3600 2419200 21600',
                     'zone_state': ZONE_OK},
                 ("tw.cn.","CH"):{
-                    'last_refresh_time': time1 - 7200, 
-                    'next_refresh_time': time1, 
-                    'refresh_timeout': time1 + MAX_TRANSFER_TIMEOUT, 
-                    'zone_soa_rdata': 'a.dns.cn. root.cnnic.cn. 2009073112 7200 3600 2419200 21600', 
+                    'last_refresh_time': time1 - 7200,
+                    'next_refresh_time': time1,
+                    'refresh_timeout': time1 + MAX_TRANSFER_TIMEOUT,
+                    'zone_soa_rdata': 'a.dns.cn. root.cnnic.cn. 2009073112 7200 3600 2419200 21600',
                     'zone_state': ZONE_REFRESHING}
                 }
         zone_need_refresh = self.zone_refresh._find_need_do_refresh_zone()
         self.assertEqual(ZONE_NAME_CLASS1_IN, zone_need_refresh)
 
-        self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS2_CH]["refresh_timeout"] = time1 
+        self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS2_CH]["refresh_timeout"] = time1
         zone_need_refresh = self.zone_refresh._find_need_do_refresh_zone()
         self.assertEqual(ZONE_NAME_CLASS2_CH, zone_need_refresh)
 
@@ -375,42 +387,42 @@ class TestZonemgrRefresh(unittest.TestCase):
         self.zone_refresh._zonemgr_refresh_info = {
                 ("sd.cn.", "IN"):{
                     'last_refresh_time': time1 - 7200,
-                    'next_refresh_time': time1 - 1, 
-                    'zone_soa_rdata': 'a.dns.cn. root.cnnic.cn. 2009073105 7200 3600 2419200 21600', 
+                    'next_refresh_time': time1 - 1,
+                    'zone_soa_rdata': 'a.dns.cn. root.cnnic.cn. 2009073105 7200 3600 2419200 21600',
                     'zone_state': ZONE_OK}
                 }
         self.zone_refresh._do_refresh(ZONE_NAME_CLASS1_IN)
         time2 = time.time()
         zone_state = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["zone_state"]
         self.assertEqual(ZONE_REFRESHING, zone_state)
-        refresh_timeout = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["refresh_timeout"] 
+        refresh_timeout = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["refresh_timeout"]
         self.assertTrue(time1 + MAX_TRANSFER_TIMEOUT <= refresh_timeout)
-        self.assertTrue(time2 + MAX_TRANSFER_TIMEOUT >= refresh_timeout) 
+        self.assertTrue(time2 + MAX_TRANSFER_TIMEOUT >= refresh_timeout)
 
         self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["notify_master"] = "127.0.0.1"
         self.zone_refresh._do_refresh(ZONE_NAME_CLASS1_IN)
         time2 = time.time()
         zone_state = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["zone_state"]
-        self.assertEqual(ZONE_REFRESHING, zone_state) 
-        refresh_timeout = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["refresh_timeout"] 
+        self.assertEqual(ZONE_REFRESHING, zone_state)
+        refresh_timeout = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["refresh_timeout"]
         self.assertTrue(time1 + MAX_TRANSFER_TIMEOUT <= refresh_timeout)
         self.assertTrue(time2 + MAX_TRANSFER_TIMEOUT >= refresh_timeout)
         self.assertFalse("notify_master" in self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN].keys())
 
     def test_run_timer(self):
-        """This case will run timer in daemon thread. 
-        The zone's next_refresh_time is less than now, so zonemgr will do zone refresh 
-        immediately. The zone's state will become "refreshing". 
+        """This case will run timer in daemon thread.
+        The zone's next_refresh_time is less than now, so zonemgr will do zone refresh
+        immediately. The zone's state will become "refreshing".
         """
         time1 = time.time()
         self.zone_refresh._zonemgr_refresh_info = {
                 ("sd.cn.", "IN"):{
                     'last_refresh_time': time1 - 7200,
-                    'next_refresh_time': time1 - 1, 
-                    'zone_soa_rdata': 'a.dns.cn. root.cnnic.cn. 2009073105 7200 3600 2419200 21600', 
+                    'next_refresh_time': time1 - 1,
+                    'zone_soa_rdata': 'a.dns.cn. root.cnnic.cn. 2009073105 7200 3600 2419200 21600',
                     'zone_state': ZONE_OK}
                 }
-        self.zone_refresh._check_sock = self.zone_refresh._master_socket 
+        self.zone_refresh._check_sock = self.zone_refresh._master_socket
         listener = self.zone_refresh.run_timer(daemon=True)
         # Shut down the timer thread
         self.zone_refresh.shutdown()
@@ -424,17 +436,19 @@ class TestZonemgrRefresh(unittest.TestCase):
                     "lowerbound_refresh" : 60,
                     "lowerbound_retry" : 30,
                     "max_transfer_timeout" : 19800,
-                    "jitter_scope" : 0.25,
+                    "refresh_jitter" : 0.25,
+                    "reload_jitter" : 0.75,
                     "secondary_zones": []
                 }
         self.zone_refresh.update_config_data(config_data)
         self.assertEqual(60, self.zone_refresh._lowerbound_refresh)
         self.assertEqual(30, self.zone_refresh._lowerbound_retry)
         self.assertEqual(19800, self.zone_refresh._max_transfer_timeout)
-        self.assertEqual(0.25, self.zone_refresh._jitter_scope)
+        self.assertEqual(0.25, self.zone_refresh._refresh_jitter)
+        self.assertEqual(0.75, self.zone_refresh._reload_jitter)
 
     def test_shutdown(self):
-        self.zone_refresh._check_sock = self.zone_refresh._master_socket 
+        self.zone_refresh._check_sock = self.zone_refresh._master_socket
         listener = self.zone_refresh.run_timer()
         self.assertTrue(listener.is_alive())
         # Shut down the timer thread
@@ -473,7 +487,7 @@ class TestZonemgrRefresh(unittest.TestCase):
 class MyCCSession():
     def __init__(self):
         pass
-                    
+
     def get_remote_config_value(self, module_name, identifier):
         if module_name == "Auth" and identifier == "database_file":
             return "initdb.file", False
@@ -493,7 +507,8 @@ class MyZonemgr(Zonemgr):
                     "lowerbound_refresh" : 10,
                     "lowerbound_retry" : 5,
                     "max_transfer_timeout" : 14400,
-                    "jitter_scope" : 0.1,
+                    "refresh_jitter" : 0.1,
+                    "reload_jitter" : 0.75,
                     "secondary_zones": []
                     }
 
@@ -510,7 +525,8 @@ class TestZonemgr(unittest.TestCase):
                     "lowerbound_refresh" : 60,
                     "lowerbound_retry" : 30,
                     "max_transfer_timeout" : 14400,
-                    "jitter_scope" : 0.1,
+                    "refresh_jitter" : 0.1,
+                    "reload_jitter" : 0.75,
                     "secondary_zones": []
                     }
         self.assertEqual(self.zonemgr.config_handler(config_data1),
@@ -520,9 +536,9 @@ class TestZonemgr(unittest.TestCase):
         self.zonemgr.config_handler(config_data2)
         self.assertEqual(config_data1, self.zonemgr._config_data)
         # jitter should not be bigger than half of the original value
-        config_data3 = {"jitter_scope" : 0.7}
+        config_data3 = {"refresh_jitter" : 0.7}
         self.zonemgr.config_handler(config_data3)
-        self.assertEqual(0.5, self.zonemgr._config_data.get("jitter_scope"))
+        self.assertEqual(0.5, self.zonemgr._config_data.get("refresh_jitter"))
         # The zone doesn't exist in database, it should be rejected
         self.zonemgr._zone_refresh = ZonemgrRefresh(None, "initdb.file", None,
                                                     config_data1)
@@ -531,7 +547,7 @@ class TestZonemgr(unittest.TestCase):
         self.assertNotEqual(self.zonemgr.config_handler(config_data1),
                             {"result": [0]})
         # As it is rejected, the old value should be kept
-        self.assertEqual(0.5, self.zonemgr._config_data.get("jitter_scope"))
+        self.assertEqual(0.5, self.zonemgr._config_data.get("refresh_jitter"))
 
     def test_get_db_file(self):
         self.assertEqual("initdb.file", self.zonemgr.get_db_file())
@@ -549,12 +565,12 @@ class TestZonemgr(unittest.TestCase):
 
     def test_config_data_check(self):
         # jitter should not be bigger than half of the original value
-        config_data2 = {"jitter_scope" : 0.2}
-        config_data3 = {"jitter_scope" : 0.6}
+        config_data2 = {"refresh_jitter" : 0.2}
+        config_data3 = {"refresh_jitter" : 0.6}
         self.zonemgr._config_data_check(config_data2)
-        self.assertEqual(0.2, config_data2.get("jitter_scope"))
+        self.assertEqual(0.2, config_data2.get("refresh_jitter"))
         self.zonemgr._config_data_check(config_data3)
-        self.assertEqual(0.5, config_data3.get("jitter_scope"))
+        self.assertEqual(0.5, config_data3.get("refresh_jitter"))
 
     def tearDown(self):
         pass
diff --git a/src/bin/zonemgr/zonemgr.py.in b/src/bin/zonemgr/zonemgr.py.in
index 129c673..cc6d7b9 100755
--- a/src/bin/zonemgr/zonemgr.py.in
+++ b/src/bin/zonemgr/zonemgr.py.in
@@ -125,19 +125,19 @@ class ZonemgrRefresh:
 
     def _set_zone_refresh_timer(self, zone_name_class):
         """Set zone next refresh time after zone refresh success.
-           now + refresh - jitter  <= next_refresh_time <= now + refresh
+           now + refresh - refresh_jitter <= next_refresh_time <= now + refresh
            """
         zone_refresh_time = float(self._get_zone_soa_rdata(zone_name_class).split(" ")[REFRESH_OFFSET])
         zone_refresh_time = max(self._lowerbound_refresh, zone_refresh_time)
-        self._set_zone_timer(zone_name_class, zone_refresh_time, self._jitter_scope * zone_refresh_time)
+        self._set_zone_timer(zone_name_class, zone_refresh_time, self._refresh_jitter * zone_refresh_time)
 
     def _set_zone_retry_timer(self, zone_name_class):
         """Set zone next refresh time after zone refresh fail.
-           now + retry - jitter <= next_refresh_time <= now + retry
+           now + retry - retry_jitter <= next_refresh_time <= now + retry
            """
         zone_retry_time = float(self._get_zone_soa_rdata(zone_name_class).split(" ")[RETRY_OFFSET])
         zone_retry_time = max(self._lowerbound_retry, zone_retry_time)
-        self._set_zone_timer(zone_name_class, zone_retry_time, self._jitter_scope * zone_retry_time)
+        self._set_zone_timer(zone_name_class, zone_retry_time, self._refresh_jitter * zone_retry_time)
 
     def _set_zone_notify_timer(self, zone_name_class):
         """Set zone next refresh time after receiving notify
@@ -194,9 +194,11 @@ class ZonemgrRefresh:
         zone_info["zone_soa_rdata"] = zone_soa[7]
         zone_info["zone_state"] = ZONE_OK
         zone_info["last_refresh_time"] = self._get_current_time()
-        zone_info["next_refresh_time"] = self._get_current_time() + \
-                                         float(zone_soa[7].split(" ")[REFRESH_OFFSET])
         self._zonemgr_refresh_info[zone_name_class] = zone_info
+        # Imposes some random jitters to avoid many zones need to do refresh at the same time.
+        zone_reload_jitter = float(zone_soa[7].split(" ")[RETRY_OFFSET])
+        zone_reload_jitter = max(self._lowerbound_retry, zone_reload_jitter)
+        self._set_zone_timer(zone_name_class, zone_reload_jitter, self._reload_jitter * zone_reload_jitter)
 
     def _zone_is_expired(self, zone_name_class):
         """Judge whether a zone is expired or not."""
@@ -431,7 +433,8 @@ class ZonemgrRefresh:
         self._lowerbound_refresh = new_config.get('lowerbound_refresh')
         self._lowerbound_retry = new_config.get('lowerbound_retry')
         self._max_transfer_timeout = new_config.get('max_transfer_timeout')
-        self._jitter_scope = new_config.get('jitter_scope')
+        self._refresh_jitter = new_config.get('refresh_jitter')
+        self._reload_jitter = new_config.get('reload_jitter')
 
 class Zonemgr:
     """Zone manager class."""
@@ -510,9 +513,9 @@ class Zonemgr:
         not. It contains only basic logic, not full check against
         database."""
         # jitter should not be bigger than half of the original value
-        if config_data.get('jitter_scope') > 0.5:
-            config_data['jitter_scope'] = 0.5
-            log_msg("[b10-zonemgr] jitter_scope is too big, its value will "
+        if config_data.get('refresh_jitter') > 0.5:
+            config_data['refresh_jitter'] = 0.5
+            log_msg("[b10-zonemgr] refresh_jitter is too big, its value will "
                       "be set to 0.5")
 
 
diff --git a/src/bin/zonemgr/zonemgr.spec.pre.in b/src/bin/zonemgr/zonemgr.spec.pre.in
index 9df01f2..36f02df 100644
--- a/src/bin/zonemgr/zonemgr.spec.pre.in
+++ b/src/bin/zonemgr/zonemgr.spec.pre.in
@@ -12,21 +12,27 @@
          "item_name": "lowerbound_retry",
          "item_type": "integer",
          "item_optional": false,
-         "item_default": 5 
+         "item_default": 5
        },
        {
          "item_name": "max_transfer_timeout",
          "item_type": "integer",
          "item_optional": false,
-         "item_default": 14400 
+         "item_default": 14400
        },
        {
-         "item_name": "jitter_scope",
+         "item_name": "refresh_jitter",
          "item_type": "real",
          "item_optional": false,
          "item_default": 0.25
        },
        {
+         "item_name": "reload_jitter",
+         "item_type": "real",
+         "item_optional": false,
+         "item_default": 0.75
+       },
+       {
          "item_name": "secondary_zones",
          "item_type": "list",
          "item_optional": false,
diff --git a/src/cppcheck-suppress.lst b/src/cppcheck-suppress.lst
index e9c4beb..5e6d81f 100644
--- a/src/cppcheck-suppress.lst
+++ b/src/cppcheck-suppress.lst
@@ -12,4 +12,4 @@ functionConst:src/lib/cache/rrset_cache.h
 // Intentional self assignment tests.  Suppress warning about them.
 selfAssignment:src/lib/dns/tests/name_unittest.cc:293
 selfAssignment:src/lib/dns/tests/rdata_unittest.cc:228
-selfAssignment:src/lib/dns/tests/tsigkey_unittest.cc:104
+selfAssignment:src/lib/dns/tests/tsigkey_unittest.cc:120
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
index 81455c4..184b090 100644
--- a/src/lib/Makefile.am
+++ b/src/lib/Makefile.am
@@ -1,2 +1,3 @@
-SUBDIRS = exceptions util dns cc config python xfr bench log asiolink \
-          asiodns nsas cache resolve testutils datasrc server_common
+SUBDIRS = exceptions util cryptolink dns cc config python xfr bench \
+          log asiolink asiodns nsas cache resolve testutils datasrc \
+          server_common
diff --git a/src/lib/asiodns/Makefile.am b/src/lib/asiodns/Makefile.am
index 4bcdde6..2a6c3ac 100644
--- a/src/lib/asiodns/Makefile.am
+++ b/src/lib/asiodns/Makefile.am
@@ -8,12 +8,17 @@ AM_CPPFLAGS += -I$(top_srcdir)/src/lib/util -I$(top_builddir)/src/lib/util
 
 AM_CXXFLAGS = $(B10_CXXFLAGS)
 
-CLEANFILES = *.gcno *.gcda
+CLEANFILES = *.gcno *.gcda asiodef.h asiodef.cc
+
+# Define rule to build logging source files from message file
+asiodef.h asiodef.cc: asiodef.mes
+	$(top_builddir)/src/lib/log/compiler/message $(top_srcdir)/src/lib/asiodns/asiodef.mes
+
+BUILT_SOURCES = asiodef.h asiodef.cc
 
 lib_LTLIBRARIES = libasiodns.la
 libasiodns_la_SOURCES = dns_answer.h
 libasiodns_la_SOURCES += asiodns.h
-libasiodns_la_SOURCES += asiodef.cc asiodef.h
 libasiodns_la_SOURCES += dns_lookup.h
 libasiodns_la_SOURCES += dns_server.h
 libasiodns_la_SOURCES += dns_service.cc dns_service.h
@@ -21,7 +26,9 @@ libasiodns_la_SOURCES += tcp_server.cc tcp_server.h
 libasiodns_la_SOURCES += udp_server.cc udp_server.h
 libasiodns_la_SOURCES += io_fetch.cc io_fetch.h
 
-EXTRA_DIST = asiodef.msg
+nodist_libasiodns_la_SOURCES = asiodef.cc asiodef.h
+
+EXTRA_DIST = asiodef.mes
 
 # Note: the ordering matters: -Wno-... must follow -Wextra (defined in
 # B10_CXXFLAGS)
diff --git a/src/lib/asiodns/asiodef.cc b/src/lib/asiodns/asiodef.cc
deleted file mode 100644
index 127e848..0000000
--- a/src/lib/asiodns/asiodef.cc
+++ /dev/null
@@ -1,39 +0,0 @@
-// File created from asiodef.msg on Mon Feb 28 17:15:30 2011
-
-#include <cstddef>
-#include <log/message_types.h>
-#include <log/message_initializer.h>
-
-namespace isc {
-namespace asiodns {
-
-extern const isc::log::MessageID ASIODNS_FETCHCOMP = "FETCHCOMP";
-extern const isc::log::MessageID ASIODNS_FETCHSTOP = "FETCHSTOP";
-extern const isc::log::MessageID ASIODNS_OPENSOCK = "OPENSOCK";
-extern const isc::log::MessageID ASIODNS_RECVSOCK = "RECVSOCK";
-extern const isc::log::MessageID ASIODNS_RECVTMO = "RECVTMO";
-extern const isc::log::MessageID ASIODNS_SENDSOCK = "SENDSOCK";
-extern const isc::log::MessageID ASIODNS_UNKORIGIN = "UNKORIGIN";
-extern const isc::log::MessageID ASIODNS_UNKRESULT = "UNKRESULT";
-
-} // namespace asiodns
-} // namespace isc
-
-namespace {
-
-const char* values[] = {
-    "FETCHCOMP", "upstream fetch to %s(%d) has now completed",
-    "FETCHSTOP", "upstream fetch to %s(%d) has been stopped",
-    "OPENSOCK", "error %d opening %s socket to %s(%d)",
-    "RECVSOCK", "error %d reading %s data from %s(%d)",
-    "RECVTMO", "receive timeout while waiting for data from %s(%d)",
-    "SENDSOCK", "error %d sending data using %s to %s(%d)",
-    "UNKORIGIN", "unknown origin for ASIO error code %d (protocol: %s, address %s)",
-    "UNKRESULT", "unknown result (%d) when IOFetch::stop() was executed for I/O to %s(%d)",
-    NULL
-};
-
-const isc::log::MessageInitializer initializer(values);
-
-} // Anonymous namespace
-
diff --git a/src/lib/asiodns/asiodef.h b/src/lib/asiodns/asiodef.h
deleted file mode 100644
index 50aa8a9..0000000
--- a/src/lib/asiodns/asiodef.h
+++ /dev/null
@@ -1,23 +0,0 @@
-// File created from asiodef.msg on Mon Feb 28 17:15:30 2011
-
-#ifndef __ASIODEF_H
-#define __ASIODEF_H
-
-#include <log/message_types.h>
-
-namespace isc {
-namespace asiodns {
-
-extern const isc::log::MessageID ASIODNS_FETCHCOMP;
-extern const isc::log::MessageID ASIODNS_FETCHSTOP;
-extern const isc::log::MessageID ASIODNS_OPENSOCK;
-extern const isc::log::MessageID ASIODNS_RECVSOCK;
-extern const isc::log::MessageID ASIODNS_RECVTMO;
-extern const isc::log::MessageID ASIODNS_SENDSOCK;
-extern const isc::log::MessageID ASIODNS_UNKORIGIN;
-extern const isc::log::MessageID ASIODNS_UNKRESULT;
-
-} // namespace asiodns
-} // namespace isc
-
-#endif // __ASIODEF_H
diff --git a/src/lib/asiodns/asiodef.mes b/src/lib/asiodns/asiodef.mes
new file mode 100644
index 0000000..3f2e80c
--- /dev/null
+++ b/src/lib/asiodns/asiodef.mes
@@ -0,0 +1,56 @@
+# Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+# PERFORMANCE OF THIS SOFTWARE.
+
+$PREFIX ASIODNS_
+$NAMESPACE isc::asiodns
+
+% FETCHCOMP   upstream fetch to %1(%2) has now completed
+A debug message, this records the the upstream fetch (a query made by the
+resolver on behalf of its client) to the specified address has completed.
+
+% FETCHSTOP   upstream fetch to %1(%2) has been stopped
+An external component has requested the halting of an upstream fetch.  This
+is an allowed operation, and the message should only appear if debug is
+enabled.
+
+% OPENSOCK    error %1 opening %2 socket to %3(%4)
+The asynchronous I/O code encountered an error when trying to open a socket
+of the specified protocol in order to send a message to the target address.
+The the number of the system error that cause the problem is given in the
+message.
+
+% RECVSOCK    error %1 reading %2 data from %3(%4)
+The asynchronous I/O code encountered an error when trying read data from
+the specified address on the given protocol.  The the number of the system
+error that cause the problem is given in the message.
+
+% SENDSOCK    error %1 sending data using %2 to %3(%4)
+The asynchronous I/O code encountered an error when trying send data to
+the specified address on the given protocol.  The the number of the system
+error that cause the problem is given in the message.
+
+% RECVTMO     receive timeout while waiting for data from %1(%2)
+An upstream fetch from the specified address timed out.  This may happen for
+any number of reasons and is most probably a problem at the remote server
+or a problem on the network.  The message will only appear if debug is
+enabled.
+
+% UNKORIGIN  unknown origin for ASIO error code %1 (protocol: %2, address %3)
+This message should not appear and indicates an internal error if it does.
+Please enter a bug report.
+
+% UNKRESULT  unknown result (%1) when IOFetch::stop() was executed for I/O to %2(%3)
+The termination method of the resolver's upstream fetch class was called with
+an unknown result code (which is given in the message).  This message should
+not appear and may indicate an internal error.  Please enter a bug report.
diff --git a/src/lib/asiodns/asiodef.msg b/src/lib/asiodns/asiodef.msg
deleted file mode 100644
index 7f86acb..0000000
--- a/src/lib/asiodns/asiodef.msg
+++ /dev/null
@@ -1,56 +0,0 @@
-# Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
-#
-# Permission to use, copy, modify, and/or distribute this software for any
-# purpose with or without fee is hereby granted, provided that the above
-# copyright notice and this permission notice appear in all copies.
-#
-# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
-# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-# AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
-# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-# PERFORMANCE OF THIS SOFTWARE.
-
-$PREFIX ASIODNS_
-$NAMESPACE isc::asiodns
-
-FETCHCOMP   upstream fetch to %s(%d) has now completed
-+ A debug message, this records the the upstream fetch (a query made by the
-+ resolver on behalf of its client) to the specified address has completed.
-
-FETCHSTOP   upstream fetch to %s(%d) has been stopped
-+ An external component has requested the halting of an upstream fetch.  This
-+ is an allowed operation, and the message should only appear if debug is
-+ enabled.
-
-OPENSOCK    error %d opening %s socket to %s(%d)
-+ The asynchronous I/O code encountered an error when trying to open a socket
-+ of the specified protocol in order to send a message to the target address.
-+ The the number of the system error that cause the problem is given in the
-+ message.
-
-RECVSOCK    error %d reading %s data from %s(%d)
-+ The asynchronous I/O code encountered an error when trying read data from
-+ the specified address on the given protocol.  The the number of the system
-+ error that cause the problem is given in the message.
-
-SENDSOCK    error %d sending data using %s to %s(%d)
-+ The asynchronous I/O code encountered an error when trying send data to
-+ the specified address on the given protocol.  The the number of the system
-+ error that cause the problem is given in the message.
-
-RECVTMO     receive timeout while waiting for data from %s(%d)
-+ An upstream fetch from the specified address timed out.  This may happen for
-+ any number of reasons and is most probably a problem at the remote server
-+ or a problem on the network.  The message will only appear if debug is
-+ enabled.
-
-UNKORIGIN  unknown origin for ASIO error code %d (protocol: %s, address %s)
-+ This message should not appear and indicates an internal error if it does.
-+ Please enter a bug report.
-
-UNKRESULT  unknown result (%d) when IOFetch::stop() was executed for I/O to %s(%d)
-+ The termination method of the resolver's upstream fetch class was called with
-+ an unknown result code (which is given in the message).  This message should
-+ not appear and may indicate an internal error.  Please enter a bug report.
diff --git a/src/lib/asiodns/io_fetch.cc b/src/lib/asiodns/io_fetch.cc
index 3517d78..e535381 100644
--- a/src/lib/asiodns/io_fetch.cc
+++ b/src/lib/asiodns/io_fetch.cc
@@ -39,6 +39,7 @@
 #include <dns/opcode.h>
 #include <dns/rcode.h>
 #include <log/logger.h>
+#include <log/macros.h>
 
 #include <asiodns/asiodef.h>
 #include <asiodns/io_fetch.h>
@@ -60,7 +61,17 @@ namespace asiodns {
 
 /// Use the ASIO logger
 
+namespace {
+
 isc::log::Logger logger("asiolink");
+// Log debug verbosity
+enum {
+    DBG_IMPORTANT = 1,
+    DBG_COMMON = 20,
+    DBG_ALL = 50
+};
+
+}
 
 /// \brief IOFetch Data
 ///
@@ -359,42 +370,34 @@ IOFetch::stop(Result result) {
         // numbers indicating the most important information.  The relative
         // values are somewhat arbitrary.
         //
-        // Although Logger::debug checks the debug flag internally, doing it
-        // below before calling Logger::debug avoids the overhead of a string
-        // conversion in the common case when debug is not enabled.
-        //
         // TODO: Update testing of stopped_ if threads are used.
         data_->stopped = true;
         switch (result) {
             case TIME_OUT:
-                if (logger.isDebugEnabled(1)) {
-                    logger.debug(20, ASIODNS_RECVTMO,
-                                 data_->remote_snd->getAddress().toText().c_str(),
-                                 static_cast<int>(data_->remote_snd->getPort()));
-                }
+                LOG_DEBUG(logger, DBG_COMMON, ASIODNS_RECVTMO).
+                    arg(data_->remote_snd->getAddress().toText()).
+                    arg(data_->remote_snd->getPort());
                 break;
 
             case SUCCESS:
-                if (logger.isDebugEnabled(50)) {
-                    logger.debug(30, ASIODNS_FETCHCOMP,
-                                 data_->remote_rcv->getAddress().toText().c_str(),
-                                 static_cast<int>(data_->remote_rcv->getPort()));
-                }
+                LOG_DEBUG(logger, DBG_ALL, ASIODNS_FETCHCOMP).
+                    arg(data_->remote_rcv->getAddress().toText()).
+                    arg(data_->remote_rcv->getPort());
                 break;
 
             case STOPPED:
                 // Fetch has been stopped for some other reason.  This is
                 // allowed but as it is unusual it is logged, but with a lower
                 // debug level than a timeout (which is totally normal).
-                logger.debug(1, ASIODNS_FETCHSTOP,
-                             data_->remote_snd->getAddress().toText().c_str(),
-                             static_cast<int>(data_->remote_snd->getPort()));
+                LOG_DEBUG(logger, DBG_IMPORTANT, ASIODNS_FETCHSTOP).
+                    arg(data_->remote_snd->getAddress().toText()).
+                    arg(data_->remote_snd->getPort());
                 break;
 
             default:
-                logger.error(ASIODNS_UNKRESULT, static_cast<int>(result),
-                             data_->remote_snd->getAddress().toText().c_str(),
-                             static_cast<int>(data_->remote_snd->getPort()));
+                LOG_ERROR(logger, ASIODNS_UNKRESULT).
+                    arg(data_->remote_snd->getAddress().toText()).
+                    arg(data_->remote_snd->getPort());
         }
 
         // Stop requested, cancel and I/O's on the socket and shut it down,
@@ -422,12 +425,11 @@ void IOFetch::logIOFailure(asio::error_code ec) {
            (data_->origin == ASIODNS_UNKORIGIN));
 
     static const char* PROTOCOL[2] = {"TCP", "UDP"};
-    logger.error(data_->origin,
-                 ec.value(),
-                 ((data_->remote_snd->getProtocol() == IPPROTO_TCP) ?
-                     PROTOCOL[0] : PROTOCOL[1]),
-                 data_->remote_snd->getAddress().toText().c_str(),
-                 static_cast<int>(data_->remote_snd->getPort()));
+    LOG_ERROR(logger, data_->origin).arg(ec.value()).
+        arg((data_->remote_snd->getProtocol() == IPPROTO_TCP) ?
+                     PROTOCOL[0] : PROTOCOL[1]).
+        arg(data_->remote_snd->getAddress().toText()).
+        arg(data_->remote_snd->getPort());
 }
 
 } // namespace asiodns
diff --git a/src/lib/asiolink/Makefile.am b/src/lib/asiolink/Makefile.am
index 66d5eda..22b3a8e 100644
--- a/src/lib/asiolink/Makefile.am
+++ b/src/lib/asiolink/Makefile.am
@@ -2,7 +2,6 @@ SUBDIRS = . tests
 
 AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
 AM_CPPFLAGS += $(BOOST_INCLUDES)
-AM_CPPFLAGS += -I$(top_srcdir)/src/lib/dns -I$(top_builddir)/src/lib/dns
 
 AM_CXXFLAGS = $(B10_CXXFLAGS)
 
diff --git a/src/lib/asiolink/interval_timer.h b/src/lib/asiolink/interval_timer.h
index 0831d44..8de16cb 100644
--- a/src/lib/asiolink/interval_timer.h
+++ b/src/lib/asiolink/interval_timer.h
@@ -22,7 +22,7 @@
 namespace isc {
 namespace asiolink {
 
-struct IntervalTimerImpl;
+class IntervalTimerImpl;
 
 /// \brief The \c IntervalTimer class is a wrapper for the ASIO
 /// \c asio::deadline_timer class.
diff --git a/src/lib/asiolink/io_service.h b/src/lib/asiolink/io_service.h
index 438667c..75aaee6 100644
--- a/src/lib/asiolink/io_service.h
+++ b/src/lib/asiolink/io_service.h
@@ -22,7 +22,7 @@ namespace asio {
 namespace isc {
 namespace asiolink {
 
-struct IOServiceImpl;
+class IOServiceImpl;
 
 /// \brief The \c IOService class is a wrapper for the ASIO \c io_service
 /// class.
diff --git a/src/lib/asiolink/tests/Makefile.am b/src/lib/asiolink/tests/Makefile.am
index 37d9ef3..bfdf7c1 100644
--- a/src/lib/asiolink/tests/Makefile.am
+++ b/src/lib/asiolink/tests/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
 AM_CPPFLAGS += $(BOOST_INCLUDES)
-AM_CPPFLAGS += -I$(top_builddir)/src/lib/dns -I$(top_srcdir)/src/bin
 AM_CPPFLAGS += -I$(top_builddir)/src/lib/util -I$(top_srcdir)/src/util
 AM_CPPFLAGS += -I$(top_builddir)/src/lib/cc
 AM_CPPFLAGS += -DTEST_DATA_DIR=\"$(srcdir)/testdata\"
@@ -17,8 +16,6 @@ TESTS =
 if HAVE_GTEST
 TESTS += run_unittests
 run_unittests_SOURCES  = run_unittests.cc
-run_unittests_SOURCES += $(top_srcdir)/src/lib/dns/tests/unittest_util.h
-run_unittests_SOURCES += $(top_srcdir)/src/lib/dns/tests/unittest_util.cc
 run_unittests_SOURCES += io_address_unittest.cc
 run_unittests_SOURCES += io_endpoint_unittest.cc
 run_unittests_SOURCES += io_socket_unittest.cc
@@ -32,7 +29,6 @@ run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
 
 run_unittests_LDADD  = $(GTEST_LDADD)
 run_unittests_LDADD += $(SQLITE_LIBS)
-run_unittests_LDADD += $(top_builddir)/src/lib/dns/libdns++.la
 run_unittests_LDADD += $(top_builddir)/src/lib/asiolink/libasiolink.la
 run_unittests_LDADD += $(top_builddir)/src/lib/util/libutil.la
 run_unittests_LDADD += $(top_builddir)/src/lib/log/liblog.la
diff --git a/src/lib/asiolink/tests/run_unittests.cc b/src/lib/asiolink/tests/run_unittests.cc
index c285f9e..97bcb65 100644
--- a/src/lib/asiolink/tests/run_unittests.cc
+++ b/src/lib/asiolink/tests/run_unittests.cc
@@ -22,7 +22,6 @@ main(int argc, char* argv[])
 {
     ::testing::InitGoogleTest(&argc, argv);         // Initialize Google test
     isc::log::setRootLoggerName("unittest");        // Set a root logger name
-    isc::UnitTestUtil::addDataPath(TEST_DATA_DIR);  // Add location of test data
 
     return (RUN_ALL_TESTS());
 }
diff --git a/src/lib/cc/Makefile.am b/src/lib/cc/Makefile.am
index 44033e9..9d5b188 100644
--- a/src/lib/cc/Makefile.am
+++ b/src/lib/cc/Makefile.am
@@ -11,6 +11,7 @@ if USE_GXX
 # avoid the error.  As a short term workaround we suppress this warning
 # for the entire this module.  See also src/bin/auth/Makefile.am.
 AM_CXXFLAGS += -Wno-unused-parameter
+AM_CXXFLAGS += -fno-strict-aliasing
 endif
 if USE_CLANGPP
 # Likewise, ASIO header files will trigger various warnings with clang++.
diff --git a/src/lib/cc/tests/Makefile.am b/src/lib/cc/tests/Makefile.am
index 535c464..71e6988 100644
--- a/src/lib/cc/tests/Makefile.am
+++ b/src/lib/cc/tests/Makefile.am
@@ -26,7 +26,6 @@ run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)
 
 run_unittests_LDADD = $(GTEST_LDADD)
 run_unittests_LDADD +=  $(top_builddir)/src/lib/cc/libcc.la
-run_unittests_LDADD +=  $(top_builddir)/src/lib/dns/libdns++.la
 run_unittests_LDADD +=  $(top_builddir)/src/lib/exceptions/libexceptions.la
 
 endif
diff --git a/src/lib/config/Makefile.am b/src/lib/config/Makefile.am
index 580f240..99e8c86 100644
--- a/src/lib/config/Makefile.am
+++ b/src/lib/config/Makefile.am
@@ -3,7 +3,6 @@ SUBDIRS = . tests
 AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
 AM_CPPFLAGS += -I$(top_builddir)/src/lib/cc
 AM_CPPFLAGS += $(BOOST_INCLUDES)
-AM_CXXFLAGS = $(B10_CXXFLAGS) -Wno-strict-aliasing
 
 lib_LTLIBRARIES = libcfgclient.la
 libcfgclient_la_SOURCES = config_data.h config_data.cc module_spec.h module_spec.cc ccsession.cc ccsession.h
diff --git a/src/lib/config/tests/fake_session.cc b/src/lib/config/tests/fake_session.cc
index 29744c7..5f79d48 100644
--- a/src/lib/config/tests/fake_session.cc
+++ b/src/lib/config/tests/fake_session.cc
@@ -52,16 +52,14 @@ listContains(ConstElementPtr list, ConstElementPtr el) {
 
 void
 listRemove(ElementPtr list, ConstElementPtr el) {
-    int i = -1;
+    int i = 0;
     BOOST_FOREACH(ConstElementPtr s_el, list->listValue()) {
         if (*el == *s_el) {
-            i = 0;
+            list->remove(i);
+            return;
         }
         i++;
     }
-    if (i >= 0) {
-        list->remove(i);
-    }
 }
 // endwant
 
diff --git a/src/lib/cryptolink/Makefile.am b/src/lib/cryptolink/Makefile.am
new file mode 100644
index 0000000..93f3443
--- /dev/null
+++ b/src/lib/cryptolink/Makefile.am
@@ -0,0 +1,14 @@
+SUBDIRS = . tests
+
+AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
+AM_CPPFLAGS += $(BOOST_INCLUDES) $(BOTAN_INCLUDES)
+AM_CXXFLAGS = $(B10_CXXFLAGS)
+
+CLEANFILES = *.gcno *.gcda
+
+lib_LTLIBRARIES = libcryptolink.la
+
+libcryptolink_la_SOURCES = cryptolink.h cryptolink.cc
+libcryptolink_la_SOURCES += crypto_hmac.h crypto_hmac.cc
+
+libcryptolink_la_LIBADD = ${BOTAN_LDFLAGS} ${BOTAN_RPATH}
diff --git a/src/lib/cryptolink/crypto_hmac.cc b/src/lib/cryptolink/crypto_hmac.cc
new file mode 100644
index 0000000..9c35f60
--- /dev/null
+++ b/src/lib/cryptolink/crypto_hmac.cc
@@ -0,0 +1,237 @@
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <cryptolink.h>
+#include <cryptolink/crypto_hmac.h>
+
+#include <boost/scoped_ptr.hpp>
+
+#include <botan/botan.h>
+#include <botan/hmac.h>
+#include <botan/hash.h>
+#include <botan/types.h>
+
+namespace {
+const char*
+getBotanHashAlgorithmName(isc::cryptolink::HashAlgorithm algorithm) {
+    switch (algorithm) {
+    case isc::cryptolink::MD5:
+        return ("MD5");
+        break;
+    case isc::cryptolink::SHA1:
+        return ("SHA-1");
+        break;
+    case isc::cryptolink::SHA256:
+        return ("SHA-256");
+        break;
+    case isc::cryptolink::UNKNOWN_HASH:
+        return ("Unknown");
+        break;
+    }
+    // compiler should have prevented us to reach this, since we have
+    // no default. But we need a return value anyway
+    return ("Unknown");
+}
+
+} // local namespace
+
+
+namespace isc {
+namespace cryptolink {
+
+class HMACImpl {
+public:
+    explicit HMACImpl(const void* secret, size_t secret_len,
+                      const HashAlgorithm hash_algorithm) {
+        Botan::HashFunction* hash;
+        try {
+            hash = Botan::get_hash(
+                getBotanHashAlgorithmName(hash_algorithm));
+        } catch (const Botan::Algorithm_Not_Found&) {
+            isc_throw(isc::cryptolink::UnsupportedAlgorithm,
+                      "Unknown hash algorithm: " + hash_algorithm);
+        } catch (const Botan::Exception& exc) {
+            isc_throw(isc::cryptolink::LibraryError, exc.what());
+        }
+
+        hmac_.reset(new Botan::HMAC(hash));
+
+        // If the key length is larger than the block size, we hash the
+        // key itself first.
+        try {
+            if (secret_len > hash->HASH_BLOCK_SIZE) {
+                Botan::SecureVector<Botan::byte> hashed_key =
+                    hash->process(static_cast<const Botan::byte*>(secret),
+                                  secret_len);
+                hmac_->set_key(hashed_key.begin(), hashed_key.size());
+            } else {
+                hmac_->set_key(static_cast<const Botan::byte*>(secret),
+                               secret_len);
+            }
+        } catch (const Botan::Invalid_Key_Length& ikl) {
+            isc_throw(BadKey, ikl.what());
+        } catch (const Botan::Exception& exc) {
+            isc_throw(isc::cryptolink::LibraryError, exc.what());
+        }
+    }
+
+    ~HMACImpl() { }
+
+    size_t getOutputLength() const {
+        return (hmac_->OUTPUT_LENGTH);
+    }
+
+    void update(const void* data, const size_t len) {
+        try {
+            hmac_->update(static_cast<const Botan::byte*>(data), len);
+        } catch (const Botan::Exception& exc) {
+            isc_throw(isc::cryptolink::LibraryError, exc.what());
+        }
+    }
+
+    void sign(isc::util::OutputBuffer& result, size_t len) {
+        try {
+            Botan::SecureVector<Botan::byte> b_result(hmac_->final());
+
+            if (len == 0 || len > b_result.size()) {
+                len = b_result.size();
+            }
+            result.writeData(b_result.begin(), len);
+        } catch (const Botan::Exception& exc) {
+            isc_throw(isc::cryptolink::LibraryError, exc.what());
+        }
+    }
+
+    void sign(void* result, size_t len) {
+        try {
+            Botan::SecureVector<Botan::byte> b_result(hmac_->final());
+            size_t output_size = getOutputLength();
+            if (output_size > len) {
+                output_size = len;
+            }
+            memcpy(result, b_result.begin(), output_size);
+        } catch (const Botan::Exception& exc) {
+            isc_throw(isc::cryptolink::LibraryError, exc.what());
+        }
+    }
+
+    std::vector<uint8_t> sign(size_t len) {
+        try {
+            Botan::SecureVector<Botan::byte> b_result(hmac_->final());
+            if (len == 0 || len > b_result.size()) {
+                return (std::vector<uint8_t>(b_result.begin(), b_result.end()));
+            } else {
+                return (std::vector<uint8_t>(b_result.begin(), &b_result[len]));
+            }
+        } catch (const Botan::Exception& exc) {
+            isc_throw(isc::cryptolink::LibraryError, exc.what());
+        }
+    }
+
+
+    bool verify(const void* sig, size_t len) {
+        // Botan's verify_mac checks if len matches the output_length,
+        // which causes it to fail for truncated signatures, so we do
+        // the check ourselves
+        try {
+            Botan::SecureVector<Botan::byte> our_mac = hmac_->final();
+            if (len == 0 || len > getOutputLength()) {
+                len = getOutputLength();
+            }
+            return (Botan::same_mem(&our_mac[0],
+                                    static_cast<const unsigned char*>(sig),
+                                    len));
+        } catch (const Botan::Exception& exc) {
+            isc_throw(isc::cryptolink::LibraryError, exc.what());
+        }
+    }
+
+private:
+    boost::scoped_ptr<Botan::HMAC> hmac_;
+};
+
+HMAC::HMAC(const void* secret, size_t secret_length,
+           const HashAlgorithm hash_algorithm)
+{
+    impl_ = new HMACImpl(secret, secret_length, hash_algorithm);
+}
+
+HMAC::~HMAC() {
+    delete impl_;
+}
+
+size_t
+HMAC::getOutputLength() const {
+    return (impl_->getOutputLength());
+}
+
+void
+HMAC::update(const void* data, const size_t len) {
+    impl_->update(data, len);
+}
+
+void
+HMAC::sign(isc::util::OutputBuffer& result, size_t len) {
+    impl_->sign(result, len);
+}
+
+void
+HMAC::sign(void* result, size_t len) {
+    impl_->sign(result, len);
+}
+
+std::vector<uint8_t>
+HMAC::sign(size_t len) {
+    return impl_->sign(len);
+}
+
+bool
+HMAC::verify(const void* sig, const size_t len) {
+    return (impl_->verify(sig, len));
+}
+
+void
+signHMAC(const void* data, size_t data_len, const void* secret,
+         size_t secret_len, const HashAlgorithm hash_algorithm,
+         isc::util::OutputBuffer& result, size_t len)
+{
+    boost::scoped_ptr<HMAC> hmac(
+        CryptoLink::getCryptoLink().createHMAC(secret,
+                                               secret_len,
+                                               hash_algorithm));
+    hmac->update(data, data_len);
+    hmac->sign(result, len);
+}
+
+
+bool
+verifyHMAC(const void* data, const size_t data_len, const void* secret,
+           size_t secret_len, const HashAlgorithm hash_algorithm,
+           const void* sig, const size_t sig_len)
+{
+    boost::scoped_ptr<HMAC> hmac(
+        CryptoLink::getCryptoLink().createHMAC(secret,
+                                               secret_len,
+                                               hash_algorithm));
+    hmac->update(data, data_len);
+    return (hmac->verify(sig, sig_len));
+}
+
+void
+deleteHMAC(HMAC* hmac) {
+    delete hmac;
+}
+
+} // namespace cryptolink
+} // namespace isc
diff --git a/src/lib/cryptolink/crypto_hmac.h b/src/lib/cryptolink/crypto_hmac.h
new file mode 100644
index 0000000..2eb0d0e
--- /dev/null
+++ b/src/lib/cryptolink/crypto_hmac.h
@@ -0,0 +1,209 @@
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <util/buffer.h>
+
+#include <boost/noncopyable.hpp>
+
+#include <cryptolink/cryptolink.h>
+
+#ifndef _ISC_CRYPTO_HMAC_H
+#define _ISC_CRYPTO_HMAC_H
+
+namespace isc {
+namespace cryptolink {
+
+/// Forward declaration, pimpl style
+class HMACImpl;
+
+/// \brief HMAC support
+///
+/// This class is used to create and verify HMAC signatures. Instances
+/// can be created with CryptoLink::createHMAC()
+///
+class HMAC : private boost::noncopyable {
+private:
+    /// \brief Constructor from a secret and a hash algorithm
+    ///
+    /// \exception UnsupportedAlgorithmException if the given algorithm
+    ///            is unknown or not supported by the underlying library
+    /// \exception InvalidKeyLength if the given key secret_len is bad
+    /// \exception LibraryError if there was any unexpected exception
+    ///                         in the underlying library
+    ///
+    /// Notes: if the secret is longer than the block size of its
+    /// algorithm, the constructor will run it through the hash
+    /// algorithm, and use the digest as the secret for this HMAC
+    /// operation
+    ///
+    /// \param secret The secret to sign with
+    /// \param len The length of the secret
+    /// \param hash_algorithm The hash algorithm
+    HMAC(const void* secret, size_t secret_len,
+         const HashAlgorithm hash_algorithm);
+
+    friend HMAC* CryptoLink::createHMAC(const void*, size_t,
+                                        const HashAlgorithm);
+
+public:
+    /// \brief Destructor
+    ~HMAC();
+
+    /// \brief Returns the output size of the digest
+    ///
+    /// \return output size of the digest
+    size_t getOutputLength() const;
+
+    /// \brief Add data to digest
+    ///
+    /// \exception LibraryError if there was any unexpected exception
+    ///                         in the underlying library
+    ///
+    /// \param data The data to add
+    /// \param len The size of the data
+    void update(const void* data, const size_t len);
+
+    /// \brief Calculate the final signature
+    ///
+    /// The result will be appended to the given outputbuffer
+    ///
+    /// \exception LibraryError if there was any unexpected exception
+    ///                         in the underlying library
+    ///
+    /// \param result The OutputBuffer to append the result to
+    /// \param len The number of bytes from the result to copy. If this
+    ///        value is smaller than the algorithms output size, the
+    ///        result will be truncated. If this value is larger, or 0
+    ///        (the default), it will be ignored
+    void sign(isc::util::OutputBuffer& result, size_t len = 0);
+
+    /// \brief Calculate the final signature
+    ///
+    /// len bytes of data from the result will be copied to *result
+    /// If len is larger than the output size, only output_size bytes
+    /// will be copied. If it is smaller, the output will be truncated
+    ///
+    /// \exception LibraryError if there was any unexpected exception
+    ///                         in the underlying library
+    ///
+    /// At least len bytes of data must be available for writing at
+    /// result
+    void sign(void* result, size_t len);
+
+    /// \brief Calculate the final signatre
+    ///
+    /// The result will be returned as a std::vector<uint8_t>
+    ///
+    /// \exception LibraryError if there was any unexpected exception
+    ///                         in the underlying library
+    ///
+    /// \param len The number of bytes from the result to copy. If this
+    ///        value is smaller than the algorithms output size, the
+    ///        result will be truncated. If this value is larger, or 0
+    ///        (the default), it will be ignored
+    /// \return a vector containing the signature
+    std::vector<uint8_t> sign(size_t len = 0);
+
+    /// \brief Verify an existing signature
+    ///
+    /// \exception LibraryError if there was any unexpected exception
+    ///                         in the underlying library
+    ///
+    /// \param sig The signature to verify
+    /// \param len The length of the signature. If this is non-zero,
+    ///            and smaller than the output length of the algorithm,
+    ///            only len bytes will be checked
+    /// \return true if the signature is correct, false otherwise
+    bool verify(const void* sig, size_t len);
+
+private:
+    HMACImpl* impl_;
+};
+
+/// \brief Create an HMAC signature for the given data
+///
+/// This is a convenience function that calculates the hmac signature,
+/// given a fixed amount of data. Internally it does the same as
+/// creating an HMAC object, feeding it the data, and calculating the
+/// resulting signature.
+///
+/// \exception UnsupportedAlgorithm if the given algorithm is unknown
+///            or not supported by the underlying library
+/// \exception BadKey if the given key secret_len is bad
+/// \exception LibraryError if there was any unexpected exception
+///                         in the underlying library
+///
+/// Notes: if the secret is longer than the block size of its
+/// algorithm, the constructor will run it through the hash
+/// algorithm, and use the digest as the secret for this HMAC
+/// operation
+///
+/// \param data The data to sign
+/// \param data_len The length of the data
+/// \param secret The secret to sign with
+/// \param secret_len The length of the secret
+/// \param hash_algorithm The hash algorithm
+/// \param result The signature will be appended to this buffer
+/// \param len If this is non-zero and less than the output size,
+///            the result will be truncated to len bytes
+void signHMAC(const void* data,
+              const size_t data_len,
+              const void* secret,
+              size_t secret_len,
+              const HashAlgorithm hash_algorithm,
+              isc::util::OutputBuffer& result,
+              size_t len = 0);
+
+/// \brief Verify an HMAC signature for the given data
+///
+/// This is a convenience function that verifies an hmac signature,
+/// given a fixed amount of data. Internally it does the same as
+/// creating an HMAC object, feeding it the data, and checking the
+/// resulting signature.
+///
+/// \exception UnsupportedAlgorithm if the given algorithm is unknown
+///            or not supported by the underlying library
+/// \exception BadKey if the given key secret_len is bad
+/// \exception LibraryError if there was any unexpected exception
+///                         in the underlying library
+///
+/// Notes: if the secret is longer than the block size of its
+/// algorithm, the constructor will run it through the hash
+/// algorithm, and use the digest as the secret for this HMAC
+/// operation
+///
+/// \param data The data to verify
+/// \param data_len The length of the data
+/// \param secret The secret to sign with
+/// \param secret_len The length of the secret
+/// \param hash_algorithm The hash algorithm
+/// \param sig The signature to verify
+/// \param sig_len The length of the signature
+/// \return True if the signature verifies, false if not
+bool verifyHMAC(const void* data,
+                const size_t data_len,
+                const void* secret,
+                size_t secret_len,
+                const HashAlgorithm hash_algorithm,
+                const void* sig,
+                const size_t sig_len);
+
+/// \brief Delete an HMAC object
+void deleteHMAC(HMAC* hmac);
+
+} // namespace cryptolink
+} // namespace isc
+
+#endif // __ISC_CRYPTO_HMAC
+
diff --git a/src/lib/cryptolink/cryptolink.cc b/src/lib/cryptolink/cryptolink.cc
new file mode 100644
index 0000000..d1c375d
--- /dev/null
+++ b/src/lib/cryptolink/cryptolink.cc
@@ -0,0 +1,69 @@
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <cryptolink/cryptolink.h>
+#include <cryptolink/crypto_hmac.h>
+
+#include <botan/botan.h>
+
+namespace isc {
+namespace cryptolink {
+
+// For Botan, we use the CryptoLink class object in RAII style
+class CryptoLinkImpl {
+private:
+    Botan::LibraryInitializer botan_init_;
+};
+
+CryptoLink::~CryptoLink() {
+    delete impl_;
+}
+
+CryptoLink&
+CryptoLink::getCryptoLink() {
+    CryptoLink& c = getCryptoLinkInternal();
+    if (c.impl_ == NULL) {
+        c.initialize();
+    }
+    return (c);
+}
+
+CryptoLink&
+CryptoLink::getCryptoLinkInternal() {
+    static CryptoLink instance;
+    return (instance);
+}
+
+void
+CryptoLink::initialize() {
+    CryptoLink& c = getCryptoLinkInternal();
+    if (c.impl_ == NULL) {
+        try {
+            c.impl_ = new CryptoLinkImpl();
+        } catch (const Botan::Exception& ex) {
+            isc_throw(InitializationError, ex.what());
+        }
+    }
+}
+
+HMAC*
+CryptoLink::createHMAC(const void* secret, size_t secret_len,
+                       const HashAlgorithm hash_algorithm)
+{
+    return (new HMAC(secret, secret_len, hash_algorithm));
+}
+
+} // namespace cryptolink
+} // namespace isc
+
diff --git a/src/lib/cryptolink/cryptolink.h b/src/lib/cryptolink/cryptolink.h
new file mode 100644
index 0000000..1583136
--- /dev/null
+++ b/src/lib/cryptolink/cryptolink.h
@@ -0,0 +1,204 @@
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#ifndef _ISC_CRYPTO_H
+#define _ISC_CRYPTO_H
+
+#include <string>
+#include <util/buffer.h>
+#include <exceptions/exceptions.h>
+
+#include <boost/noncopyable.hpp>
+#include <boost/scoped_ptr.hpp>
+
+#include <memory>
+
+namespace isc {
+namespace cryptolink {
+
+/// \brief Hash algorithm identifiers
+enum HashAlgorithm {
+    MD5 = 0,            ///< MD5
+    SHA1 = 1,           ///< SHA-1
+    SHA256 = 2,         ///< SHA-256
+    UNKNOWN_HASH = 3    ///< This value can be used in conversion
+                        ///  functions, to be returned when the
+                        ///  input is unknown (but a value MUST be
+                        ///  returned), for instance when the input
+                        ///  is a Name or a string, and the return
+                        ///  value is a HashAlgorithm.
+};
+
+// Forward declaration for createHMAC()
+class HMAC;
+
+/// General exception class that is the base for all crypto-related
+/// exceptions
+class CryptoLinkError : public Exception {
+public:
+    CryptoLinkError(const char* file, size_t line, const char* what) :
+        isc::Exception(file, line, what) {}
+};
+
+/// This exception is thrown if there was a problem initializing the
+/// crypto library
+class InitializationError : public CryptoLinkError {
+public:
+    InitializationError(const char* file, size_t line, const char* what) :
+        CryptoLinkError(file, line, what) {}
+};
+
+/// This exception is thrown when a cryptographic action is requested
+/// for an algorithm that is not supported by the underlying library.
+class UnsupportedAlgorithm : public CryptoLinkError {
+public:
+    UnsupportedAlgorithm(const char* file, size_t line, const char* what) :
+        CryptoLinkError(file, line, what) {}
+};
+
+/// This exception is thrown when the underlying library could not
+/// handle the key data.
+class BadKey : public CryptoLinkError {
+public:
+    BadKey(const char* file, size_t line, const char* what) :
+        CryptoLinkError(file, line, what) {}
+};
+
+/// This exception is raised when a general error that was not
+/// specifically caught is thrown by the underlying library. It
+/// is replaced by this one so as not have 'external' exceptions
+/// bubbling up
+class LibraryError : public CryptoLinkError {
+public:
+    LibraryError(const char* file, size_t line, const char* what) :
+        CryptoLinkError(file, line, what) {}
+};
+
+/// Forward declaration for pimpl
+class CryptoLinkImpl;
+
+/// \brief Singleton entry point and factory class
+///
+/// This is a singleton class that serves as the entry point to
+/// the underlying cryptography library, and as a factory for objects
+/// within the cryptolink library.
+///
+/// There is only one way to access it, through getCryptoLink(), which
+/// returns a reference to the initialized library. On the first call,
+/// it will be initialized automatically. You can however initialize it
+/// manually through a call to the initalize(), before your first call
+/// to getCryptoLink. Any subsequent call to initialize() will be a
+/// noop.
+///
+/// In order for the CryptoLink library to be sure that the underlying
+/// library has been initialized, and because we do not want to add
+/// such a check to every class and function within it, we have made
+/// the constructors of all classes within cryptolink private. This way
+/// a caller cannot instantiate an object before the library is
+/// initialized, but must use CryptoLink's create method (e.g.
+/// createHMAC()), which enforces (automatic) initialization.
+///
+/// In order for the CryptoLink class to be able to create objects that
+/// have private constructors, it is declared a friend class of these
+/// classes.
+///
+/// Since these factory functions return bare pointers, we also provide
+/// deleter functions for them (e.g. deleteHMAC()), so that a caller
+/// can use that to make sure it uses the correct delete operator (the
+/// one defined at compilation time of this library). A way to make
+/// sure you do not forget this, is to place the result of the create
+/// functions in a shared_ptr with the corresponding deleter function.
+///
+/// \note All other classes within cryptolink should have private
+/// constructors as well, and should have a factory function from
+/// CryptoLink, and a deleter function.
+///
+// Internal note: we can use this class later to initialize and manage
+// dynamic (PKCS#11) libs
+class CryptoLink : private boost::noncopyable {
+public:
+    /// \brief Returns a reference to the singleton instance
+    ///
+    /// If the library has not been initialized yet, it will be
+    /// initialized with some default values.
+    ///
+    /// Since this class is noncopyable, you must use the return
+    /// value directly, or store it in a reference variable.
+    ///
+    /// \exception InitializationError if initialization fails
+    ///
+    /// \return Reference to the singleton instance
+    static CryptoLink& getCryptoLink();
+
+    /// \brief Initialize the library manually
+    ///
+    /// If the library has already been initialized (either by a call
+    /// to initialize() or automatically in getCryptoLink()), this
+    /// function does nothing.
+    ///
+    /// \note A call to initialize() is not strictly necessary with
+    /// the current implementation.
+    ///
+    /// \exception InitializationError if initialization fails
+    ///
+    static void initialize();
+
+    /// \brief Factory function for HMAC objects
+    ///
+    /// CryptoLink objects cannot be constructed directly. This
+    /// function creates a new HMAC object usable for signing or
+    /// verification.
+    ///
+    /// The caller is responsible for deleting the object, and it is
+    /// therefore highly recommended to place the return value of this
+    /// function in a scoped_ptr or shared_ptr.
+    ///
+    /// Notes: if the secret is longer than the block size of its
+    /// algorithm, the constructor will run it through the hash
+    /// algorithm, and use the digest as the secret for this HMAC
+    /// operation
+    ///
+    /// If you want to safely delete objects created with this method,
+    /// you can use the function deleteHMAC() as defined in
+    /// crypto_hmac.h
+    ///
+    /// \exception UnsupportedAlgorithmException if the given algorithm
+    ///            is unknown or not supported by the underlying library
+    /// \exception InvalidKeyLength if the given key secret_len is bad
+    /// \exception LibraryError if there was any unexpected exception
+    ///                         in the underlying library
+    ///
+    /// \param secret The secret to sign with
+    /// \param secret_len The length of the secret
+    /// \param hash_algorithm The hash algorithm
+    HMAC* createHMAC(const void* secret, size_t secret_len,
+                     const HashAlgorithm hash_algorithm);
+
+private:
+    // To enable us to use an optional explicit initialization call,
+    // the 'real' instance getter is private
+    static CryptoLink& getCryptoLinkInternal();
+
+    // To prevent people constructing their own, we make the constructor
+    // private too.
+    CryptoLink() : impl_(NULL) {}
+    ~CryptoLink();
+
+    CryptoLinkImpl* impl_;
+};
+
+} // namespace cryptolink
+} // namespace isc
+
+#endif // _ISC_CRYPTO_H
diff --git a/src/lib/cryptolink/tests/Makefile.am b/src/lib/cryptolink/tests/Makefile.am
new file mode 100644
index 0000000..c8b5e26
--- /dev/null
+++ b/src/lib/cryptolink/tests/Makefile.am
@@ -0,0 +1,26 @@
+SUBDIRS = .
+
+AM_CPPFLAGS = -I$(top_builddir)/src/lib -I$(top_srcdir)/src/lib
+AM_CPPFLAGS += $(BOOST_INCLUDES)
+AM_CXXFLAGS = $(B10_CXXFLAGS)
+
+if USE_STATIC_LINK
+AM_LDFLAGS = -static
+endif
+
+CLEANFILES = *.gcno *.gcda
+
+TESTS =
+if HAVE_GTEST
+TESTS += run_unittests
+run_unittests_SOURCES = run_unittests.cc
+run_unittests_SOURCES += crypto_unittests.cc
+run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
+run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)
+run_unittests_LDADD = $(GTEST_LDADD)
+run_unittests_LDADD += $(top_builddir)/src/lib/cryptolink/libcryptolink.la
+run_unittests_LDADD += $(top_builddir)/src/lib/util/libutil.la
+run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
+endif
+
+noinst_PROGRAMS = $(TESTS)
diff --git a/src/lib/cryptolink/tests/crypto_unittests.cc b/src/lib/cryptolink/tests/crypto_unittests.cc
new file mode 100644
index 0000000..65018c6
--- /dev/null
+++ b/src/lib/cryptolink/tests/crypto_unittests.cc
@@ -0,0 +1,511 @@
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <config.h>
+#include <gtest/gtest.h>
+
+#include <cryptolink/cryptolink.h>
+#include <cryptolink/crypto_hmac.h>
+
+#include <util/buffer.h>
+#include <exceptions/exceptions.h>
+
+#include <boost/shared_ptr.hpp>
+
+using namespace isc::util;
+using namespace isc::cryptolink;
+
+namespace {
+    void checkData(const uint8_t* data, const uint8_t* expected,
+                   size_t len) {
+        for (size_t i = 0; i < len; ++i) {
+            ASSERT_EQ(expected[i], data[i]);
+        }
+    }
+
+    void checkBuffer(const OutputBuffer& buf, const uint8_t* expected,
+                     size_t len)
+    {
+        ASSERT_EQ(len, buf.getLength());
+        checkData(static_cast<const uint8_t*>(buf.getData()), expected,
+                  len);
+    }
+
+    // Sign and verify with the convenience functions
+    void doHMACTestConv(const std::string& data,
+                        const void* secret,
+                        size_t secret_len,
+                        const HashAlgorithm hash_algorithm,
+                        const uint8_t* expected_hmac,
+                        size_t hmac_len) {
+        OutputBuffer data_buf(data.size());
+        data_buf.writeData(data.c_str(), data.size());
+        OutputBuffer hmac_sig(0);
+
+        // Sign it
+        signHMAC(data_buf.getData(), data_buf.getLength(),
+                 secret, secret_len, hash_algorithm, hmac_sig, hmac_len);
+
+        // Check if the signature is what we expect
+        checkBuffer(hmac_sig, expected_hmac, hmac_len);
+
+        // Check whether we can verify it ourselves
+        EXPECT_TRUE(verifyHMAC(data_buf.getData(), data_buf.getLength(),
+                               secret, secret_len, hash_algorithm,
+                               hmac_sig.getData(),
+                               hmac_sig.getLength()));
+
+        // Change the sig by flipping the first octet, and check
+        // whether verification fails then
+        hmac_sig.writeUint8At(~hmac_sig[0], 0);
+        EXPECT_FALSE(verifyHMAC(data_buf.getData(), data_buf.getLength(),
+                               secret, secret_len, hash_algorithm,
+                               hmac_sig.getData(),
+                               hmac_sig.getLength()));
+    }
+
+    // Sign and verify with an instantiation of an HMAC object
+    void doHMACTestDirect(const std::string& data,
+                          const void* secret,
+                          size_t secret_len,
+                          const HashAlgorithm hash_algorithm,
+                          const uint8_t* expected_hmac,
+                          size_t hmac_len) {
+        OutputBuffer data_buf(data.size());
+        data_buf.writeData(data.c_str(), data.size());
+        OutputBuffer hmac_sig(1);
+        CryptoLink& crypto = CryptoLink::getCryptoLink();
+
+        // Sign it
+        boost::shared_ptr<HMAC> hmac_sign(crypto.createHMAC(secret,
+                                                            secret_len,
+                                                            hash_algorithm),
+                                          deleteHMAC);
+        hmac_sign->update(data_buf.getData(), data_buf.getLength());
+        hmac_sign->sign(hmac_sig, hmac_len);
+
+        // Check if the signature is what we expect
+        checkBuffer(hmac_sig, expected_hmac, hmac_len);
+
+        // Check whether we can verify it ourselves
+        boost::shared_ptr<HMAC> hmac_verify(crypto.createHMAC(secret,
+                                                              secret_len,
+                                                              hash_algorithm),
+                                            deleteHMAC);
+        hmac_verify->update(data_buf.getData(), data_buf.getLength());
+        EXPECT_TRUE(hmac_verify->verify(hmac_sig.getData(),
+                                        hmac_sig.getLength()));
+
+        // Change the sig by flipping the first octet, and check
+        // whether verification fails then
+        hmac_sig.writeUint8At(~hmac_sig[0], 0);
+        EXPECT_FALSE(hmac_verify->verify(hmac_sig.getData(),
+                                         hmac_sig.getLength()));
+    }
+
+    void doHMACTestVector(const std::string& data,
+                          const void* secret,
+                          size_t secret_len,
+                          const HashAlgorithm hash_algorithm,
+                          const uint8_t* expected_hmac,
+                          size_t hmac_len) {
+        CryptoLink& crypto = CryptoLink::getCryptoLink();
+        boost::shared_ptr<HMAC> hmac_sign(crypto.createHMAC(secret,
+                                                            secret_len,
+                                                            hash_algorithm),
+                                          deleteHMAC);
+        hmac_sign->update(data.c_str(), data.size());
+        std::vector<uint8_t> sig = hmac_sign->sign(hmac_len);
+        ASSERT_EQ(hmac_len, sig.size());
+        checkData(&sig[0], expected_hmac, hmac_len);
+
+        boost::shared_ptr<HMAC> hmac_verify(crypto.createHMAC(secret,
+                                                              secret_len,
+                                                              hash_algorithm),
+                                            deleteHMAC);
+        hmac_verify->update(data.c_str(), data.size());
+        EXPECT_TRUE(hmac_verify->verify(&sig[0], sig.size()));
+
+        sig[0] = ~sig[0];
+        EXPECT_FALSE(hmac_verify->verify(&sig[0], sig.size()));
+    }
+
+    void doHMACTestArray(const std::string& data,
+                         const void* secret,
+                         size_t secret_len,
+                         const HashAlgorithm hash_algorithm,
+                         const uint8_t* expected_hmac,
+                         size_t hmac_len) {
+        CryptoLink& crypto = CryptoLink::getCryptoLink();
+        boost::shared_ptr<HMAC> hmac_sign(crypto.createHMAC(secret,
+                                                            secret_len,
+                                                            hash_algorithm),
+                                          deleteHMAC);
+        hmac_sign->update(data.c_str(), data.size());
+
+        // note: this is not exception-safe, and can leak, but
+        // if there is an unexpected exception in the code below we
+        // have more important things to fix.
+        uint8_t* sig = new uint8_t[hmac_len];
+
+        hmac_sign->sign(sig, hmac_len);
+        checkData(sig, expected_hmac, hmac_len);
+
+        boost::shared_ptr<HMAC> hmac_verify(crypto.createHMAC(secret,
+                                                              secret_len,
+                                                              hash_algorithm),
+                                            deleteHMAC);
+        hmac_verify->update(data.c_str(), data.size());
+        EXPECT_TRUE(hmac_verify->verify(sig, hmac_len));
+
+        sig[0] = ~sig[0];
+        EXPECT_FALSE(hmac_verify->verify(sig, hmac_len));
+
+        delete[] sig;
+    }
+
+    void doHMACTest(const std::string& data,
+                    const void* secret,
+                    size_t secret_len,
+                    const HashAlgorithm hash_algorithm,
+                    const uint8_t* expected_hmac,
+                    size_t hmac_len) {
+        doHMACTestConv(data, secret, secret_len, hash_algorithm,
+                       expected_hmac, hmac_len);
+        doHMACTestDirect(data, secret, secret_len, hash_algorithm,
+                         expected_hmac, hmac_len);
+        doHMACTestVector(data, secret, secret_len, hash_algorithm,
+                         expected_hmac, hmac_len);
+        doHMACTestArray(data, secret, secret_len, hash_algorithm,
+                        expected_hmac, hmac_len);
+    }
+}
+
+//
+// Test values taken from RFC 2202
+//
+TEST(CryptoLinkTest, HMAC_MD5_RFC2202_SIGN) {
+    const uint8_t secret[] = { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+                               0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+                               0x0b, 0x0b };
+    const uint8_t hmac_expected[] = { 0x92, 0x94, 0x72, 0x7a, 0x36,
+                                      0x38, 0xbb, 0x1c, 0x13, 0xf4,
+                                      0x8e, 0xf8, 0x15, 0x8b, 0xfc,
+                                      0x9d };
+    doHMACTest("Hi There", secret, 16, MD5, hmac_expected, 16);
+
+    const uint8_t hmac_expected2[] = { 0x75, 0x0c, 0x78, 0x3e, 0x6a,
+                                       0xb0, 0xb5, 0x03, 0xea, 0xa8,
+                                       0x6e, 0x31, 0x0a, 0x5d, 0xb7,
+                                       0x38 };
+    doHMACTest("what do ya want for nothing?", "Jefe", 4, MD5,
+               hmac_expected2, 16);
+
+    const uint8_t secret3[] = { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+                                0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+                                0xaa, 0xaa, 0xaa, 0xaa };
+    const uint8_t hmac_expected3[] = { 0x56, 0xbe, 0x34, 0x52, 0x1d,
+                                       0x14, 0x4c, 0x88, 0xdb, 0xb8,
+                                       0xc7, 0x33, 0xf0, 0xe8, 0xb3,
+                                       0xf6};
+    doHMACTest(std::string(50, 0xdd), secret3, 16, MD5, hmac_expected3, 16);
+
+    const std::string data4(50, 0xcd);
+    const uint8_t secret4[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
+                                0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
+                                0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12,
+                                0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
+                                0x19 };
+    const uint8_t hmac_expected4[] = { 0x69, 0x7e, 0xaf, 0x0a, 0xca,
+                                       0x3a, 0x3a, 0xea, 0x3a, 0x75,
+                                       0x16, 0x47, 0x46, 0xff, 0xaa,
+                                       0x79 };
+    doHMACTest(data4, secret4, 25, MD5, hmac_expected4, 16);
+
+    const uint8_t secret5[] = { 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+                                0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+                                0x0c, 0x0c, 0x0c, 0x0c };
+    const uint8_t hmac_expected5[] = { 0x56, 0x46, 0x1e, 0xf2, 0x34,
+                                       0x2e, 0xdc, 0x00, 0xf9, 0xba,
+                                       0xb9, 0x95, 0x69, 0x0e, 0xfd,
+                                       0x4c };
+    doHMACTest("Test With Truncation", secret5, 16, MD5,
+               hmac_expected5, 16);
+    doHMACTest("Test With Truncation", secret5, 16, MD5,
+               hmac_expected5, 12);
+
+    const uint8_t hmac_expected6[] = { 0x6b, 0x1a, 0xb7, 0xfe, 0x4b,
+                                       0xd7, 0xbf, 0x8f, 0x0b, 0x62,
+                                       0xe6, 0xce, 0x61, 0xb9, 0xd0,
+                                       0xcd };
+    doHMACTest("Test Using Larger Than Block-Size Key - Hash Key First",
+               std::string(80, 0xaa).c_str(), 80, MD5, hmac_expected6, 16);
+
+    const uint8_t hmac_expected7[] = { 0x6f, 0x63, 0x0f, 0xad, 0x67,
+                                       0xcd, 0xa0, 0xee, 0x1f, 0xb1,
+                                       0xf5, 0x62, 0xdb, 0x3a, 0xa5,
+                                       0x3e };
+    doHMACTest("Test Using Larger Than Block-Size Key and Larger Than "
+               "One Block-Size Data",
+               std::string(80, 0xaa).c_str(), 80, MD5, hmac_expected7, 16);
+}
+
+//
+// Test values taken from RFC 2202
+//
+TEST(CryptoLinkTest, HMAC_SHA1_RFC2202_SIGN) {
+    const uint8_t secret[] = { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+                               0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+                               0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b };
+    const uint8_t hmac_expected[] = { 0xb6, 0x17, 0x31, 0x86, 0x55,
+                                      0x05, 0x72, 0x64, 0xe2, 0x8b,
+                                      0xc0, 0xb6, 0xfb, 0x37, 0x8c,
+                                      0x8e, 0xf1, 0x46, 0xbe, 0x00 };
+    doHMACTest("Hi There", secret, 20, SHA1, hmac_expected, 20);
+
+    const uint8_t hmac_expected2[] = { 0xef, 0xfc, 0xdf, 0x6a, 0xe5,
+                                       0xeb, 0x2f, 0xa2, 0xd2, 0x74,
+                                       0x16, 0xd5, 0xf1, 0x84, 0xdf,
+                                       0x9c, 0x25, 0x9a, 0x7c, 0x79 };
+    doHMACTest("what do ya want for nothing?", "Jefe", 4, SHA1,
+               hmac_expected2, 20);
+
+    const uint8_t secret3[] = { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+                                0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+                                0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+                                0xaa, 0xaa };
+    const uint8_t hmac_expected3[] = { 0x12, 0x5d, 0x73, 0x42, 0xb9,
+                                       0xac, 0x11, 0xcd, 0x91, 0xa3,
+                                       0x9a, 0xf4, 0x8a, 0xa1, 0x7b,
+                                       0x4f, 0x63, 0xf1, 0x75, 0xd3 };
+    doHMACTest(std::string(50, 0xdd), secret3, 20, SHA1, hmac_expected3, 20);
+
+    const uint8_t secret4[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
+                                0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
+                                0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12,
+                                0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
+                                0x19 };
+    const uint8_t hmac_expected4[] = { 0x4c, 0x90, 0x07, 0xf4, 0x02,
+                                       0x62, 0x50, 0xc6, 0xbc, 0x84,
+                                       0x14, 0xf9, 0xbf, 0x50, 0xc8,
+                                       0x6c, 0x2d, 0x72, 0x35, 0xda };
+    doHMACTest(std::string(50, 0xcd), secret4, 25, SHA1, hmac_expected4, 20);
+
+    const uint8_t secret5[] = { 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+                                0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+                                0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+                                0x0c, 0x0c };
+    const uint8_t hmac_expected5[] = { 0x4c, 0x1a, 0x03, 0x42, 0x4b,
+                                       0x55, 0xe0, 0x7f, 0xe7, 0xf2,
+                                       0x7b, 0xe1, 0xd5, 0x8b, 0xb9,
+                                       0x32, 0x4a, 0x9a, 0x5a, 0x04 };
+    doHMACTest("Test With Truncation", secret5, 20, SHA1,
+               hmac_expected5, 20);
+    doHMACTest("Test With Truncation", secret5, 20, SHA1,
+               hmac_expected5, 12);
+
+    const uint8_t hmac_expected6[] = { 0xaa, 0x4a, 0xe5, 0xe1, 0x52,
+                                       0x72, 0xd0, 0x0e, 0x95, 0x70,
+                                       0x56, 0x37, 0xce, 0x8a, 0x3b,
+                                       0x55, 0xed, 0x40, 0x21, 0x12 };
+    doHMACTest("Test Using Larger Than Block-Size Key - Hash Key First",
+               std::string(80, 0xaa).c_str(), 80, SHA1, hmac_expected6, 20);
+
+    const uint8_t hmac_expected7[] = { 0xe8, 0xe9, 0x9d, 0x0f, 0x45,
+                                       0x23, 0x7d, 0x78, 0x6d, 0x6b,
+                                       0xba, 0xa7, 0x96, 0x5c, 0x78,
+                                       0x08, 0xbb, 0xff, 0x1a, 0x91 };
+    doHMACTest("Test Using Larger Than Block-Size Key and Larger Than "
+               "One Block-Size Data",
+               std::string(80, 0xaa).c_str(), 80, SHA1, hmac_expected7, 20);
+}
+
+//
+// Test values taken from RFC 4231
+//
+TEST(CryptoLinkTest, HMAC_SHA256_RFC2202_SIGN) {
+    const uint8_t secret[] = { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+                               0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+                               0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b };
+    const uint8_t hmac_expected[] = { 0xb0, 0x34, 0x4c, 0x61, 0xd8,
+                                      0xdb, 0x38, 0x53, 0x5c, 0xa8,
+                                      0xaf, 0xce, 0xaf, 0x0b, 0xf1,
+                                      0x2b, 0x88, 0x1d, 0xc2, 0x00,
+                                      0xc9, 0x83, 0x3d, 0xa7, 0x26,
+                                      0xe9, 0x37, 0x6c, 0x2e, 0x32,
+                                      0xcf, 0xf7 };
+    doHMACTest("Hi There", secret, 20, SHA256, hmac_expected, 32);
+
+    const uint8_t hmac_expected2[] = { 0x5b, 0xdc, 0xc1, 0x46, 0xbf,
+                                       0x60, 0x75, 0x4e, 0x6a, 0x04,
+                                       0x24, 0x26, 0x08, 0x95, 0x75,
+                                       0xc7, 0x5a, 0x00, 0x3f, 0x08,
+                                       0x9d, 0x27, 0x39, 0x83, 0x9d,
+                                       0xec, 0x58, 0xb9, 0x64, 0xec,
+                                       0x38, 0x43 };
+    doHMACTest("what do ya want for nothing?", "Jefe", 4, SHA256,
+               hmac_expected2, 32);
+
+    const uint8_t secret3[] = { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+                                0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+                                0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+                                0xaa, 0xaa };
+    const uint8_t hmac_expected3[] = { 0x77, 0x3e, 0xa9, 0x1e, 0x36,
+                                       0x80, 0x0e, 0x46, 0x85, 0x4d,
+                                       0xb8, 0xeb, 0xd0, 0x91, 0x81,
+                                       0xa7, 0x29, 0x59, 0x09, 0x8b,
+                                       0x3e, 0xf8, 0xc1, 0x22, 0xd9,
+                                       0x63, 0x55, 0x14, 0xce, 0xd5,
+                                       0x65, 0xfe };
+    doHMACTest(std::string(50, 0xdd), secret3, 20, SHA256, hmac_expected3, 32);
+
+    const uint8_t secret4[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
+                                0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
+                                0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12,
+                                0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
+                                0x19 };
+    const uint8_t hmac_expected4[] = { 0x82, 0x55, 0x8a, 0x38, 0x9a,
+                                       0x44, 0x3c, 0x0e, 0xa4, 0xcc,
+                                       0x81, 0x98, 0x99, 0xf2, 0x08,
+                                       0x3a, 0x85, 0xf0, 0xfa, 0xa3,
+                                       0xe5, 0x78, 0xf8, 0x07, 0x7a,
+                                       0x2e, 0x3f, 0xf4, 0x67, 0x29,
+                                       0x66, 0x5b };
+    doHMACTest(std::string(50, 0xcd), secret4, 25, SHA256, hmac_expected4, 32);
+
+    const uint8_t secret5[] = { 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+                                0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+                                0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+                                0x0c, 0x0c };
+    const uint8_t hmac_expected5[] = { 0xa3, 0xb6, 0x16, 0x74, 0x73,
+                                       0x10, 0x0e, 0xe0, 0x6e, 0x0c,
+                                       0x79, 0x6c, 0x29, 0x55, 0x55,
+                                       0x2b };
+    doHMACTest("Test With Truncation", secret5, 20, SHA256,
+               hmac_expected5, 16);
+
+    const uint8_t hmac_expected6[] = { 0x60, 0xe4, 0x31, 0x59, 0x1e,
+                                       0xe0, 0xb6, 0x7f, 0x0d, 0x8a,
+                                       0x26, 0xaa, 0xcb, 0xf5, 0xb7,
+                                       0x7f, 0x8e, 0x0b, 0xc6, 0x21,
+                                       0x37, 0x28, 0xc5, 0x14, 0x05,
+                                       0x46, 0x04, 0x0f, 0x0e, 0xe3,
+                                       0x7f, 0x54 };
+    doHMACTest("Test Using Larger Than Block-Size Key - Hash Key First",
+               std::string(131, 0xaa).c_str(), 131, SHA256, hmac_expected6, 32);
+
+    const uint8_t hmac_expected7[] = { 0x9b, 0x09, 0xff, 0xa7, 0x1b,
+                                       0x94, 0x2f, 0xcb, 0x27, 0x63,
+                                       0x5f, 0xbc, 0xd5, 0xb0, 0xe9,
+                                       0x44, 0xbf, 0xdc, 0x63, 0x64,
+                                       0x4f, 0x07, 0x13, 0x93, 0x8a,
+                                       0x7f, 0x51, 0x53, 0x5c, 0x3a,
+                                       0x35, 0xe2 };
+    doHMACTest("This is a test using a larger than block-size key and a"
+               " larger than block-size data. The key needs to be hashe"
+               "d before being used by the HMAC algorithm.",
+               std::string(131, 0xaa).c_str(), 131, SHA256, hmac_expected7, 32);
+}
+
+namespace {
+    size_t
+    sigVectorLength(HashAlgorithm alg, size_t len) {
+        boost::shared_ptr<HMAC> hmac_sign(
+            CryptoLink::getCryptoLink().createHMAC("asdf", 4, alg),
+            deleteHMAC);
+        hmac_sign->update("asdf", 4);
+        const std::vector<uint8_t> sig = hmac_sign->sign(len);
+        return (sig.size());
+    }
+
+    size_t
+    sigBufferLength(HashAlgorithm alg, size_t len) {
+        boost::shared_ptr<HMAC> hmac_sign(
+            CryptoLink::getCryptoLink().createHMAC("asdf", 4, alg),
+            deleteHMAC);
+        hmac_sign->update("asdf", 4);
+        OutputBuffer sig(0);
+        hmac_sign->sign(sig, len);
+        return (sig.getLength());
+    }
+}
+
+TEST(CryptoLinkTest, HMACSigLengthArgument) {
+    std::vector<uint8_t> sig;
+
+    EXPECT_EQ(16, sigVectorLength(MD5, 0));
+    EXPECT_EQ(8, sigVectorLength(MD5, 8));
+    EXPECT_EQ(16, sigVectorLength(MD5, 16));
+    EXPECT_EQ(16, sigVectorLength(MD5, 40));
+    EXPECT_EQ(16, sigVectorLength(MD5, 2000));
+
+    EXPECT_EQ(20, sigBufferLength(SHA1, 0));
+    EXPECT_EQ(8, sigBufferLength(SHA1, 8));
+    EXPECT_EQ(20, sigBufferLength(SHA1, 20));
+    EXPECT_EQ(20, sigBufferLength(SHA1, 40));
+    EXPECT_EQ(20, sigBufferLength(SHA1, 2000));
+
+    EXPECT_EQ(32, sigBufferLength(SHA256, 0));
+    EXPECT_EQ(8, sigBufferLength(SHA256, 8));
+    EXPECT_EQ(32, sigBufferLength(SHA256, 32));
+    EXPECT_EQ(32, sigBufferLength(SHA256, 40));
+    EXPECT_EQ(32, sigBufferLength(SHA256, 3200));
+
+    EXPECT_EQ(16, sigBufferLength(MD5, 0));
+    EXPECT_EQ(8, sigBufferLength(MD5, 8));
+    EXPECT_EQ(16, sigBufferLength(MD5, 16));
+    EXPECT_EQ(16, sigBufferLength(MD5, 40));
+    EXPECT_EQ(16, sigBufferLength(MD5, 2000));
+
+    EXPECT_EQ(20, sigBufferLength(SHA1, 0));
+    EXPECT_EQ(8, sigBufferLength(SHA1, 8));
+    EXPECT_EQ(20, sigBufferLength(SHA1, 20));
+    EXPECT_EQ(20, sigBufferLength(SHA1, 40));
+    EXPECT_EQ(20, sigBufferLength(SHA1, 2000));
+
+    EXPECT_EQ(32, sigBufferLength(SHA256, 0));
+    EXPECT_EQ(8, sigBufferLength(SHA256, 8));
+    EXPECT_EQ(32, sigBufferLength(SHA256, 32));
+    EXPECT_EQ(32, sigBufferLength(SHA256, 40));
+    EXPECT_EQ(32, sigBufferLength(SHA256, 3200));
+}
+
+TEST(CryptoLinkTest, BadKey) {
+    OutputBuffer data_buf(0);
+    OutputBuffer hmac_sig(0);
+    CryptoLink& crypto = CryptoLink::getCryptoLink();
+
+    EXPECT_THROW(crypto.createHMAC(NULL, 0, MD5), BadKey);
+    EXPECT_THROW(crypto.createHMAC(NULL, 0, UNKNOWN_HASH), UnsupportedAlgorithm);
+
+    EXPECT_THROW(signHMAC(data_buf.getData(), data_buf.getLength(),
+                          NULL, 0, MD5, hmac_sig), BadKey);
+    EXPECT_THROW(signHMAC(data_buf.getData(), data_buf.getLength(),
+                          NULL, 0, UNKNOWN_HASH, hmac_sig),
+                          UnsupportedAlgorithm);
+
+    EXPECT_THROW(verifyHMAC(data_buf.getData(), data_buf.getLength(),
+                            NULL, 0, MD5, hmac_sig.getData(),
+                            hmac_sig.getLength()), BadKey);
+    EXPECT_THROW(verifyHMAC(data_buf.getData(), data_buf.getLength(),
+                            NULL, 0, UNKNOWN_HASH, hmac_sig.getData(),
+                            hmac_sig.getLength()),
+                            UnsupportedAlgorithm);
+}
+
+TEST(CryptoLinkTest, Singleton) {
+    const CryptoLink& c1 = CryptoLink::getCryptoLink();
+    const CryptoLink& c2 = CryptoLink::getCryptoLink();
+    ASSERT_EQ(&c1, &c2);
+}
diff --git a/src/lib/cryptolink/tests/run_unittests.cc b/src/lib/cryptolink/tests/run_unittests.cc
new file mode 100644
index 0000000..d16327e
--- /dev/null
+++ b/src/lib/cryptolink/tests/run_unittests.cc
@@ -0,0 +1,22 @@
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <gtest/gtest.h>
+
+int
+main(int argc, char* argv[]) {
+    ::testing::InitGoogleTest(&argc, argv);
+
+    return (RUN_ALL_TESTS());
+}
diff --git a/src/lib/datasrc/data_source.cc b/src/lib/datasrc/data_source.cc
index 90e1dd7..548a811 100644
--- a/src/lib/datasrc/data_source.cc
+++ b/src/lib/datasrc/data_source.cc
@@ -354,7 +354,19 @@ doQueryTask(QueryTask& task, ZoneInfo& zoneinfo, RRsetList& target) {
     HotCache& cache = task.q.getCache();
     RRsetPtr rrset;
 
-    // First, check the cache for matching data
+    // First off, make sure at least we have a matching zone in some data
+    // source.  We must do this before checking the cache, because it can
+    // happen that the matching zone has been removed after an RRset of that
+    // zone is cached.  Such inconsistency will cause various problems,
+    // including a crash.
+    const DataSrc* ds = zoneinfo.getDataSource();
+    const Name* const zonename = zoneinfo.getEnclosingZone();
+    if (ds == NULL) {
+        task.flags |= DataSrc::NO_SUCH_ZONE;
+        return (DataSrc::SUCCESS);
+    }
+
+    // Then check the cache for matching data
     if (checkCache(task, target)) {
         return (DataSrc::SUCCESS);
     }
@@ -362,13 +374,6 @@ doQueryTask(QueryTask& task, ZoneInfo& zoneinfo, RRsetList& target) {
     // Requested data weren't in the cache (or were, but had expired),
     // so now we proceed with the low-level data source lookup, and cache
     // whatever we find.
-    const DataSrc* ds = zoneinfo.getDataSource();
-    const Name* const zonename = zoneinfo.getEnclosingZone();
-
-    if (ds == NULL) {
-        task.flags |= DataSrc::NO_SUCH_ZONE;
-        return (DataSrc::SUCCESS);
-    }
 
     DataSrc::Result result;
     switch (task.op) {
diff --git a/src/lib/datasrc/tests/datasrc_unittest.cc b/src/lib/datasrc/tests/datasrc_unittest.cc
index 01de77a..cd1a40c 100644
--- a/src/lib/datasrc/tests/datasrc_unittest.cc
+++ b/src/lib/datasrc/tests/datasrc_unittest.cc
@@ -1092,6 +1092,22 @@ TEST_F(DataSrcTest, DISABLED_synthesizedCnameTooLong) {
         RRClass::IN(), RRType::A());
 }
 
+TEST_F(DataSrcTest, cacheDataInNonexistentZone) {
+    // This test emulates the situation where an RRset in some zone of some
+    // data source is cached and then the zone is removed from the data source.
+    // When there is such a substantial inconsistency between the cache and
+    // the real data source, we should honor the latter.  More important,
+    // the inconsistency shouldn't cause any disruption such as a crash.
+
+    const Name qname("nosuchzone.example");
+    RRsetPtr rrset(new RRset(qname, RRClass::IN(), RRType::A(), RRTTL(0)));
+    cache.addPositive(rrset, DataSrc::REFERRAL);
+
+    createAndProcessQuery(qname, RRClass::IN(), RRType::A(), false);
+    headerCheck(msg, qid, Rcode::REFUSED(), opcodeval, QR_FLAG | RD_FLAG,
+                1, 0, 0, 0);
+}
+
 // Tests of the DataSrcMatch class start here
 class DataSrcMatchTest : public ::testing::Test {
 protected:
diff --git a/src/lib/dns/Makefile.am b/src/lib/dns/Makefile.am
index 5a7151e..887ac09 100644
--- a/src/lib/dns/Makefile.am
+++ b/src/lib/dns/Makefile.am
@@ -17,48 +17,52 @@ EXTRA_DIST += rrtype-placeholder.h
 # NOTE: when an rdata file is added, please also add to this list:
 EXTRA_DIST += rdata/any_255/tsig_250.cc
 EXTRA_DIST += rdata/any_255/tsig_250.h
-EXTRA_DIST += rdata/in_1/aaaa_28.cc
-EXTRA_DIST += rdata/in_1/aaaa_28.h
-EXTRA_DIST += rdata/in_1/a_1.cc
-EXTRA_DIST += rdata/in_1/a_1.h
 EXTRA_DIST += rdata/ch_3/a_1.cc
 EXTRA_DIST += rdata/ch_3/a_1.h
-EXTRA_DIST += rdata/generic/mx_15.h
-EXTRA_DIST += rdata/generic/rrsig_46.cc
+EXTRA_DIST += rdata/generic/cname_5.cc
+EXTRA_DIST += rdata/generic/cname_5.h
+EXTRA_DIST += rdata/generic/detail/nsec_bitmap.cc
+EXTRA_DIST += rdata/generic/detail/nsec_bitmap.h
 EXTRA_DIST += rdata/generic/dname_39.cc
-EXTRA_DIST += rdata/generic/rrsig_46.h
 EXTRA_DIST += rdata/generic/dname_39.h
-EXTRA_DIST += rdata/generic/ns_2.cc
-EXTRA_DIST += rdata/generic/nsec_47.cc
-EXTRA_DIST += rdata/generic/ns_2.h
-EXTRA_DIST += rdata/generic/nsec_47.h
-EXTRA_DIST += rdata/generic/opt_41.cc
-EXTRA_DIST += rdata/generic/soa_6.cc
-EXTRA_DIST += rdata/generic/cname_5.cc
 EXTRA_DIST += rdata/generic/dnskey_48.cc
-EXTRA_DIST += rdata/generic/opt_41.h
-EXTRA_DIST += rdata/generic/soa_6.h
-EXTRA_DIST += rdata/generic/cname_5.h
 EXTRA_DIST += rdata/generic/dnskey_48.h
 EXTRA_DIST += rdata/generic/ds_43.cc
 EXTRA_DIST += rdata/generic/ds_43.h
-EXTRA_DIST += rdata/generic/txt_16.cc
-EXTRA_DIST += rdata/generic/txt_16.h
 EXTRA_DIST += rdata/generic/mx_15.cc
-EXTRA_DIST += rdata/generic/nsec3param_51.h
-EXTRA_DIST += rdata/generic/nsec3param_51.cc
+EXTRA_DIST += rdata/generic/mx_15.h
+EXTRA_DIST += rdata/generic/ns_2.cc
+EXTRA_DIST += rdata/generic/ns_2.h
 EXTRA_DIST += rdata/generic/nsec3_50.cc
 EXTRA_DIST += rdata/generic/nsec3_50.h
+EXTRA_DIST += rdata/generic/nsec3param_51.cc
+EXTRA_DIST += rdata/generic/nsec3param_51.h
+EXTRA_DIST += rdata/generic/nsec_47.cc
+EXTRA_DIST += rdata/generic/nsec_47.h
+EXTRA_DIST += rdata/generic/opt_41.cc
+EXTRA_DIST += rdata/generic/opt_41.h
 EXTRA_DIST += rdata/generic/ptr_12.cc
 EXTRA_DIST += rdata/generic/ptr_12.h
+EXTRA_DIST += rdata/generic/rp_17.cc
+EXTRA_DIST += rdata/generic/rp_17.h
+EXTRA_DIST += rdata/generic/rrsig_46.cc
+EXTRA_DIST += rdata/generic/rrsig_46.h
+EXTRA_DIST += rdata/generic/soa_6.cc
+EXTRA_DIST += rdata/generic/soa_6.h
+EXTRA_DIST += rdata/generic/txt_16.cc
+EXTRA_DIST += rdata/generic/txt_16.h
 EXTRA_DIST += rdata/hs_4/a_1.cc
 EXTRA_DIST += rdata/hs_4/a_1.h
+EXTRA_DIST += rdata/in_1/a_1.cc
+EXTRA_DIST += rdata/in_1/a_1.h
+EXTRA_DIST += rdata/in_1/aaaa_28.cc
+EXTRA_DIST += rdata/in_1/aaaa_28.h
 #EXTRA_DIST += rdata/template.cc
 #EXTRA_DIST += rdata/template.h
 
 # auto-generate by gen-rdatacode.py:
 BUILT_SOURCES = rrclass.h rrtype.h rrparamregistry.cc
-#TODO: check this###BUILT_SOURCES = rdataclass.h rdataclass.cc
+BUILT_SOURCES += rdataclass.h rdataclass.cc
 
 lib_LTLIBRARIES = libdns++.la
 
@@ -80,15 +84,22 @@ libdns___la_SOURCES += rrsetlist.h rrsetlist.cc
 libdns___la_SOURCES += rrttl.h rrttl.cc
 libdns___la_SOURCES += rrtype.cc
 libdns___la_SOURCES += question.h question.cc
+libdns___la_SOURCES += tsig.h tsig.cc
+libdns___la_SOURCES += tsigerror.h tsigerror.cc
 libdns___la_SOURCES += tsigkey.h tsigkey.cc
+libdns___la_SOURCES += tsigrecord.h tsigrecord.cc
 libdns___la_SOURCES += rdata/generic/detail/nsec_bitmap.h
 libdns___la_SOURCES += rdata/generic/detail/nsec_bitmap.cc
 
 libdns___la_CPPFLAGS = $(AM_CPPFLAGS)
-libdns___la_LIBADD = $(top_builddir)/src/lib/util/libutil.la
+# Most applications of libdns++ will only implicitly rely on libcryptolink,
+# so we add the dependency here so that the applications don't have to link
+# libcryptolink explicitly.
+libdns___la_LIBADD = $(top_builddir)/src/lib/cryptolink/libcryptolink.la
+libdns___la_LIBADD += $(top_builddir)/src/lib/util/libutil.la
 
-nodist_libdns___la_SOURCES = rdataclass.cc rrclass.h rrtype.h
-nodist_libdns___la_SOURCES += rrparamregistry.cc
+nodist_libdns___include_HEADERS = rdataclass.h rrclass.h rrtype.h
+nodist_libdns___la_SOURCES = rdataclass.cc rrparamregistry.cc
 
 rrclass.h: rrclass-placeholder.h
 rrtype.h: rrtype-placeholder.h
@@ -106,13 +117,10 @@ libdns___include_HEADERS = \
 	question.h \
 	rcode.h \
 	rdata.h \
-	rdataclass.h \
-	rrclass.h \
 	rrparamregistry.h \
 	rrset.h \
 	rrsetlist.h \
 	rrttl.h \
-	rrtype.h \
 	tsigkey.h
 # Purposely not installing these headers:
 # util/*.h: used only internally, and not actually DNS specific
diff --git a/src/lib/dns/edns.cc b/src/lib/dns/edns.cc
index 5405dab..447b479 100644
--- a/src/lib/dns/edns.cc
+++ b/src/lib/dns/edns.cc
@@ -110,19 +110,25 @@ EDNS::toText() const {
     return (ret);
 }
 
+namespace {
+/// Helper function to define unified implementation for the public versions
+/// of toWire().
 template <typename Output>
 int
-EDNS::toWire(Output& output, const uint8_t extended_rcode) const {
+toWireCommon(Output& output, const uint8_t version,
+             const uint16_t udp_size, const bool dnssec_aware,
+             const uint8_t extended_rcode)
+{
     // Render EDNS OPT RR
     uint32_t extrcode_flags = extended_rcode << EXTRCODE_SHIFT;
-    extrcode_flags |= (version_ << VERSION_SHIFT) & VERSION_MASK;
-    if (dnssec_aware_) {
+    extrcode_flags |= (version << VERSION_SHIFT) & VERSION_MASK;
+    if (dnssec_aware) {
         extrcode_flags |= EXTFLAG_DO;
     }
 
     // Construct an RRset corresponding to the EDNS.
     // We don't support any options for now, so the OPT RR can be empty.
-    RRsetPtr edns_rrset(new RRset(Name::ROOT_NAME(), RRClass(udp_size_),
+    RRsetPtr edns_rrset(new RRset(Name::ROOT_NAME(), RRClass(udp_size),
                                   RRType::OPT(), RRTTL(extrcode_flags)));
     edns_rrset->addRdata(ConstRdataPtr(new generic::OPT()));
 
@@ -130,9 +136,12 @@ EDNS::toWire(Output& output, const uint8_t extended_rcode) const {
 
     return (1);
 }
+}
 
 unsigned int
-EDNS::toWire(MessageRenderer& renderer, const uint8_t extended_rcode) const {
+EDNS::toWire(AbstractMessageRenderer& renderer,
+             const uint8_t extended_rcode) const
+{
     // If adding the OPT RR would exceed the size limit, don't do it.
     // 11 = len(".") + type(2byte) + class(2byte) + TTL(4byte) + RDLEN(2byte)
     // (RDATA is empty in this simple implementation)
@@ -140,12 +149,16 @@ EDNS::toWire(MessageRenderer& renderer, const uint8_t extended_rcode) const {
         return (0);
     }
 
-    return (toWire<MessageRenderer>(renderer, extended_rcode));
+    return (toWireCommon(renderer, version_, udp_size_, dnssec_aware_,
+                         extended_rcode));
 }
 
 unsigned int
-EDNS::toWire(isc::util::OutputBuffer& buffer, const uint8_t extended_rcode) const {
-    return (toWire<isc::util::OutputBuffer>(buffer, extended_rcode));
+EDNS::toWire(isc::util::OutputBuffer& buffer,
+             const uint8_t extended_rcode) const
+{
+    return (toWireCommon(buffer, version_, udp_size_, dnssec_aware_,
+                         extended_rcode));
 }
 
 EDNS*
diff --git a/src/lib/dns/edns.h b/src/lib/dns/edns.h
index b794183..a7bc4c4 100644
--- a/src/lib/dns/edns.h
+++ b/src/lib/dns/edns.h
@@ -32,7 +32,7 @@ namespace dns {
 
 class EDNS;
 class Name;
-class MessageRenderer;
+class AbstractMessageRenderer;
 class RRClass;
 class RRTTL;
 class RRType;
@@ -314,7 +314,7 @@ public:
     /// \param extended_rcode Upper 8 bits of extended RCODE to be rendered as
     /// part of the EDNS OPT RR.
     /// \return 1 if the OPT RR fits in the message size limit; otherwise 0.
-    unsigned int toWire(MessageRenderer& renderer,
+    unsigned int toWire(AbstractMessageRenderer& renderer,
                         const uint8_t extended_rcode) const;
 
     /// \brief Render the \c EDNS in the wire format.
@@ -354,12 +354,6 @@ public:
     // something like this.
     //void addOption();
 
-private:
-    /// Helper method to define unified implementation for the public versions
-    /// of toWire().
-    template <typename Output>
-    int toWire(Output& output, const uint8_t extended_rcode) const;
-
 public:
     /// \brief The highest EDNS version this implementation supports.
     static const uint8_t SUPPORTED_VERSION = 0;
@@ -386,7 +380,7 @@ private:
 ///
 /// The intended usage of this function is to parse an OPT RR of an incoming
 /// DNS message, while updating the RCODE of the message.
-/// One common usage patter is as follows:
+/// One common usage pattern is as follows:
 ///
 /// \code Message msg;
 /// ...
diff --git a/src/lib/dns/message.cc b/src/lib/dns/message.cc
index d1025d1..bf7ccd5 100644
--- a/src/lib/dns/message.cc
+++ b/src/lib/dns/message.cc
@@ -15,6 +15,7 @@
 #include <stdint.h>
 
 #include <algorithm>
+#include <cassert>
 #include <string>
 #include <sstream>
 #include <vector>
@@ -40,6 +41,7 @@
 #include <dns/rrtype.h>
 #include <dns/rrttl.h>
 #include <dns/rrset.h>
+#include <dns/tsig.h>
 
 using namespace std;
 using namespace boost;
@@ -81,7 +83,7 @@ const unsigned int HEADERFLAG_MASK = 0x87b0;
 const uint16_t MESSAGE_REPLYPRESERVE = (Message::HEADERFLAG_RD |
                                         Message::HEADERFLAG_CD);
 
-const char *sectiontext[] = {
+const char* const sectiontext[] = {
     "QUESTION",
     "ANSWER",
     "AUTHORITY",
@@ -114,8 +116,8 @@ public:
     vector<QuestionPtr> questions_;
     vector<RRsetPtr> rrsets_[NUM_SECTIONS];
     ConstEDNSPtr edns_;
+    ConstTSIGRecordPtr tsig_rr_;
 
-    // tsig/sig0: TODO
     // RRsetsSorter* sorter_; : TODO
 
     void init();
@@ -123,6 +125,17 @@ public:
     void setRcode(const Rcode& rcode);
     int parseQuestion(InputBuffer& buffer);
     int parseSection(const Message::Section section, InputBuffer& buffer);
+    void addRR(Message::Section section, const Name& name,
+               const RRClass& rrclass, const RRType& rrtype,
+               const RRTTL& ttl, ConstRdataPtr rdata);
+    void addEDNS(Message::Section section, const Name& name,
+                 const RRClass& rrclass, const RRType& rrtype,
+                 const RRTTL& ttl, const Rdata& rdata);
+    void addTSIG(Message::Section section, unsigned int count,
+                 const InputBuffer& buffer, size_t start_position,
+                 const Name& name, const RRClass& rrclass,
+                 const RRTTL& ttl, const Rdata& rdata);
+    void toWire(AbstractMessageRenderer& renderer, TSIGContext* tsig_ctx);
 };
 
 MessageImpl::MessageImpl(Message::Mode mode) :
@@ -140,6 +153,7 @@ MessageImpl::init() {
     rcode_ = NULL;
     opcode_ = NULL;
     edns_ = EDNSPtr();
+    tsig_rr_ = ConstTSIGRecordPtr();
 
     for (int i = 0; i < NUM_SECTIONS; ++i) {
         counts_[i] = 0;
@@ -164,6 +178,154 @@ MessageImpl::setRcode(const Rcode& rcode) {
     rcode_ = &rcode_placeholder_;
 }
 
+namespace {
+// This helper class is used by MessageImpl::toWire() to render a set of
+// RRsets of a specific section of message to a given MessageRenderer.
+//
+// A RenderSection object is expected to be used with a QuestionIterator or
+// SectionIterator.  Its operator() is called for each RRset as the iterator
+// iterates over the corresponding section, and it renders the RRset to
+// the given MessageRenderer, while counting the number of RRs (note: not
+// RRsets) successfully rendered.  If the MessageRenderer reports the need
+// for truncation (via its isTruncated() method), the RenderSection object
+// stops rendering further RRsets.  In addition, unless partial_ok (given on
+// construction) is true, it removes any RRs that are partially rendered
+// from the MessageRenderer.
+//
+// On the completion of rendering the entire section, the owner of the
+// RenderSection object can get the number of rendered RRs via the
+// getTotalCount() method.
+template <typename T>
+struct RenderSection {
+    RenderSection(AbstractMessageRenderer& renderer, const bool partial_ok) :
+        counter_(0), renderer_(renderer), partial_ok_(partial_ok),
+        truncated_(false)
+    {}
+    void operator()(const T& entry) {
+        // If it's already truncated, ignore the rest of the section.
+        if (truncated_) {
+            return;
+        }
+        const size_t pos0 = renderer_.getLength();
+        counter_ += entry->toWire(renderer_);
+        if (renderer_.isTruncated()) {
+            truncated_ = true;
+            if (!partial_ok_) {
+                // roll back to the end of the previous RRset.
+                renderer_.trim(renderer_.getLength() - pos0);
+            }
+        }
+    }
+    unsigned int getTotalCount() { return (counter_); }
+    unsigned int counter_;
+    AbstractMessageRenderer& renderer_;
+    const bool partial_ok_;
+    bool truncated_;
+};
+}
+
+void
+MessageImpl::toWire(AbstractMessageRenderer& renderer, TSIGContext* tsig_ctx) {
+    if (mode_ != Message::RENDER) {
+        isc_throw(InvalidMessageOperation,
+                  "Message rendering attempted in non render mode");
+    }
+    if (rcode_ == NULL) {
+        isc_throw(InvalidMessageOperation,
+                  "Message rendering attempted without Rcode set");
+    }
+    if (opcode_ == NULL) {
+        isc_throw(InvalidMessageOperation,
+                  "Message rendering attempted without Opcode set");
+    }
+
+    // reserve room for the header
+    renderer.skip(HEADERLEN);
+
+    uint16_t qdcount =
+        for_each(questions_.begin(), questions_.end(),
+                 RenderSection<QuestionPtr>(renderer, false)).getTotalCount();
+
+    // TODO: sort RRsets in each section based on configuration policy.
+    uint16_t ancount = 0;
+    if (!renderer.isTruncated()) {
+        ancount =
+            for_each(rrsets_[Message::SECTION_ANSWER].begin(),
+                     rrsets_[Message::SECTION_ANSWER].end(),
+                     RenderSection<RRsetPtr>(renderer, true)).getTotalCount();
+    }
+    uint16_t nscount = 0;
+    if (!renderer.isTruncated()) {
+        nscount =
+            for_each(rrsets_[Message::SECTION_AUTHORITY].begin(),
+                     rrsets_[Message::SECTION_AUTHORITY].end(),
+                     RenderSection<RRsetPtr>(renderer, true)).getTotalCount();
+    }
+    uint16_t arcount = 0;
+    if (renderer.isTruncated()) {
+        flags_ |= Message::HEADERFLAG_TC;
+    } else {
+        arcount =
+            for_each(rrsets_[Message::SECTION_ADDITIONAL].begin(),
+                     rrsets_[Message::SECTION_ADDITIONAL].end(),
+                     RenderSection<RRsetPtr>(renderer, false)).getTotalCount();
+    }
+
+    // Add EDNS OPT RR if necessary.  Basically, we add it only when EDNS
+    // has been explicitly set.  However, if the RCODE would require it and
+    // no EDNS has been set we generate a temporary local EDNS and use it.
+    if (!renderer.isTruncated()) {
+        ConstEDNSPtr local_edns = edns_;
+        if (!local_edns && rcode_->getExtendedCode() != 0) {
+            local_edns = ConstEDNSPtr(new EDNS());
+        }
+        if (local_edns) {
+            arcount += local_edns->toWire(renderer, rcode_->getExtendedCode());
+        }
+    }
+
+    // Adjust the counter buffer.
+    // XXX: these may not be equal to the number of corresponding entries
+    // in rrsets_[] or questions_ if truncation occurred or an EDNS OPT RR
+    // was inserted.  This is not good, and we should revisit the entire
+    // design.
+    counts_[Message::SECTION_QUESTION] = qdcount;
+    counts_[Message::SECTION_ANSWER] = ancount;
+    counts_[Message::SECTION_AUTHORITY] = nscount;
+    counts_[Message::SECTION_ADDITIONAL] = arcount;
+
+    // fill in the header
+    size_t header_pos = 0;
+    renderer.writeUint16At(qid_, header_pos);
+    header_pos += sizeof(uint16_t);
+
+    uint16_t codes_and_flags =
+        (opcode_->getCode() << OPCODE_SHIFT) & OPCODE_MASK;
+    codes_and_flags |= (rcode_->getCode() & RCODE_MASK);
+    codes_and_flags |= (flags_ & HEADERFLAG_MASK);
+    renderer.writeUint16At(codes_and_flags, header_pos);
+    header_pos += sizeof(uint16_t);
+    // TODO: should avoid repeated pattern
+    renderer.writeUint16At(qdcount, header_pos);
+    header_pos += sizeof(uint16_t);
+    renderer.writeUint16At(ancount, header_pos);
+    header_pos += sizeof(uint16_t);
+    renderer.writeUint16At(nscount, header_pos);
+    header_pos += sizeof(uint16_t);
+    renderer.writeUint16At(arcount, header_pos);
+
+    // Add TSIG, if necessary, at the end of the message.
+    // TODO: truncate case consideration
+    if (tsig_ctx != NULL) {
+        tsig_ctx->sign(qid_, renderer.getData(),
+                       renderer.getLength())->toWire(renderer);
+
+        // update the ARCOUNT for the TSIG RR.  Note that for a sane DNS
+        // message arcount should never overflow to 0.
+        renderer.writeUint16At(++arcount, header_pos);
+    }
+}
+
 Message::Message(Mode mode) :
     impl_(new MessageImpl(mode))
 {}
@@ -262,6 +424,16 @@ Message::setEDNS(ConstEDNSPtr edns) {
     impl_->edns_ = edns;
 }
 
+const TSIGRecord*
+Message::getTSIGRecord() const {
+    if (impl_->mode_ != Message::PARSE) {
+        isc_throw(InvalidMessageOperation,
+                  "getTSIGRecord performed in non-parse mode");
+    }
+
+    return (impl_->tsig_rr_.get());
+}
+
 unsigned int
 Message::getRRCount(const Section section) const {
     if (section >= MessageImpl::NUM_SECTIONS) {
@@ -363,129 +535,14 @@ Message::addQuestion(const Question& question) {
     addQuestion(QuestionPtr(new Question(question)));
 }
 
-namespace {
-template <typename T>
-struct RenderSection {
-    RenderSection(MessageRenderer& renderer, const bool partial_ok) :
-        counter_(0), renderer_(renderer), partial_ok_(partial_ok),
-        truncated_(false)
-    {}
-    void operator()(const T& entry) {
-        // If it's already truncated, ignore the rest of the section.
-        if (truncated_) {
-            return;
-        }
-        const size_t pos0 = renderer_.getLength();
-        counter_ += entry->toWire(renderer_);
-        if (renderer_.isTruncated()) {
-            truncated_ = true;
-            if (!partial_ok_) {
-                // roll back to the end of the previous RRset.
-                renderer_.trim(renderer_.getLength() - pos0);
-            }
-        }
-    }
-    unsigned int getTotalCount() { return (counter_); }
-    unsigned int counter_;
-    MessageRenderer& renderer_;
-    const bool partial_ok_;
-    bool truncated_;
-};
+void
+Message::toWire(AbstractMessageRenderer& renderer) {
+    impl_->toWire(renderer, NULL);
 }
 
 void
-Message::toWire(MessageRenderer& renderer) {
-    if (impl_->mode_ != Message::RENDER) {
-        isc_throw(InvalidMessageOperation,
-                  "Message rendering attempted in non render mode");
-    }
-    if (impl_->rcode_ == NULL) {
-        isc_throw(InvalidMessageOperation,
-                  "Message rendering attempted without Rcode set");
-    }
-    if (impl_->opcode_ == NULL) {
-        isc_throw(InvalidMessageOperation,
-                  "Message rendering attempted without Opcode set");
-    }
-
-    // reserve room for the header
-    renderer.skip(HEADERLEN);
-
-    uint16_t qdcount =
-        for_each(impl_->questions_.begin(), impl_->questions_.end(),
-                 RenderSection<QuestionPtr>(renderer, false)).getTotalCount();
-
-    // TBD: sort RRsets in each section based on configuration policy.
-    uint16_t ancount = 0;
-    if (!renderer.isTruncated()) {
-        ancount =
-            for_each(impl_->rrsets_[SECTION_ANSWER].begin(),
-                     impl_->rrsets_[SECTION_ANSWER].end(),
-                     RenderSection<RRsetPtr>(renderer, true)).getTotalCount();
-    }
-    uint16_t nscount = 0;
-    if (!renderer.isTruncated()) {
-        nscount =
-            for_each(impl_->rrsets_[SECTION_AUTHORITY].begin(),
-                     impl_->rrsets_[SECTION_AUTHORITY].end(),
-                     RenderSection<RRsetPtr>(renderer, true)).getTotalCount();
-    }
-    uint16_t arcount = 0;
-    if (renderer.isTruncated()) {
-        setHeaderFlag(HEADERFLAG_TC, true);
-    } else {
-        arcount =
-            for_each(impl_->rrsets_[SECTION_ADDITIONAL].begin(),
-                     impl_->rrsets_[SECTION_ADDITIONAL].end(),
-                     RenderSection<RRsetPtr>(renderer, false)).getTotalCount();
-    }
-
-    // Add EDNS OPT RR if necessary.  Basically, we add it only when EDNS
-    // has been explicitly set.  However, if the RCODE would require it and
-    // no EDNS has been set we generate a temporary local EDNS and use it.
-    if (!renderer.isTruncated()) {
-        ConstEDNSPtr local_edns = impl_->edns_;
-        if (!local_edns && impl_->rcode_->getExtendedCode() != 0) {
-            local_edns = ConstEDNSPtr(new EDNS());
-        }
-        if (local_edns) {
-            arcount += local_edns->toWire(renderer,
-                                          impl_->rcode_->getExtendedCode());
-        }
-    }
- 
-    // Adjust the counter buffer.
-    // XXX: these may not be equal to the number of corresponding entries
-    // in rrsets_[] or questions_ if truncation occurred or an EDNS OPT RR
-    // was inserted.  This is not good, and we should revisit the entire
-    // design.
-    impl_->counts_[SECTION_QUESTION] = qdcount;
-    impl_->counts_[SECTION_ANSWER] = ancount;
-    impl_->counts_[SECTION_AUTHORITY] = nscount;
-    impl_->counts_[SECTION_ADDITIONAL] = arcount;
-
-    // TBD: TSIG, SIG(0) etc.
-
-    // fill in the header
-    size_t header_pos = 0;
-    renderer.writeUint16At(impl_->qid_, header_pos);
-    header_pos += sizeof(uint16_t);
-
-    uint16_t codes_and_flags =
-        (impl_->opcode_->getCode() << OPCODE_SHIFT) & OPCODE_MASK;
-    codes_and_flags |= (impl_->rcode_->getCode() & RCODE_MASK);
-    codes_and_flags |= (impl_->flags_ & HEADERFLAG_MASK);
-    renderer.writeUint16At(codes_and_flags, header_pos);
-    header_pos += sizeof(uint16_t);
-    // XXX: should avoid repeated pattern (TODO)
-    renderer.writeUint16At(qdcount, header_pos);
-    header_pos += sizeof(uint16_t);
-    renderer.writeUint16At(ancount, header_pos);
-    header_pos += sizeof(uint16_t);
-    renderer.writeUint16At(nscount, header_pos);
-    header_pos += sizeof(uint16_t);
-    renderer.writeUint16At(arcount, header_pos);
-    header_pos += sizeof(uint16_t);
+Message::toWire(AbstractMessageRenderer& renderer, TSIGContext& tsig_ctx) {
+    impl_->toWire(renderer, &tsig_ctx);
 }
 
 void
@@ -613,6 +670,9 @@ MessageImpl::parseSection(const Message::Section section,
     unsigned int added = 0;
 
     for (unsigned int count = 0; count < counts_[section]; ++count) {
+        // We need to remember the start position for TSIG processing
+        const size_t start_position = buffer.getPosition();
+
         const Name name(buffer);
 
         // buffer must store at least RR TYPE, RR CLASS, TTL, and RDLEN.
@@ -630,32 +690,12 @@ MessageImpl::parseSection(const Message::Section section,
         ConstRdataPtr rdata = createRdata(rrtype, rrclass, buffer, rdlen);
 
         if (rrtype == RRType::OPT()) {
-            if (section != Message::SECTION_ADDITIONAL) {
-                isc_throw(DNSMessageFORMERR,
-                          "EDNS OPT RR found in an invalid section");
-            }
-            if (edns_) {
-                isc_throw(DNSMessageFORMERR, "multiple EDNS OPT RR found");
-            }
-
-            uint8_t extended_rcode;
-            edns_ = ConstEDNSPtr(createEDNSFromRR(name, rrclass, rrtype, ttl,
-                                                  *rdata, extended_rcode));
-            setRcode(Rcode(rcode_->getCode(), extended_rcode));
-            continue;
+            addEDNS(section, name, rrclass, rrtype, ttl, *rdata);
+        } else if (rrtype == RRType::TSIG()) {
+            addTSIG(section, count, buffer, start_position, name, rrclass, ttl,
+                    *rdata);
         } else {
-            vector<RRsetPtr>::iterator it =
-                find_if(rrsets_[section].begin(), rrsets_[section].end(),
-                        MatchRR(name, rrtype, rrclass));
-            if (it != rrsets_[section].end()) {
-                (*it)->setTTL(min((*it)->getTTL(), ttl));
-                (*it)->addRdata(rdata);
-            } else {
-                RRsetPtr rrset =
-                    RRsetPtr(new RRset(name, rrclass, rrtype, ttl)); 
-                rrset->addRdata(rdata);
-                rrsets_[section].push_back(rrset);
-            }
+            addRR(section, name, rrclass, rrtype, ttl, rdata);
             ++added;
         }
     }
@@ -663,6 +703,65 @@ MessageImpl::parseSection(const Message::Section section,
     return (added);
 }
 
+void
+MessageImpl::addRR(Message::Section section, const Name& name,
+                   const RRClass& rrclass, const RRType& rrtype,
+                   const RRTTL& ttl, ConstRdataPtr rdata)
+{
+    vector<RRsetPtr>::iterator it =
+        find_if(rrsets_[section].begin(), rrsets_[section].end(),
+                MatchRR(name, rrtype, rrclass));
+    if (it != rrsets_[section].end()) {
+        (*it)->setTTL(min((*it)->getTTL(), ttl));
+        (*it)->addRdata(rdata);
+    } else {
+        RRsetPtr rrset(new RRset(name, rrclass, rrtype, ttl));
+        rrset->addRdata(rdata);
+        rrsets_[section].push_back(rrset);
+    }
+}
+
+void
+MessageImpl::addEDNS(Message::Section section,  const Name& name,
+                     const RRClass& rrclass, const RRType& rrtype,
+                     const RRTTL& ttl, const Rdata& rdata)
+{
+    if (section != Message::SECTION_ADDITIONAL) {
+        isc_throw(DNSMessageFORMERR,
+                  "EDNS OPT RR found in an invalid section");
+    }
+    if (edns_) {
+        isc_throw(DNSMessageFORMERR, "multiple EDNS OPT RR found");
+    }
+
+    uint8_t extended_rcode;
+    edns_ = ConstEDNSPtr(createEDNSFromRR(name, rrclass, rrtype, ttl, rdata,
+                                          extended_rcode));
+    setRcode(Rcode(rcode_->getCode(), extended_rcode));
+}
+
+void
+MessageImpl::addTSIG(Message::Section section, unsigned int count,
+                     const InputBuffer& buffer, size_t start_position,
+                     const Name& name, const RRClass& rrclass,
+                     const RRTTL& ttl, const Rdata& rdata)
+{
+    if (section != Message::SECTION_ADDITIONAL) {
+        isc_throw(DNSMessageFORMERR,
+                  "TSIG RR found in an invalid section");
+    }
+    if (count != counts_[section] - 1) {
+        isc_throw(DNSMessageFORMERR, "TSIG RR is not the last record");
+    }
+    if (tsig_rr_) {
+        isc_throw(DNSMessageFORMERR, "multiple TSIG RRs found");
+    }
+    tsig_rr_ = ConstTSIGRecordPtr(new TSIGRecord(name, rrclass,
+                                                 ttl, rdata,
+                                                 buffer.getPosition() -
+                                                 start_position));
+}
+
 namespace {
 template <typename T>
 struct SectionFormatter {
@@ -696,31 +795,31 @@ Message::toText() const {
     // for simplicity we don't consider extended rcode (unlike BIND9)
     s += ", status: " + impl_->rcode_->toText();
     s += ", id: " + boost::lexical_cast<string>(impl_->qid_);
-    s += "\n;; flags: ";
+    s += "\n;; flags:";
     if (getHeaderFlag(HEADERFLAG_QR)) {
-        s += "qr ";
+        s += " qr";
     }
     if (getHeaderFlag(HEADERFLAG_AA)) {
-        s += "aa ";
+        s += " aa";
     }
     if (getHeaderFlag(HEADERFLAG_TC)) {
-        s += "tc ";
+        s += " tc";
     }
     if (getHeaderFlag(HEADERFLAG_RD)) {
-        s += "rd ";
+        s += " rd";
     }
     if (getHeaderFlag(HEADERFLAG_RA)) {
-        s += "ra ";
+        s += " ra";
     }
     if (getHeaderFlag(HEADERFLAG_AD)) {
-        s += "ad ";
+        s += " ad";
     }
     if (getHeaderFlag(HEADERFLAG_CD)) {
-        s += "cd ";
+        s += " cd";
     }
 
     // for simplicity, don't consider the update case for now
-    s += "; QUESTION: " +
+    s += "; QUERY: " + // note: not "QUESTION" to be compatible with BIND 9 dig
         lexical_cast<string>(impl_->counts_[SECTION_QUESTION]);
     s += ", ANSWER: " +
         lexical_cast<string>(impl_->counts_[SECTION_ANSWER]);
@@ -731,6 +830,9 @@ Message::toText() const {
     if (impl_->edns_ != NULL) {
         ++arcount;
     }
+    if (impl_->tsig_rr_ != NULL) {
+        ++arcount;
+    }
     s += ", ADDITIONAL: " + lexical_cast<string>(arcount) + "\n";
 
     if (impl_->edns_ != NULL) {
@@ -767,6 +869,11 @@ Message::toText() const {
                  SectionFormatter<RRsetPtr>(SECTION_ADDITIONAL, s));
     }
 
+    if (impl_->tsig_rr_ != NULL) {
+        s += "\n;; TSIG PSEUDOSECTION:\n";
+        s += impl_->tsig_rr_->toText();
+    }
+
     return (s);
 }
 
diff --git a/src/lib/dns/message.h b/src/lib/dns/message.h
index 660b151..fcc53e9 100644
--- a/src/lib/dns/message.h
+++ b/src/lib/dns/message.h
@@ -33,6 +33,8 @@ class InputBuffer;
 }
 
 namespace dns {
+class TSIGContext;
+class TSIGRecord;
 
 ///
 /// \brief A standard DNS module exception that is thrown if a wire format
@@ -80,7 +82,7 @@ public:
 
 typedef uint16_t qid_t;
 
-class MessageRenderer;
+class AbstractMessageRenderer;
 class Message;
 class MessageImpl;
 class Opcode;
@@ -368,6 +370,25 @@ public:
     /// \c Message.
     void setEDNS(ConstEDNSPtr edns);
 
+    /// \brief Return, if any, the TSIG record contained in the received
+    /// message.
+    ///
+    /// Currently, this method is only intended to return a TSIG record
+    /// for an incoming message built via the \c fromWire() method in the
+    /// PARSE mode.  A call to this method in the RENDER mode is invalid and
+    /// result in an exception.  Also, calling this method is meaningless
+    /// unless \c fromWire() is performed.
+    ///
+    /// The returned pointer is valid only during the lifetime of the
+    /// \c Message object and until \c clear() is called.  The \c Message
+    /// object retains the ownership of \c TSIGRecord; the caller must not
+    /// try to delete it.
+    ///
+    /// \exception InvalidMessageOperation Message is not in the PARSE mode.
+    ///
+    /// \return A pointer to the stored \c TSIGRecord or \c NULL.
+    const TSIGRecord* getTSIGRecord() const;
+
     /// \brief Returns the number of RRs contained in the given section.
     ///
     /// In the \c PARSE mode, the returned value may not be identical to
@@ -523,13 +544,31 @@ public:
     /// class \c InvalidMessageOperation will be thrown.
     std::string toText() const;
 
-    /// \brief Render the message in wire formant into a \c MessageRenderer
+    /// \brief Render the message in wire formant into a message renderer
     /// object.
     ///
     /// This \c Message must be in the \c RENDER mode and both \c Opcode and
     /// \c Rcode must have been set beforehand; otherwise, an exception of
     /// class \c InvalidMessageOperation will be thrown.
-    void toWire(MessageRenderer& renderer);
+    ///
+    /// \param renderer DNS message rendering context that encapsulates the
+    /// output buffer and name compression information.
+    void toWire(AbstractMessageRenderer& renderer);
+
+    /// \brief Render the message in wire formant into a message renderer
+    /// object with TSIG.
+    ///
+    /// This method is similar to the other version of \c toWire(), but
+    /// it will also add a TSIG RR with (in many cases) the TSIG MAC for
+    /// the message along with the given TSIG context (\c tsig_ctx).
+    /// The TSIG RR will be placed at the end of \c renderer.
+    /// \c tsig_ctx will be updated based on the fact it was used for signing
+    /// and with the latest MAC.
+    ///
+    /// \param renderer See the other version
+    /// \param tsig_ctx A TSIG context that is to be used for signing the
+    /// message
+    void toWire(AbstractMessageRenderer& renderer, TSIGContext& tsig_ctx);
 
     /// \brief Parse the header section of the \c Message.
     void parseHeader(isc::util::InputBuffer& buffer);
@@ -564,6 +603,16 @@ private:
 typedef boost::shared_ptr<Message> MessagePtr;
 typedef boost::shared_ptr<const Message> ConstMessagePtr;
 
+/// Insert the \c Message as a string into stream.
+///
+/// This method convert \c message into a string and inserts it into the
+/// output stream \c os.
+///
+/// \param os A \c std::ostream object on which the insertion operation is
+/// performed.
+/// \param record A \c Message object output by the operation.
+/// \return A reference to the same \c std::ostream object referenced by
+/// parameter \c os after the insertion operation.
 std::ostream& operator<<(std::ostream& os, const Message& message);
 }
 }
diff --git a/src/lib/dns/messagerenderer.cc b/src/lib/dns/messagerenderer.cc
index 6438fb0..767aca9 100644
--- a/src/lib/dns/messagerenderer.cc
+++ b/src/lib/dns/messagerenderer.cc
@@ -228,8 +228,9 @@ MessageRenderer::writeName(const Name& name, const bool compress) {
     name.toWire(impl_->nbuffer_);
 
     unsigned int i;
-    std::set<NameCompressNode>::const_iterator notfound = impl_->nodeset_.end();
-    std::set<NameCompressNode>::const_iterator n = notfound;
+    std::set<NameCompressNode, NameCompare>::const_iterator notfound =
+        impl_->nodeset_.end();
+    std::set<NameCompressNode, NameCompare>::const_iterator n = notfound;
 
     // Find the longest ancestor name in the rendered set that matches the
     // given name.
diff --git a/src/lib/dns/python/Makefile.am b/src/lib/dns/python/Makefile.am
index 9d171cd..9162f4e 100644
--- a/src/lib/dns/python/Makefile.am
+++ b/src/lib/dns/python/Makefile.am
@@ -25,6 +25,7 @@ EXTRA_DIST += rrttl_python.cc
 EXTRA_DIST += rdata_python.cc
 EXTRA_DIST += rrtype_python.cc
 EXTRA_DIST += tsigkey_python.cc
+EXTRA_DIST += tsig_python.cc
 
 # Python prefers .so, while some OSes (specifically MacOS) use a different
 # suffix for dynamic objects.  -module is necessary to work this around.
diff --git a/src/lib/dns/python/message_python.cc b/src/lib/dns/python/message_python.cc
index 058312e..e3cc53f 100644
--- a/src/lib/dns/python/message_python.cc
+++ b/src/lib/dns/python/message_python.cc
@@ -17,15 +17,16 @@
 using namespace isc::dns;
 using namespace isc::util;
 
+namespace {
 //
 // Declaration of the custom exceptions
 // Initialization and addition of these go in the initModulePart
 // function at the end of this file
 //
-static PyObject* po_MessageTooShort;
-static PyObject* po_InvalidMessageSection;
-static PyObject* po_InvalidMessageOperation;
-static PyObject* po_InvalidMessageUDPSize;
+PyObject* po_MessageTooShort;
+PyObject* po_InvalidMessageSection;
+PyObject* po_InvalidMessageOperation;
+PyObject* po_InvalidMessageUDPSize;
 
 //
 // Definition of the classes
@@ -36,10 +37,6 @@ static PyObject* po_InvalidMessageUDPSize;
 // and a type description
 
 //
-// Section
-//
-
-//
 // Message
 //
 
@@ -55,36 +52,36 @@ public:
 //
 
 // General creation and destruction
-static int Message_init(s_Message* self, PyObject* args);
-static void Message_destroy(s_Message* self);
-
-static PyObject* Message_getHeaderFlag(s_Message* self, PyObject* args);
-static PyObject* Message_setHeaderFlag(s_Message* self, PyObject* args);
-static PyObject* Message_getQid(s_Message* self);
-static PyObject* Message_setQid(s_Message* self, PyObject* args);
-static PyObject* Message_getRcode(s_Message* self);
-static PyObject* Message_setRcode(s_Message* self, PyObject* args);
-static PyObject* Message_getOpcode(s_Message* self);
-static PyObject* Message_setOpcode(s_Message* self, PyObject* args);
-static PyObject* Message_getEDNS(s_Message* self);
-static PyObject* Message_setEDNS(s_Message* self, PyObject* args);
-static PyObject* Message_getRRCount(s_Message* self, PyObject* args);
+int Message_init(s_Message* self, PyObject* args);
+void Message_destroy(s_Message* self);
+
+PyObject* Message_getHeaderFlag(s_Message* self, PyObject* args);
+PyObject* Message_setHeaderFlag(s_Message* self, PyObject* args);
+PyObject* Message_getQid(s_Message* self);
+PyObject* Message_setQid(s_Message* self, PyObject* args);
+PyObject* Message_getRcode(s_Message* self);
+PyObject* Message_setRcode(s_Message* self, PyObject* args);
+PyObject* Message_getOpcode(s_Message* self);
+PyObject* Message_setOpcode(s_Message* self, PyObject* args);
+PyObject* Message_getEDNS(s_Message* self);
+PyObject* Message_setEDNS(s_Message* self, PyObject* args);
+PyObject* Message_getRRCount(s_Message* self, PyObject* args);
 // use direct iterators for these? (or simply lists for now?)
-static PyObject* Message_getQuestion(s_Message* self);
-static PyObject* Message_getSection(s_Message* self, PyObject* args);
+PyObject* Message_getQuestion(s_Message* self);
+PyObject* Message_getSection(s_Message* self, PyObject* args);
 //static PyObject* Message_beginQuestion(s_Message* self, PyObject* args);
 //static PyObject* Message_endQuestion(s_Message* self, PyObject* args);
 //static PyObject* Message_beginSection(s_Message* self, PyObject* args);
 //static PyObject* Message_endSection(s_Message* self, PyObject* args);
 
-static PyObject* Message_addQuestion(s_Message* self, PyObject* args);
-static PyObject* Message_addRRset(s_Message* self, PyObject* args);
-static PyObject* Message_clear(s_Message* self, PyObject* args);
-static PyObject* Message_makeResponse(s_Message* self);
-static PyObject* Message_toText(s_Message* self);
-static PyObject* Message_str(PyObject* self);
-static PyObject* Message_toWire(s_Message* self, PyObject* args);
-static PyObject* Message_fromWire(s_Message* self, PyObject* args);
+PyObject* Message_addQuestion(s_Message* self, PyObject* args);
+PyObject* Message_addRRset(s_Message* self, PyObject* args);
+PyObject* Message_clear(s_Message* self, PyObject* args);
+PyObject* Message_makeResponse(s_Message* self);
+PyObject* Message_toText(s_Message* self);
+PyObject* Message_str(PyObject* self);
+PyObject* Message_toWire(s_Message* self, PyObject* args);
+PyObject* Message_fromWire(s_Message* self, PyObject* args);
 
 // This list contains the actual set of functions we have in
 // python. Each entry has
@@ -92,7 +89,7 @@ static PyObject* Message_fromWire(s_Message* self, PyObject* args);
 // 2. Our static function here
 // 3. Argument type
 // 4. Documentation
-static PyMethodDef Message_methods[] = {
+PyMethodDef Message_methods[] = {
     { "get_header_flag", reinterpret_cast<PyCFunction>(Message_getHeaderFlag),
       METH_VARARGS,
       "Return whether the specified header flag bit is set in the "
@@ -175,7 +172,7 @@ static PyMethodDef Message_methods[] = {
 // This defines the complete type for reflection in python and
 // parsing of PyObject* to s_Message
 // Most of the functions are not actually implemented and NULL here.
-static PyTypeObject message_type = {
+PyTypeObject message_type = {
     PyVarObject_HEAD_INIT(NULL, 0)
     "pydnspp.Message",
     sizeof(s_Message),                  // tp_basicsize
@@ -225,7 +222,7 @@ static PyTypeObject message_type = {
     0                                   // tp_version_tag
 };
 
-static int
+int
 Message_init(s_Message* self, PyObject* args) {
     int i;
 
@@ -248,14 +245,14 @@ Message_init(s_Message* self, PyObject* args) {
     return (-1);
 }
 
-static void
+void
 Message_destroy(s_Message* self) {
     delete self->message;
     self->message = NULL;
     Py_TYPE(self)->tp_free(self);
 }
 
-static PyObject*
+PyObject*
 Message_getHeaderFlag(s_Message* self, PyObject* args) {
     unsigned int messageflag;
     if (!PyArg_ParseTuple(args, "I", &messageflag)) {
@@ -273,7 +270,7 @@ Message_getHeaderFlag(s_Message* self, PyObject* args) {
     }
 }
 
-static PyObject*
+PyObject*
 Message_setHeaderFlag(s_Message* self, PyObject* args) {
     long messageflag;
     PyObject *on = Py_True;
@@ -304,12 +301,12 @@ Message_setHeaderFlag(s_Message* self, PyObject* args) {
     }
 }
 
-static PyObject*
+PyObject*
 Message_getQid(s_Message* self) {
     return (Py_BuildValue("I", self->message->getQid()));
 }
 
-static PyObject*
+PyObject*
 Message_setQid(s_Message* self, PyObject* args) {
     long id;
     if (!PyArg_ParseTuple(args, "l", &id)) {
@@ -333,7 +330,7 @@ Message_setQid(s_Message* self, PyObject* args) {
     }
 }
 
-static PyObject*
+PyObject*
 Message_getRcode(s_Message* self) {
     s_Rcode* rcode;
 
@@ -356,7 +353,7 @@ Message_getRcode(s_Message* self) {
     return (rcode);
 }
 
-static PyObject*
+PyObject*
 Message_setRcode(s_Message* self, PyObject* args) {
     s_Rcode* rcode;
     if (!PyArg_ParseTuple(args, "O!", &rcode_type, &rcode)) {
@@ -371,7 +368,7 @@ Message_setRcode(s_Message* self, PyObject* args) {
     }
 }
 
-static PyObject*
+PyObject*
 Message_getOpcode(s_Message* self) {
     s_Opcode* opcode;
 
@@ -394,7 +391,7 @@ Message_getOpcode(s_Message* self) {
     return (opcode);
 }
 
-static PyObject*
+PyObject*
 Message_setOpcode(s_Message* self, PyObject* args) {
     s_Opcode* opcode;
     if (!PyArg_ParseTuple(args, "O!", &opcode_type, &opcode)) {
@@ -409,7 +406,7 @@ Message_setOpcode(s_Message* self, PyObject* args) {
     }
 }
 
-static PyObject*
+PyObject*
 Message_getEDNS(s_Message* self) {
     s_EDNS* edns;
     EDNS* edns_body;
@@ -429,7 +426,7 @@ Message_getEDNS(s_Message* self) {
     return (edns);
 }
 
-static PyObject*
+PyObject*
 Message_setEDNS(s_Message* self, PyObject* args) {
     s_EDNS* edns;
     if (!PyArg_ParseTuple(args, "O!", &edns_type, &edns)) {
@@ -444,7 +441,7 @@ Message_setEDNS(s_Message* self, PyObject* args) {
     }
 }
 
-static PyObject*
+PyObject*
 Message_getRRCount(s_Message* self, PyObject* args) {
     unsigned int section;
     if (!PyArg_ParseTuple(args, "I", &section)) {
@@ -463,7 +460,7 @@ Message_getRRCount(s_Message* self, PyObject* args) {
 }
 
 // TODO use direct iterators for these? (or simply lists for now?)
-static PyObject*
+PyObject*
 Message_getQuestion(s_Message* self) {
     QuestionIterator qi, qi_end;
     try {
@@ -502,7 +499,7 @@ Message_getQuestion(s_Message* self) {
     return (list);
 }
 
-static PyObject*
+PyObject*
 Message_getSection(s_Message* self, PyObject* args) {
     unsigned int section;
     if (!PyArg_ParseTuple(args, "I", &section)) {
@@ -559,7 +556,7 @@ Message_getSection(s_Message* self, PyObject* args) {
 //static PyObject* Message_beginSection(s_Message* self, PyObject* args);
 //static PyObject* Message_endSection(s_Message* self, PyObject* args);
 //static PyObject* Message_addQuestion(s_Message* self, PyObject* args);
-static PyObject*
+PyObject*
 Message_addQuestion(s_Message* self, PyObject* args) {
     s_Question *question;
 
@@ -572,7 +569,7 @@ Message_addQuestion(s_Message* self, PyObject* args) {
     Py_RETURN_NONE;
 }
 
-static PyObject*
+PyObject*
 Message_addRRset(s_Message* self, PyObject* args) {
     PyObject *sign = Py_False;
     int section;
@@ -599,7 +596,7 @@ Message_addRRset(s_Message* self, PyObject* args) {
     }
 }
 
-static PyObject*
+PyObject*
 Message_clear(s_Message* self, PyObject* args) {
     int i;
     if (PyArg_ParseTuple(args, "i", &i)) {
@@ -620,13 +617,13 @@ Message_clear(s_Message* self, PyObject* args) {
     }
 }
 
-static PyObject*
+PyObject*
 Message_makeResponse(s_Message* self) {
     self->message->makeResponse();
     Py_RETURN_NONE;
 }
 
-static PyObject*
+PyObject*
 Message_toText(s_Message* self) {
     // Py_BuildValue makes python objects from native data
     try {
@@ -641,7 +638,7 @@ Message_toText(s_Message* self) {
     }
 }
 
-static PyObject*
+PyObject*
 Message_str(PyObject* self) {
     // Simply call the to_text method we already defined
     return (PyObject_CallMethod(self,
@@ -649,13 +646,20 @@ Message_str(PyObject* self) {
                                 const_cast<char*>("")));
 }
 
-static PyObject*
+PyObject*
 Message_toWire(s_Message* self, PyObject* args) {
     s_MessageRenderer* mr;
+    s_TSIGContext* tsig_ctx = NULL;
     
-    if (PyArg_ParseTuple(args, "O!", &messagerenderer_type, &mr)) {
+    if (PyArg_ParseTuple(args, "O!|O!", &messagerenderer_type, &mr,
+                         &tsig_context_type, &tsig_ctx)) {
         try {
-            self->message->toWire(*mr->messagerenderer);
+            if (tsig_ctx == NULL) {
+                self->message->toWire(*mr->messagerenderer);
+            } else {
+                self->message->toWire(*mr->messagerenderer,
+                                      *tsig_ctx->tsig_ctx);
+            }
             // If we return NULL it is seen as an error, so use this for
             // None returns
             Py_RETURN_NONE;
@@ -671,7 +675,7 @@ Message_toWire(s_Message* self, PyObject* args) {
     return (NULL);
 }
 
-static PyObject*
+PyObject*
 Message_fromWire(s_Message* self, PyObject* args) {
     const char* b;
     Py_ssize_t len;
@@ -765,3 +769,4 @@ initModulePart_Message(PyObject* mod) {
 
     return (true);
 }
+} // end of unnamed namespace
diff --git a/src/lib/dns/python/pydnspp.cc b/src/lib/dns/python/pydnspp.cc
index 27dbae6..2138198 100644
--- a/src/lib/dns/python/pydnspp.cc
+++ b/src/lib/dns/python/pydnspp.cc
@@ -56,6 +56,7 @@ static PyObject* po_DNSMessageBADVERS;
 #include <dns/python/question_python.cc>       // needs RRClass, RRType, RRTTL,
                                                // Name
 #include <dns/python/tsigkey_python.cc>        // needs Name
+#include <dns/python/tsig_python.cc>           // needs tsigkey
 #include <dns/python/opcode_python.cc>
 #include <dns/python/rcode_python.cc>
 #include <dns/python/edns_python.cc>           // needs Messagerenderer, Rcode
@@ -153,6 +154,10 @@ PyInit_pydnspp(void) {
         return (NULL);
     }
 
+    if (!initModulePart_TSIGContext(mod)) {
+        return (NULL);
+    }
+
     return (mod);
 }
 
diff --git a/src/lib/dns/python/tests/Makefile.am b/src/lib/dns/python/tests/Makefile.am
index 272f1c1..9ee98c7 100644
--- a/src/lib/dns/python/tests/Makefile.am
+++ b/src/lib/dns/python/tests/Makefile.am
@@ -11,6 +11,7 @@ PYTESTS += rrclass_python_test.py
 PYTESTS += rrset_python_test.py
 PYTESTS += rrttl_python_test.py
 PYTESTS += rrtype_python_test.py
+PYTESTS += tsig_python_test.py
 PYTESTS += tsigkey_python_test.py
 
 EXTRA_DIST = $(PYTESTS)
@@ -20,7 +21,7 @@ EXTRA_DIST += testutil.py
 # required by loadable python modules.
 LIBRARY_PATH_PLACEHOLDER =
 if SET_ENV_LIBRARY_PATH
-LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/dns/.libs:$(abs_top_builddir)/src/lib/util/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs:$$$(ENV_LIBRARY_PATH)
+LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/dns/.libs:$(abs_top_builddir)/src/lib/cryptolink/.libs:$(abs_top_builddir)/src/lib/util/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs:$$$(ENV_LIBRARY_PATH)
 endif
 
 # test using command-line arguments, so use check-local target instead of TESTS
diff --git a/src/lib/dns/python/tests/message_python_test.py b/src/lib/dns/python/tests/message_python_test.py
index bccc596..72807cc 100644
--- a/src/lib/dns/python/tests/message_python_test.py
+++ b/src/lib/dns/python/tests/message_python_test.py
@@ -62,6 +62,12 @@ def create_message():
     message_render.add_rrset(Message.SECTION_ANSWER, rrset)
     return message_render
 
+def strip_mutable_tsig_data(data):
+    # Unfortunately we cannot easily compare TSIG RR because we can't tweak
+    # current time.  As a work around this helper function strips off the time
+    # dependent part of TSIG RDATA, i.e., the MAC (assuming HMAC-MD5) and
+    # Time Signed.
+    return data[0:-32] + data[-26:-22] + data[-6:]
 
 class MessageTest(unittest.TestCase):
 
@@ -81,6 +87,8 @@ class MessageTest(unittest.TestCase):
 
         self.bogus_section = Message.SECTION_ADDITIONAL + 1
         self.bogus_below_section = Message.SECTION_QUESTION - 1
+        self.tsig_key = TSIGKey("www.example.com:SFuWd/q99SzF8Yzd1QbB9g==")
+        self.tsig_ctx = TSIGContext(self.tsig_key)
 
     def test_init(self):
         self.assertRaises(TypeError, Message, -1)
@@ -277,12 +285,39 @@ class MessageTest(unittest.TestCase):
         self.assertRaises(InvalidMessageOperation, self.r.to_wire,
                           MessageRenderer())
 
+    def __common_tsigquery_setup(self):
+        self.r.set_opcode(Opcode.QUERY())
+        self.r.set_rcode(Rcode.NOERROR())
+        self.r.set_header_flag(Message.HEADERFLAG_RD)
+        self.r.add_question(Question(Name("www.example.com"),
+                                     RRClass("IN"), RRType("A")))
+
+    def __common_tsig_checks(self, expected_file):
+        renderer = MessageRenderer()
+        self.r.to_wire(renderer, self.tsig_ctx)
+        actual_wire = strip_mutable_tsig_data(renderer.get_data())
+        expected_wire = strip_mutable_tsig_data(read_wire_data(expected_file))
+        self.assertEqual(expected_wire, actual_wire)
+
+    def test_to_wire_with_tsig(self):
+        self.r.set_qid(0x2d65)
+        self.__common_tsigquery_setup()
+        self.__common_tsig_checks("message_toWire2.wire")
+
+    def test_to_wire_with_edns_tsig(self):
+        self.r.set_qid(0x6cd)
+        self.__common_tsigquery_setup()
+        edns = EDNS()
+        edns.set_udp_size(4096)
+        self.r.set_edns(edns)
+        self.__common_tsig_checks("message_toWire3.wire")
+
     def test_to_text(self):
         message_render = create_message()
         
         msg_str =\
 """;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 4149
-;; flags: qr aa rd ; QUESTION: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0
+;; flags: qr aa rd; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0
 
 ;; QUESTION SECTION:
 ;test.example.com. IN A
diff --git a/src/lib/dns/python/tests/tsig_python_test.py b/src/lib/dns/python/tests/tsig_python_test.py
new file mode 100644
index 0000000..bffa0cf
--- /dev/null
+++ b/src/lib/dns/python/tests/tsig_python_test.py
@@ -0,0 +1,29 @@
+# Copyright (C) 2010  Internet Systems Consortium.
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SYSTEMS CONSORTIUM
+# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+# INTERNET SYSTEMS CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+# FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+import unittest
+from pydnspp import *
+
+class TSIGContextTest(unittest.TestCase):
+    tsig_key = TSIGKey('www.example.com:SFuWd/q99SzF8Yzd1QbB9g==')
+
+    def setUp(self):
+        # In the minimal implementation, we simply check constructing a
+        # TSIGContext doesn't cause any disruption.  We can add more tests
+        # later.
+        self.tsig_ctx = TSIGContext(self.tsig_key)
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/src/lib/dns/python/tests/tsigkey_python_test.py b/src/lib/dns/python/tests/tsigkey_python_test.py
index 06e6868..97be501 100644
--- a/src/lib/dns/python/tests/tsigkey_python_test.py
+++ b/src/lib/dns/python/tests/tsigkey_python_test.py
@@ -44,6 +44,28 @@ class TSIGKeyTest(unittest.TestCase):
                           TSIGKey.HMACMD5_NAME,
                           'should be binary') # signature mismatch
 
+    def test_str(self):
+        k1 = TSIGKey('test.example:CwsLCwsLCwsLCwsLCwsLCw==:hmac-md5.sig-alg.reg.int')
+        self.assertEqual(Name('test.example.'), k1.get_key_name())
+        self.assertEqual(Name('hmac-md5.sig-alg.reg.int.'), k1.get_algorithm_name())
+        self.assertEqual(b'\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b',
+                         k1.get_secret())
+        self.assertEqual('test.example.:CwsLCwsLCwsLCwsLCwsLCw==:hmac-md5.sig-alg.reg.int.',
+                         k1.to_text())
+
+        self.assertRaises(InvalidParameter, TSIGKey,
+                          'test.example:CwsLCwsLCwsLCwsLCwsLCw==:unsupported')
+        self.assertRaises(InvalidParameter, TSIGKey,
+                          '::')
+        self.assertRaises(InvalidParameter, TSIGKey,
+                          'test.example:')
+        self.assertRaises(InvalidParameter, TSIGKey,
+                          'test.example:%bad_base_64%')
+        self.assertRaises(InvalidParameter, TSIGKey,
+                          'test.example:CwsLCwsLCwsLCwsLCwsLCw==:')
+        self.assertRaises(InvalidParameter, TSIGKey,
+                          'test.:example:CwsLCwsLCwsLCwsLCwsLCw==')
+
 class TSIGKeyRingTest(unittest.TestCase):
     key_name = Name('example.com')
     secret = b'someRandomData'
diff --git a/src/lib/dns/python/tsig_python.cc b/src/lib/dns/python/tsig_python.cc
new file mode 100644
index 0000000..2e6d986
--- /dev/null
+++ b/src/lib/dns/python/tsig_python.cc
@@ -0,0 +1,157 @@
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <dns/tsig.h>
+
+using namespace isc::dns;
+
+//
+// Definition of the classes
+//
+
+// For each class, we need a struct, a helper functions (init, destroy,
+// and static wrappers around the methods we export), a list of methods,
+// and a type description
+
+namespace {
+// The s_* Class simply covers one instantiation of the object
+
+class s_TSIGContext : public PyObject {
+public:
+    TSIGContext* tsig_ctx;
+};
+
+//
+// We declare the functions here, the definitions are below
+// the type definition of the object, since both can use the other
+//
+
+// General creation and destruction
+int TSIGContext_init(s_TSIGContext* self, PyObject* args);
+void TSIGContext_destroy(s_TSIGContext* self);
+
+// These are the functions we export
+// For a minimal support, we don't need them.
+
+// This list contains the actual set of functions we have in
+// python. Each entry has
+// 1. Python method name
+// 2. Our static function here
+// 3. Argument type
+// 4. Documentation
+PyMethodDef TSIGContext_methods[] = {
+    { NULL, NULL, 0, NULL }
+};
+
+// This defines the complete type for reflection in python and
+// parsing of PyObject* to s_EDNS
+// Most of the functions are not actually implemented and NULL here.
+PyTypeObject tsig_context_type = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "libdns_python.TSIGContext",
+    sizeof(s_TSIGContext),              // tp_basicsize
+    0,                                  // tp_itemsize
+    (destructor)TSIGContext_destroy,    // tp_dealloc
+    NULL,                               // tp_print
+    NULL,                               // tp_getattr
+    NULL,                               // tp_setattr
+    NULL,                               // tp_reserved
+    NULL,                               // tp_repr
+    NULL,                               // tp_as_number
+    NULL,                               // tp_as_sequence
+    NULL,                               // tp_as_mapping
+    NULL,                               // tp_hash 
+    NULL,                               // tp_call
+    NULL,                               // tp_str
+    NULL,                               // tp_getattro
+    NULL,                               // tp_setattro
+    NULL,                               // tp_as_buffer
+    Py_TPFLAGS_DEFAULT,                 // tp_flags
+    "The TSIGContext class maintains a context of a signed session of "
+    "DNS transactions by TSIG.",
+    NULL,                               // tp_traverse
+    NULL,                               // tp_clear
+    NULL,                               // tp_richcompare
+    0,                                  // tp_weaklistoffset
+    NULL,                               // tp_iter
+    NULL,                               // tp_iternext
+    TSIGContext_methods,                // tp_methods
+    NULL,                               // tp_members
+    NULL,                               // tp_getset
+    NULL,                               // tp_base
+    NULL,                               // tp_dict
+    NULL,                               // tp_descr_get
+    NULL,                               // tp_descr_set
+    0,                                  // tp_dictoffset
+    (initproc)TSIGContext_init,         // tp_init
+    NULL,                               // tp_alloc
+    PyType_GenericNew,                  // tp_new
+    NULL,                               // tp_free
+    NULL,                               // tp_is_gc
+    NULL,                               // tp_bases
+    NULL,                               // tp_mro
+    NULL,                               // tp_cache
+    NULL,                               // tp_subclasses
+    NULL,                               // tp_weaklist
+    NULL,                               // tp_del
+    0                                   // tp_version_tag
+};
+
+int
+TSIGContext_init(s_TSIGContext* self, PyObject* args) {
+    const s_TSIGKey* tsigkey_obj;
+
+    try {
+        if (PyArg_ParseTuple(args, "O!", &tsigkey_type, &tsigkey_obj)) {
+            self->tsig_ctx = new TSIGContext(*tsigkey_obj->tsigkey);
+            return (0);
+        }
+    } catch (...) {
+        PyErr_SetString(po_IscException, "Unexpected exception");
+        return (-1);
+    }
+
+    PyErr_Clear();
+    PyErr_SetString(PyExc_TypeError,
+                    "Invalid arguments to TSIGContext constructor");
+
+    return (-1);
+}
+
+void
+TSIGContext_destroy(s_TSIGContext* const self) {
+    delete self->tsig_ctx;
+    self->tsig_ctx = NULL;
+    Py_TYPE(self)->tp_free(self);
+}
+
+// Module Initialization, all statics are initialized here
+bool
+initModulePart_TSIGContext(PyObject* mod) {
+    // We initialize the static description object with PyType_Ready(),
+    // then add it to the module. This is not just a check! (leaving
+    // this out results in segmentation faults)
+    if (PyType_Ready(&tsig_context_type) < 0) {
+        return (false);
+    }
+    Py_INCREF(&tsig_context_type);
+    void* p = &tsig_context_type;
+    PyModule_AddObject(mod, "TSIGContext", static_cast<PyObject*>(p));
+
+    addClassVariable(tsig_context_type, "DEFAULT_FUDGE",
+                     Py_BuildValue("H", TSIGContext::DEFAULT_FUDGE));
+
+    return (true);
+}
+} // end of anonymous namespace
diff --git a/src/lib/dns/python/tsigkey_python.cc b/src/lib/dns/python/tsigkey_python.cc
index aa87909..906dfc0 100644
--- a/src/lib/dns/python/tsigkey_python.cc
+++ b/src/lib/dns/python/tsigkey_python.cc
@@ -55,6 +55,7 @@ void TSIGKey_destroy(s_TSIGKey* self);
 PyObject* TSIGKey_getKeyName(const s_TSIGKey* self);
 PyObject* TSIGKey_getAlgorithmName(const s_TSIGKey* self);
 PyObject* TSIGKey_getSecret(const s_TSIGKey* self);
+PyObject* TSIGKey_toText(const s_TSIGKey* self);
 
 // This list contains the actual set of functions we have in
 // python. Each entry has
@@ -72,6 +73,8 @@ PyMethodDef TSIGKey_methods[] = {
     { "get_secret",
       reinterpret_cast<PyCFunction>(TSIGKey_getSecret), METH_NOARGS,
       "Return the value of the TSIG secret." },
+    { "to_text", reinterpret_cast<PyCFunction>(TSIGKey_toText), METH_NOARGS,
+      "Returns the string representation (name:secret:algorithm)" },
     { NULL, NULL, 0, NULL }
 };
 
@@ -148,27 +151,33 @@ createNameObject(const Name& source) {
 
 int
 TSIGKey_init(s_TSIGKey* self, PyObject* args) {
+    const char* str;
+
     const s_Name* key_name;
     const s_Name* algorithm_name;
     PyObject* bytes_obj;
     const char* secret;
     Py_ssize_t secret_len;
 
-    if (PyArg_ParseTuple(args, "O!O!O", &name_type, &key_name,
+
+    try {
+        if (PyArg_ParseTuple(args, "s", &str)) {
+            self->tsigkey = new TSIGKey(str);
+            return (0);
+        } else if (PyArg_ParseTuple(args, "O!O!O", &name_type, &key_name,
                          &name_type, &algorithm_name, &bytes_obj) &&
-        PyObject_AsCharBuffer(bytes_obj, &secret, &secret_len) != -1) {
-        try {
-            self->tsigkey = new TSIGKey(*key_name->name,
-                                        *algorithm_name->name,
-                                        secret, secret_len);
-        } catch (const isc::InvalidParameter& ex) {
-            PyErr_SetString(po_InvalidParameter, ex.what());
-            return (-1);
-        } catch (...) {
-            PyErr_SetString(po_IscException, "Unexpected exception");
-            return (-1);
+            PyObject_AsCharBuffer(bytes_obj, &secret, &secret_len) != -1) {
+                self->tsigkey = new TSIGKey(*key_name->name,
+                                            *algorithm_name->name,
+                                            secret, secret_len);
+            return (0);
         }
-        return (0);
+    } catch (const isc::InvalidParameter& ex) {
+        PyErr_SetString(po_InvalidParameter, ex.what());
+        return (-1);
+    } catch (...) {
+        PyErr_SetString(po_IscException, "Unexpected exception");
+        return (-1);
     }
 
     PyErr_Clear();
@@ -201,6 +210,11 @@ TSIGKey_getSecret(const s_TSIGKey* const self) {
                           self->tsigkey->getSecretLength()));
 }
 
+PyObject*
+TSIGKey_toText(const s_TSIGKey* self) {
+    return (Py_BuildValue("s", self->tsigkey->toText().c_str()));
+}
+
 // Module Initialization, all statics are initialized here
 bool
 initModulePart_TSIGKey(PyObject* mod) {
diff --git a/src/lib/dns/question.cc b/src/lib/dns/question.cc
index 723fc88..96e2a9c 100644
--- a/src/lib/dns/question.cc
+++ b/src/lib/dns/question.cc
@@ -56,7 +56,7 @@ Question::toWire(OutputBuffer& buffer) const {
 }
 
 unsigned int
-Question::toWire(MessageRenderer& renderer) const {
+Question::toWire(AbstractMessageRenderer& renderer) const {
     renderer.writeName(name_);
     rrtype_.toWire(renderer);
     rrclass_.toWire(renderer);
diff --git a/src/lib/dns/question.h b/src/lib/dns/question.h
index 3c038b3..b3f3d98 100644
--- a/src/lib/dns/question.h
+++ b/src/lib/dns/question.h
@@ -32,7 +32,7 @@ class OutputBuffer;
 
 namespace dns {
 
-class MessageRenderer;
+class AbstractMessageRenderer;
 class Question;
 
 /// \brief A pointer-like type pointing to an \c Question object.
@@ -218,13 +218,13 @@ public:
     /// \param renderer DNS message rendering context that encapsulates the
     /// output buffer and name compression information.
     /// \return 1
-    unsigned int toWire(MessageRenderer& renderer) const;
+    unsigned int toWire(AbstractMessageRenderer& renderer) const;
 
     /// \brief Render the Question in the wire format without name compression.
     ///
     /// This method behaves like the render version except it doesn't compress
     /// the owner name.
-    /// See \c toWire(MessageRenderer& renderer)const.
+    /// See \c toWire(AbstractMessageRenderer& renderer)const.
     ///
     /// \param buffer An output buffer to store the wire data.
     /// \return 1
diff --git a/src/lib/dns/rdata/any_255/tsig_250.cc b/src/lib/dns/rdata/any_255/tsig_250.cc
index f2bd7ad..8211e7f 100644
--- a/src/lib/dns/rdata/any_255/tsig_250.cc
+++ b/src/lib/dns/rdata/any_255/tsig_250.cc
@@ -24,7 +24,7 @@
 #include <dns/messagerenderer.h>
 #include <dns/rdata.h>
 #include <dns/rdataclass.h>
-
+#include <dns/tsigerror.h>
 
 using namespace std;
 using namespace boost;
@@ -313,15 +313,7 @@ TSIG::toText() const {
         result += encodeBase64(impl_->mac_) + " ";
     }
     result += lexical_cast<string>(impl_->original_id_) + " ";
-    if (impl_->error_ == 16) {  // XXX: we'll soon introduce generic converter.
-        result += "BADSIG ";
-    } else if (impl_->error_ == 17) {
-        result += "BADKEY ";
-    } else if (impl_->error_ == 18) {
-        result += "BADTIME ";
-    } else {
-        result += lexical_cast<string>(impl_->error_) + " ";
-    }
+    result += TSIGError(impl_->error_).toText() + " ";
     result += lexical_cast<string>(impl_->other_data_.size());
     if (impl_->other_data_.size() > 0) {
         result += " " + encodeBase64(impl_->other_data_);
diff --git a/src/lib/dns/rrclass-placeholder.h b/src/lib/dns/rrclass-placeholder.h
index ae3ff6f..80035d8 100644
--- a/src/lib/dns/rrclass-placeholder.h
+++ b/src/lib/dns/rrclass-placeholder.h
@@ -31,7 +31,7 @@ class OutputBuffer;
 namespace dns {
 
 // forward declarations
-class MessageRenderer;
+class AbstractMessageRenderer;
 
 ///
 /// \brief A standard DNS module exception that is thrown if an RRClass object
@@ -169,7 +169,7 @@ public:
     /// standard exception will be thrown.
     ///
     /// \param buffer An output buffer to store the wire data.
-    void toWire(MessageRenderer& renderer) const;
+    void toWire(AbstractMessageRenderer& renderer) const;
     /// \brief Render the \c RRClass in the wire format.
     ///
     /// This method renders the class code in network byte order into the
diff --git a/src/lib/dns/rrclass.cc b/src/lib/dns/rrclass.cc
index f1bb8d7..a28e5cf 100644
--- a/src/lib/dns/rrclass.cc
+++ b/src/lib/dns/rrclass.cc
@@ -52,7 +52,7 @@ RRClass::toWire(OutputBuffer& buffer) const {
 }
 
 void
-RRClass::toWire(MessageRenderer& renderer) const {
+RRClass::toWire(AbstractMessageRenderer& renderer) const {
     renderer.writeUint16(classcode_);
 }
 
diff --git a/src/lib/dns/rrset.cc b/src/lib/dns/rrset.cc
index e80afdb..776d49f 100644
--- a/src/lib/dns/rrset.cc
+++ b/src/lib/dns/rrset.cc
@@ -104,8 +104,8 @@ AbstractRRset::toWire(OutputBuffer& buffer) const {
 }
 
 unsigned int
-AbstractRRset::toWire(MessageRenderer& renderer) const {
-    const unsigned int rrs_written = rrsetToWire<MessageRenderer>(
+AbstractRRset::toWire(AbstractMessageRenderer& renderer) const {
+    const unsigned int rrs_written = rrsetToWire<AbstractMessageRenderer>(
         *this, renderer, renderer.getLengthLimit());
     if (getRdataCount() > rrs_written) {
         renderer.setTruncated();
@@ -202,7 +202,7 @@ BasicRRset::toWire(OutputBuffer& buffer) const {
 }
 
 unsigned int
-BasicRRset::toWire(MessageRenderer& renderer) const {
+BasicRRset::toWire(AbstractMessageRenderer& renderer) const {
     return (AbstractRRset::toWire(renderer));
 }
 
diff --git a/src/lib/dns/rrset.h b/src/lib/dns/rrset.h
index bf7adc0..6c15b53 100644
--- a/src/lib/dns/rrset.h
+++ b/src/lib/dns/rrset.h
@@ -47,7 +47,7 @@ class Name;
 class RRType;
 class RRClass;
 class RRTTL;
-class MessageRenderer;
+class AbstractMessageRenderer;
 class AbstractRRset;
 class BasicRRset;
 class RdataIterator;
@@ -311,7 +311,7 @@ public:
     /// \return The number of RRs rendered.  If the truncation is necessary
     /// this value may be different from the number of RDATA objects contained
     /// in the RRset.
-    virtual unsigned int toWire(MessageRenderer& renderer) const = 0;
+    virtual unsigned int toWire(AbstractMessageRenderer& renderer) const = 0;
 
     /// \brief Render the RRset in the wire format without any compression.
     ///
@@ -617,7 +617,7 @@ public:
     ///
     /// This method simply uses the default implementation.
     /// See \c AbstractRRset::toWire(MessageRenderer&)const.
-    virtual unsigned int toWire(MessageRenderer& renderer) const;
+    virtual unsigned int toWire(AbstractMessageRenderer& renderer) const;
 
     /// \brief Render the RRset in the wire format without any compression.
     ///
diff --git a/src/lib/dns/rrttl.cc b/src/lib/dns/rrttl.cc
index a4c4f83..ecd8cc6 100644
--- a/src/lib/dns/rrttl.cc
+++ b/src/lib/dns/rrttl.cc
@@ -63,7 +63,7 @@ RRTTL::toWire(OutputBuffer& buffer) const {
 }
 
 void
-RRTTL::toWire(MessageRenderer& renderer) const {
+RRTTL::toWire(AbstractMessageRenderer& renderer) const {
     renderer.writeUint32(ttlval_);
 }
 
diff --git a/src/lib/dns/rrttl.h b/src/lib/dns/rrttl.h
index 17ec891..bf23295 100644
--- a/src/lib/dns/rrttl.h
+++ b/src/lib/dns/rrttl.h
@@ -28,7 +28,7 @@ class OutputBuffer;
 namespace dns {
 
 // forward declarations
-class MessageRenderer;
+class AbstractMessageRenderer;
 
 ///
 /// \brief A standard DNS module exception that is thrown if an RRTTL object
@@ -123,7 +123,7 @@ public:
     ///
     /// \param renderer DNS message rendering context that encapsulates the
     /// output buffer in which the RRTTL is to be stored.
-    void toWire(MessageRenderer& renderer) const;
+    void toWire(AbstractMessageRenderer& renderer) const;
     /// \brief Render the \c RRTTL in the wire format.
     ///
     /// This method renders the TTL value in network byte order into the
diff --git a/src/lib/dns/tests/Makefile.am b/src/lib/dns/tests/Makefile.am
index fdd6e1e..9783beb 100644
--- a/src/lib/dns/tests/Makefile.am
+++ b/src/lib/dns/tests/Makefile.am
@@ -20,6 +20,7 @@ TESTS += run_unittests
 run_unittests_SOURCES = unittest_util.h unittest_util.cc
 run_unittests_SOURCES += edns_unittest.cc
 run_unittests_SOURCES += messagerenderer_unittest.cc
+run_unittests_SOURCES += name_unittest.cc
 run_unittests_SOURCES += rrclass_unittest.cc rrtype_unittest.cc
 run_unittests_SOURCES += rrttl_unittest.cc
 run_unittests_SOURCES += opcode_unittest.cc
@@ -46,13 +47,18 @@ run_unittests_SOURCES += question_unittest.cc
 run_unittests_SOURCES += rrparamregistry_unittest.cc
 run_unittests_SOURCES += masterload_unittest.cc
 run_unittests_SOURCES += message_unittest.cc
+run_unittests_SOURCES += tsig_unittest.cc
+run_unittests_SOURCES += tsigerror_unittest.cc
 run_unittests_SOURCES += tsigkey_unittest.cc
+run_unittests_SOURCES += tsigrecord_unittest.cc
 run_unittests_SOURCES += run_unittests.cc
 run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
 run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)
 run_unittests_LDADD = $(GTEST_LDADD)
 run_unittests_LDADD += $(top_builddir)/src/lib/dns/libdns++.la
 run_unittests_LDADD += $(top_builddir)/src/lib/util/libutil.la
+run_unittests_LDADD += $(top_builddir)/src/lib/util/unittests/libutil_unittests.la
+run_unittests_LDADD += $(top_builddir)/src/lib/util/io/libutil_io.la
 run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
 endif
 
diff --git a/src/lib/dns/tests/message_unittest.cc b/src/lib/dns/tests/message_unittest.cc
index 4031e4f..c79ea2c 100644
--- a/src/lib/dns/tests/message_unittest.cc
+++ b/src/lib/dns/tests/message_unittest.cc
@@ -12,9 +12,18 @@
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // PERFORMANCE OF THIS SOFTWARE.
 
+#include <fstream>
+
+#include <boost/scoped_ptr.hpp>
+
 #include <exceptions/exceptions.h>
 
 #include <util/buffer.h>
+#include <util/time_utilities.h>
+
+#include <util/unittests/testdata.h>
+#include <util/unittests/textdata.h>
+
 #include <dns/edns.h>
 #include <dns/exceptions.h>
 #include <dns/message.h>
@@ -26,6 +35,8 @@
 #include <dns/rrclass.h>
 #include <dns/rrttl.h>
 #include <dns/rrtype.h>
+#include <dns/tsig.h>
+#include <dns/tsigkey.h>
 
 #include <gtest/gtest.h>
 
@@ -53,6 +64,18 @@ using namespace isc::dns::rdata;
 const uint16_t Message::DEFAULT_MAX_UDPSIZE;
 const Name test_name("test.example.com");
 
+namespace isc {
+namespace util {
+namespace detail {
+extern int64_t (*gettimeFunction)();
+}
+}
+}
+
+// XXX: this is defined as class static constants, but some compilers
+// seemingly cannot find the symbol when used in the EXPECT_xxx macros.
+const uint16_t TSIGContext::DEFAULT_FUDGE;
+
 namespace {
 class MessageTest : public ::testing::Test {
 protected:
@@ -60,7 +83,9 @@ protected:
                     message_parse(Message::PARSE),
                     message_render(Message::RENDER),
                     bogus_section(static_cast<Message::Section>(
-                                      Message::SECTION_ADDITIONAL + 1))
+                                      Message::SECTION_ADDITIONAL + 1)),
+                    tsig_ctx(TSIGKey("www.example.com:"
+                                     "SFuWd/q99SzF8Yzd1QbB9g=="))
     {
         rrset_a = RRsetPtr(new RRset(test_name, RRClass::IN(),
                                      RRType::A(), RRTTL(3600)));
@@ -88,6 +113,9 @@ protected:
     RRsetPtr rrset_a;           // A RRset with two RDATAs
     RRsetPtr rrset_aaaa;        // AAAA RRset with one RDATA with RRSIG
     RRsetPtr rrset_rrsig;       // RRSIG for the AAAA RRset
+    TSIGContext tsig_ctx;
+    vector<unsigned char> expected_data;
+
     static void factoryFromFile(Message& message, const char* datafile);
 };
 
@@ -166,6 +194,70 @@ TEST_F(MessageTest, setEDNS) {
     EXPECT_EQ(edns, message_render.getEDNS());
 }
 
+TEST_F(MessageTest, fromWireWithTSIG) {
+    // Initially there should be no TSIG
+    EXPECT_EQ(static_cast<void*>(NULL), message_parse.getTSIGRecord());
+
+    // getTSIGRecord() is only valid in the parse mode.
+    EXPECT_THROW(message_render.getTSIGRecord(), InvalidMessageOperation);
+
+    factoryFromFile(message_parse, "message_toWire2.wire");
+    const char expected_mac[] = {
+        0x22, 0x70, 0x26, 0xad, 0x29, 0x7b, 0xee, 0xe7,
+        0x21, 0xce, 0x6c, 0x6f, 0xff, 0x1e, 0x9e, 0xf3
+    };
+    const TSIGRecord* tsig_rr = message_parse.getTSIGRecord();
+    ASSERT_NE(static_cast<void*>(NULL), tsig_rr);
+    EXPECT_EQ(Name("www.example.com"), tsig_rr->getName());
+    EXPECT_EQ(85, tsig_rr->getLength()); // see TSIGRecordTest.getLength
+    EXPECT_EQ(TSIGKey::HMACMD5_NAME(), tsig_rr->getRdata().getAlgorithm());
+    EXPECT_EQ(0x4da8877a, tsig_rr->getRdata().getTimeSigned());
+    EXPECT_EQ(TSIGContext::DEFAULT_FUDGE, tsig_rr->getRdata().getFudge());
+    EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
+                        tsig_rr->getRdata().getMAC(),
+                        tsig_rr->getRdata().getMACSize(),
+                        expected_mac, sizeof(expected_mac));
+    EXPECT_EQ(0, tsig_rr->getRdata().getError());
+    EXPECT_EQ(0, tsig_rr->getRdata().getOtherLen());
+    EXPECT_EQ(static_cast<void*>(NULL), tsig_rr->getRdata().getOtherData());
+
+    // If we clear the message for reuse, the recorded TSIG will be cleared.
+    message_parse.clear(Message::PARSE);
+    EXPECT_EQ(static_cast<void*>(NULL), message_parse.getTSIGRecord());
+}
+
+TEST_F(MessageTest, fromWireWithTSIGCompressed) {
+    // Mostly same as fromWireWithTSIG, but the TSIG owner name is compressed.
+    factoryFromFile(message_parse, "message_fromWire12.wire");
+    const TSIGRecord* tsig_rr = message_parse.getTSIGRecord();
+    ASSERT_NE(static_cast<void*>(NULL), tsig_rr);
+    EXPECT_EQ(Name("www.example.com"), tsig_rr->getName());
+    // len(www.example.com) = 17, but when fully compressed, the length is
+    // 2 bytes.  So the length of the record should be 15 bytes shorter.
+    EXPECT_EQ(70, tsig_rr->getLength());
+}
+
+TEST_F(MessageTest, fromWireWithBadTSIG) {
+    // Multiple TSIG RRs
+    EXPECT_THROW(factoryFromFile(message_parse, "message_fromWire13.wire"),
+                 DNSMessageFORMERR);
+    message_parse.clear(Message::PARSE);
+
+    // TSIG in the answer section (must be in additional)
+    EXPECT_THROW(factoryFromFile(message_parse, "message_fromWire14.wire"),
+                 DNSMessageFORMERR);
+    message_parse.clear(Message::PARSE);
+
+    // TSIG is not the last record.
+    EXPECT_THROW(factoryFromFile(message_parse, "message_fromWire15.wire"),
+                 DNSMessageFORMERR);
+    message_parse.clear(Message::PARSE);
+
+    // Unexpected RR Class (this will fail in constructing TSIGRecord)
+    EXPECT_THROW(factoryFromFile(message_parse, "message_fromWire16.wire"),
+                 DNSMessageFORMERR);
+}
+
 TEST_F(MessageTest, getRRCount) {
     // by default all counters should be 0
     EXPECT_EQ(0, message_render.getRRCount(Message::SECTION_QUESTION));
@@ -519,6 +611,65 @@ TEST_F(MessageTest, toWireInParseMode) {
     EXPECT_THROW(message_parse.toWire(renderer), InvalidMessageOperation);
 }
 
+// See dnssectime_unittest.cc
+template <int64_t NOW>
+int64_t
+testGetTime() {
+    return (NOW);
+}
+
+void
+commonTSIGToWireCheck(Message& message, MessageRenderer& renderer,
+                      TSIGContext& tsig_ctx, const char* const expected_file)
+{
+    message.setOpcode(Opcode::QUERY());
+    message.setRcode(Rcode::NOERROR());
+    message.setHeaderFlag(Message::HEADERFLAG_RD, true);
+    message.addQuestion(Question(Name("www.example.com"), RRClass::IN(),
+                                 RRType::A()));
+
+    message.toWire(renderer, tsig_ctx);
+    vector<unsigned char> expected_data;
+    UnitTestUtil::readWireData(expected_file, expected_data);
+    EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, renderer.getData(),
+                        renderer.getLength(),
+                        &expected_data[0], expected_data.size());
+}
+
+TEST_F(MessageTest, toWireWithTSIG) {
+    // Rendering a message with TSIG.  Various special cases specific to
+    // TSIG are tested in the tsig tests.  We only check the message contains
+    // a TSIG at the end and the ARCOUNT of the header is updated.
+
+    isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>;
+
+    message_render.setQid(0x2d65);
+
+    {
+        SCOPED_TRACE("Message sign with TSIG");
+        commonTSIGToWireCheck(message_render, renderer, tsig_ctx,
+                              "message_toWire2.wire");
+    }
+}
+
+TEST_F(MessageTest, toWireWithEDNSAndTSIG) {
+    // Similar to the previous test, but with an EDNS before TSIG.
+    // The wire data check will confirm the ordering.
+    isc::util::detail::gettimeFunction = testGetTime<0x4db60d1f>;
+
+    message_render.setQid(0x6cd);
+
+    EDNSPtr edns(new EDNS());
+    edns->setUDPSize(4096);
+    message_render.setEDNS(edns);
+
+    {
+        SCOPED_TRACE("Message sign with TSIG and EDNS");
+        commonTSIGToWireCheck(message_render, renderer, tsig_ctx,
+                              "message_toWire3.wire");
+    }
+}
+
 TEST_F(MessageTest, toWireWithoutOpcode) {
     message_render.setRcode(Rcode::NOERROR());
     EXPECT_THROW(message_render.toWire(renderer), InvalidMessageOperation);
@@ -529,6 +680,45 @@ TEST_F(MessageTest, toWireWithoutRcode) {
     EXPECT_THROW(message_render.toWire(renderer), InvalidMessageOperation);
 }
 
+TEST_F(MessageTest, toText) {
+    // Check toText() output for a typical DNS response with records in
+    // all sections
+    
+    factoryFromFile(message_parse, "message_toText1.wire");
+    {
+        SCOPED_TRACE("Message toText test (basic case)");
+        ifstream ifs;
+        unittests::openTestData("message_toText1.txt", ifs);
+        unittests::matchTextData(ifs, message_parse.toText());
+    }
+
+    // Another example with EDNS.  The expected data was slightly modified
+    // from the dig output (other than replacing tabs with a space): adding
+    // a newline after the "OPT PSEUDOSECTION".  This is an intentional change
+    // in our version for better readability.
+    message_parse.clear(Message::PARSE);
+    factoryFromFile(message_parse, "message_toText2.wire");
+    {
+        SCOPED_TRACE("Message toText test with EDNS");
+        ifstream ifs;
+        unittests::openTestData("message_toText2.txt", ifs);
+        unittests::matchTextData(ifs, message_parse.toText());
+    }
+
+    // Another example with TSIG.  The expected data was slightly modified
+    // from the dig output (other than replacing tabs with a space): removing
+    // a redundant white space at the end of TSIG RDATA.  We'd rather consider
+    // it a dig's defect than a feature.
+    message_parse.clear(Message::PARSE);
+    factoryFromFile(message_parse, "message_toText3.wire");
+    {
+        SCOPED_TRACE("Message toText test with TSIG");
+        ifstream ifs;
+        unittests::openTestData("message_toText3.txt", ifs);
+        unittests::matchTextData(ifs, message_parse.toText());
+    }
+}
+
 TEST_F(MessageTest, toTextWithoutOpcode) {
     message_render.setRcode(Rcode::NOERROR());
     EXPECT_THROW(message_render.toText(), InvalidMessageOperation);
diff --git a/src/lib/dns/tests/run_unittests.cc b/src/lib/dns/tests/run_unittests.cc
index 3cdc61d..18eb0a5 100644
--- a/src/lib/dns/tests/run_unittests.cc
+++ b/src/lib/dns/tests/run_unittests.cc
@@ -14,13 +14,16 @@
 
 #include <gtest/gtest.h>
 
+#include <util/unittests/testdata.h>
 #include <dns/tests/unittest_util.h>
 
 int
 main(int argc, char* argv[]) {
     ::testing::InitGoogleTest(&argc, argv);
     isc::UnitTestUtil::addDataPath(TEST_DATA_SRCDIR);
+    isc::util::unittests::addTestDataPath(TEST_DATA_SRCDIR);
     isc::UnitTestUtil::addDataPath(TEST_DATA_BUILDDIR);
+    isc::util::unittests::addTestDataPath(TEST_DATA_BUILDDIR);
 
     return (RUN_ALL_TESTS());
 }
diff --git a/src/lib/dns/tests/testdata/Makefile.am b/src/lib/dns/tests/testdata/Makefile.am
index 31771bb..8a83aae 100644
--- a/src/lib/dns/tests/testdata/Makefile.am
+++ b/src/lib/dns/tests/testdata/Makefile.am
@@ -3,6 +3,12 @@ CLEANFILES = *.wire
 BUILT_SOURCES = edns_toWire1.wire edns_toWire2.wire edns_toWire3.wire
 BUILT_SOURCES += edns_toWire4.wire
 BUILT_SOURCES += message_fromWire10.wire message_fromWire11.wire
+BUILT_SOURCES += message_fromWire12.wire message_fromWire13.wire
+BUILT_SOURCES += message_fromWire14.wire message_fromWire15.wire
+BUILT_SOURCES += message_fromWire16.wire
+BUILT_SOURCES += message_toWire2.wire message_toWire3.wire
+BUILT_SOURCES += message_toText1.wire message_toText2.wire
+BUILT_SOURCES += message_toText3.wire
 BUILT_SOURCES += name_toWire5.wire name_toWire6.wire
 BUILT_SOURCES += rdatafields1.wire rdatafields2.wire rdatafields3.wire
 BUILT_SOURCES += rdatafields4.wire rdatafields5.wire rdatafields6.wire
@@ -33,6 +39,7 @@ BUILT_SOURCES += rdata_tsig_fromWire9.wire
 BUILT_SOURCES += rdata_tsig_toWire1.wire rdata_tsig_toWire2.wire
 BUILT_SOURCES += rdata_tsig_toWire3.wire rdata_tsig_toWire4.wire
 BUILT_SOURCES += rdata_tsig_toWire5.wire
+BUILT_SOURCES += tsigrecord_toWire1.wire tsigrecord_toWire2.wire
 
 # NOTE: keep this in sync with real file listing
 # so is included in tarball
@@ -45,8 +52,13 @@ EXTRA_DIST += message_fromWire3 message_fromWire4
 EXTRA_DIST += message_fromWire5 message_fromWire6
 EXTRA_DIST += message_fromWire7 message_fromWire8
 EXTRA_DIST += message_fromWire9 message_fromWire10.spec
-EXTRA_DIST += message_fromWire11.spec
-EXTRA_DIST += message_toWire1
+EXTRA_DIST += message_fromWire11.spec message_fromWire12.spec
+EXTRA_DIST += message_fromWire13.spec message_fromWire14.spec
+EXTRA_DIST += message_fromWire15.spec message_fromWire16.spec
+EXTRA_DIST += message_toWire1 message_toWire2.spec message_toWire3.spec
+EXTRA_DIST += message_toText1.txt message_toText1.spec
+EXTRA_DIST += message_toText2.txt message_toText2.spec
+EXTRA_DIST += message_toText3.txt message_toText3.spec
 EXTRA_DIST += name_fromWire1 name_fromWire2 name_fromWire3_1 name_fromWire3_2
 EXTRA_DIST += name_fromWire4 name_fromWire6 name_fromWire7 name_fromWire8
 EXTRA_DIST += name_fromWire9 name_fromWire10 name_fromWire11 name_fromWire12
@@ -66,7 +78,8 @@ EXTRA_DIST += rdata_nsec_fromWire6.spec rdata_nsec_fromWire7.spec
 EXTRA_DIST += rdata_nsec_fromWire8.spec rdata_nsec_fromWire9.spec
 EXTRA_DIST += rdata_nsec_fromWire10.spec
 EXTRA_DIST += rdata_nsec3param_fromWire1
-EXTRA_DIST += rdata_nsec3_fromWire1 rdata_nsec3_fromWire3
+EXTRA_DIST += rdata_nsec3_fromWire1
+EXTRA_DIST += rdata_nsec3_fromWire2.spec rdata_nsec3_fromWire3
 EXTRA_DIST += rdata_nsec3_fromWire4.spec rdata_nsec3_fromWire5.spec
 EXTRA_DIST += rdata_nsec3_fromWire6.spec rdata_nsec3_fromWire7.spec
 EXTRA_DIST += rdata_nsec3_fromWire8.spec rdata_nsec3_fromWire9.spec
@@ -94,7 +107,7 @@ EXTRA_DIST += rdata_tsig_fromWire9.spec
 EXTRA_DIST += rdata_tsig_toWire1.spec rdata_tsig_toWire2.spec
 EXTRA_DIST += rdata_tsig_toWire3.spec rdata_tsig_toWire4.spec
 EXTRA_DIST += rdata_tsig_toWire5.spec
-EXTRA_DIST += rdata_nsec3_fromWire2.spec
+EXTRA_DIST += tsigrecord_toWire1.spec tsigrecord_toWire2.spec
 
 .spec.wire:
 	./gen-wiredata.py -o $@ $<
diff --git a/src/lib/dns/tests/testdata/gen-wiredata.py.in b/src/lib/dns/tests/testdata/gen-wiredata.py.in
index 72cbdaa..7a82bfd 100755
--- a/src/lib/dns/tests/testdata/gen-wiredata.py.in
+++ b/src/lib/dns/tests/testdata/gen-wiredata.py.in
@@ -15,7 +15,7 @@
 # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
 # WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
-import configparser, re, time, sys
+import configparser, re, time, socket, sys
 from datetime import datetime
 from optparse import OptionParser
 
@@ -215,6 +215,74 @@ class EDNS:
         f.write('# RDLEN=%d\n' % self.rdlen)
         f.write('%04x\n' % self.rdlen)
 
+class RR:
+    '''This is a base class for various types of RR test data.
+    For each RR type (A, AAAA, NS, etc), we define a derived class of RR
+    to dump type specific RDATA parameters.  This class defines parameters
+    common to all types of RDATA, namely the owner name, RR class and TTL.
+    The dump() method of derived classes are expected to call dump_header(),
+    whose default implementation is provided in this class.  This method
+    decides whether to dump the test data as an RR (with name, type, class)
+    or only as RDATA (with its length), and dumps the corresponding data
+    via the specified file object.
+
+    By convention we assume derived classes are named after the common
+    standard mnemonic of the corresponding RR types.  For example, the
+    derived class for the RR type SOA should be named "SOA".
+
+    Configurable parameters are as follows:
+    - as_rr (bool): Whether or not the data is to be dumped as an RR.  False
+      by default.
+    - rr_class (string): The RR class of the data.  Only meaningful when the
+      data is dumped as an RR.  Default is 'IN'.
+    - rr_ttl (integer): The TTL value of the RR.  Only meaningful when the
+      data is dumped as an RR.  Default is 86400 (1 day).
+    '''
+
+    def __init__(self):
+        self.as_rr = False
+        # only when as_rr is True, same for class/TTL:
+        self.rr_name = 'example.com'
+        self.rr_class = 'IN'
+        self.rr_ttl = 86400
+    def dump_header(self, f, rdlen):
+        type_txt = self.__class__.__name__
+        type_code = parse_value(type_txt, dict_rrtype)
+        if self.as_rr:
+            rrclass = parse_value(self.rr_class, dict_rrclass)
+            f.write('\n# %s RR (QNAME=%s Class=%s TTL=%d RDLEN=%d)\n' %
+                    (type_txt, self.rr_name,
+                     code_totext(rrclass, rdict_rrclass), self.rr_ttl, rdlen))
+            f.write('%s %04x %04x %08x %04x\n' %
+                    (encode_name(self.rr_name), type_code, rrclass,
+                     self.rr_ttl, rdlen))
+        else:
+            f.write('\n# %s RDATA (RDLEN=%d)\n' % (type_txt, rdlen))
+            f.write('%04x\n' % rdlen)
+
+class A(RR):
+    rdlen = 4                   # fixed by default
+    address = '192.0.2.1'
+
+    def dump(self, f):
+        self.dump_header(f, self.rdlen)
+        f.write('# Address=%s\n' % (self.address))
+        bin_address = socket.inet_aton(self.address)
+        f.write('%02x%02x%02x%02x\n' % (bin_address[0], bin_address[1],
+                                        bin_address[2], bin_address[3]))
+
+class NS(RR):
+    rdlen = None                   # auto calculate
+    nsname = 'ns.example.com'
+
+    def dump(self, f):
+        nsname_wire = encode_name(self.nsname)
+        if self.rdlen is None:
+            self.rdlen = len(nsname_wire) / 2
+        self.dump_header(f, self.rdlen)
+        f.write('# NS name=%s\n' % (self.nsname))
+        f.write('%s\n' % nsname_wire)
+
 class SOA:
     # this currently doesn't support name compression within the RDATA.
     rdlen = -1                  # auto-calculate
@@ -432,7 +500,7 @@ class RRSIG:
         f.write('# Tag=%d Signer=%s and Signature\n' % (self.tag, self.signer))
         f.write('%04x %s %s\n' % (self.tag, name_wire, sig_wire))
 
-class TSIG:
+class TSIG(RR):
     rdlen = None                # auto-calculate
     algorithm = 'hmac-sha256'
     time_signed = 1286978795    # arbitrarily chosen default
@@ -444,12 +512,18 @@ class TSIG:
     other_len = None         # 6 if error is BADTIME; otherwise 0
     other_data = None        # use time_signed + fudge + 1 for BADTIME
     dict_macsize = { 'hmac-md5' : 16, 'hmac-sha1' : 20, 'hmac-sha256' : 32 }
+
+    # TSIG has some special defaults
+    def __init__(self):
+        super().__init__()
+        self.rr_class = 'ANY'
+        self.rr_ttl = 0
+
     def dump(self, f):
         if str(self.algorithm) == 'hmac-md5':
             name_wire = encode_name('hmac-md5.sig-alg.reg.int')
         else:
             name_wire = encode_name(self.algorithm)
-        rdlen = self.rdlen
         mac_size = self.mac_size
         if mac_size is None:
             if self.algorithm in self.dict_macsize.keys():
@@ -468,11 +542,10 @@ class TSIG:
                 if self.error == 18 else ''
         else:
             other_data = encode_string(self.other_data, other_len)
-        if rdlen is None:
-            rdlen = int(len(name_wire) / 2 + 16 + len(mac) / 2 + \
-                            len(other_data) / 2)
-        f.write('\n# TSIG RDATA (RDLEN=%d)\n' % rdlen)
-        f.write('%04x\n' % rdlen);
+        if self.rdlen is None:
+            self.rdlen = int(len(name_wire) / 2 + 16 + len(mac) / 2 + \
+                                 len(other_data) / 2)
+        self.dump_header(f, self.rdlen)
         f.write('# Algorithm=%s Time-Signed=%d Fudge=%d\n' %
                 (self.algorithm, self.time_signed, self.fudge))
         f.write('%s %012x %04x\n' % (name_wire, self.time_signed, self.fudge))
@@ -488,7 +561,8 @@ def get_config_param(section):
     config_param = {'name' : (Name, {}),
                     'header' : (DNSHeader, header_xtables),
                     'question' : (DNSQuestion, question_xtables),
-                    'edns' : (EDNS, {}), 'soa' : (SOA, {}), 'txt' : (TXT, {}),
+                    'edns' : (EDNS, {}), 'a' : (A, {}), 'ns' : (NS, {}),
+                    'soa' : (SOA, {}), 'txt' : (TXT, {}),
                     'rp' : (RP, {}), 'rrsig' : (RRSIG, {}),
                     'nsec' : (NSEC, {}), 'nsec3' : (NSEC3, {}),
                     'tsig' : (TSIG, {}) }
diff --git a/src/lib/dns/tests/testdata/message_fromWire12.spec b/src/lib/dns/tests/testdata/message_fromWire12.spec
new file mode 100644
index 0000000..4eadeed
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_fromWire12.spec
@@ -0,0 +1,21 @@
+#
+# A simple DNS response message with TSIG signed, but the owner name of TSIG
+# is compressed
+#
+
+[custom]
+sections: header:question:tsig
+[header]
+id: 0x2d65
+rd: 1
+arcount: 1
+[question]
+name: www.example.com
+[tsig]
+as_rr: True
+rr_name: ptr=12
+algorithm: hmac-md5
+time_signed: 0x4da8877a
+mac_size: 16
+mac: 0x227026ad297beee721ce6c6fff1e9ef3
+original_id: 0x2d65
diff --git a/src/lib/dns/tests/testdata/message_fromWire13.spec b/src/lib/dns/tests/testdata/message_fromWire13.spec
new file mode 100644
index 0000000..e81ec4c
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_fromWire13.spec
@@ -0,0 +1,20 @@
+#
+# Invalid TSIG: containing 2 TSIG RRs.
+#
+
+[custom]
+sections: header:question:tsig:tsig
+[header]
+id: 0x2d65
+rd: 1
+arcount: 2
+[question]
+name: www.example.com
+[tsig]
+as_rr: True
+rr_name: www.example.com
+algorithm: hmac-md5
+time_signed: 0x4da8877a
+mac_size: 16
+mac: 0x227026ad297beee721ce6c6fff1e9ef3
+original_id: 0x2d65
diff --git a/src/lib/dns/tests/testdata/message_fromWire14.spec b/src/lib/dns/tests/testdata/message_fromWire14.spec
new file mode 100644
index 0000000..bf68a93
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_fromWire14.spec
@@ -0,0 +1,21 @@
+#
+# Invalid TSIG: not in the additional section.
+#
+
+[custom]
+sections: header:question:tsig
+[header]
+id: 0x2d65
+rd: 1
+# TSIG goes to the answer section
+ancount: 1
+[question]
+name: www.example.com
+[tsig]
+as_rr: True
+rr_name: www.example.com
+algorithm: hmac-md5
+time_signed: 0x4da8877a
+mac_size: 16
+mac: 0x227026ad297beee721ce6c6fff1e9ef3
+original_id: 0x2d65
diff --git a/src/lib/dns/tests/testdata/message_fromWire15.spec b/src/lib/dns/tests/testdata/message_fromWire15.spec
new file mode 100644
index 0000000..25d810f
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_fromWire15.spec
@@ -0,0 +1,22 @@
+#
+# Invalid TSIG: not at the end of the message
+#
+
+[custom]
+sections: header:question:tsig:edns
+[header]
+id: 0x2d65
+rd: 1
+arcount: 2
+[question]
+name: www.example.com
+[tsig]
+as_rr: True
+rr_name: www.example.com
+algorithm: hmac-md5
+time_signed: 0x4da8877a
+mac_size: 16
+mac: 0x227026ad297beee721ce6c6fff1e9ef3
+original_id: 0x2d65
+[edns]
+# (all default)
diff --git a/src/lib/dns/tests/testdata/message_fromWire16.spec b/src/lib/dns/tests/testdata/message_fromWire16.spec
new file mode 100644
index 0000000..be0abc3
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_fromWire16.spec
@@ -0,0 +1,21 @@
+#
+# Invalid TSIG: not in the additional section.
+#
+
+[custom]
+sections: header:question:tsig
+[header]
+id: 0x2d65
+rd: 1
+arcount: 1
+[question]
+name: www.example.com
+[tsig]
+as_rr: True
+rr_class: IN
+rr_name: www.example.com
+algorithm: hmac-md5
+time_signed: 0x4da8877a
+mac_size: 16
+mac: 0x227026ad297beee721ce6c6fff1e9ef3
+original_id: 0x2d65
diff --git a/src/lib/dns/tests/testdata/message_toText1.spec b/src/lib/dns/tests/testdata/message_toText1.spec
new file mode 100644
index 0000000..b31310e
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_toText1.spec
@@ -0,0 +1,24 @@
+#
+# A standard DNS message (taken from an invocation of dig)
+#
+
+[custom]
+sections: header:question:a/1:ns:a/2
+[header]
+id: 29174
+qr: 1
+aa: 1
+ancount: 1
+nscount: 1
+arcount: 1
+[question]
+name: www.example.com
+[a/1]
+as_rr: True
+rr_name: www.example.com
+address: 192.0.2.80
+[ns]
+as_rr: True
+[a/2]
+as_rr: True
+rr_name: ns.example.com
diff --git a/src/lib/dns/tests/testdata/message_toText1.txt b/src/lib/dns/tests/testdata/message_toText1.txt
new file mode 100644
index 0000000..58c7239
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_toText1.txt
@@ -0,0 +1,14 @@
+;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 29174
+;; flags: qr aa; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 1
+
+;; QUESTION SECTION:
+;www.example.com. IN A
+
+;; ANSWER SECTION:
+www.example.com. 86400 IN A 192.0.2.80
+
+;; AUTHORITY SECTION:
+example.com. 86400 IN NS ns.example.com.
+
+;; ADDITIONAL SECTION:
+ns.example.com. 86400 IN A 192.0.2.1
diff --git a/src/lib/dns/tests/testdata/message_toText2.spec b/src/lib/dns/tests/testdata/message_toText2.spec
new file mode 100644
index 0000000..978aab3
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_toText2.spec
@@ -0,0 +1,14 @@
+#
+# A standard DNS message with EDNS (taken from an invocation of dig)
+#
+
+[custom]
+sections: header:question:edns
+[header]
+id: 45981
+qr: 1
+rcode: refused
+arcount: 1
+[question]
+[edns]
+do: 1
diff --git a/src/lib/dns/tests/testdata/message_toText2.txt b/src/lib/dns/tests/testdata/message_toText2.txt
new file mode 100644
index 0000000..42cc2c1
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_toText2.txt
@@ -0,0 +1,8 @@
+;; ->>HEADER<<- opcode: QUERY, status: REFUSED, id: 45981
+;; flags: qr; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1
+
+;; OPT PSEUDOSECTION:
+; EDNS: version: 0, flags: do; udp: 4096
+
+;; QUESTION SECTION:
+;example.com. IN A
diff --git a/src/lib/dns/tests/testdata/message_toText3.spec b/src/lib/dns/tests/testdata/message_toText3.spec
new file mode 100644
index 0000000..a74ea1b
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_toText3.spec
@@ -0,0 +1,31 @@
+#
+# A standard DNS message with TSIG (taken from an invocation of dig)
+#
+
+[custom]
+sections: header:question:a/1:ns:a/2:tsig
+[header]
+id: 10140
+qr: 1
+aa: 1
+ancount: 1
+nscount: 1
+arcount: 2
+[question]
+name: www.example.com
+[a/1]
+as_rr: True
+rr_name: www.example.com
+address: 192.0.2.80
+[ns]
+as_rr: True
+[a/2]
+as_rr: True
+rr_name: ns.example.com
+[tsig]
+as_rr: True
+rr_name: www.example.com
+algorithm: hmac-md5
+time_signed: 1304384318
+original_id: 10140
+mac: 0x5257c80396f2fa95b20c77ae9a652fb2
diff --git a/src/lib/dns/tests/testdata/message_toText3.txt b/src/lib/dns/tests/testdata/message_toText3.txt
new file mode 100644
index 0000000..359b9c5
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_toText3.txt
@@ -0,0 +1,17 @@
+;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 10140
+;; flags: qr aa; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 2
+
+;; QUESTION SECTION:
+;www.example.com. IN A
+
+;; ANSWER SECTION:
+www.example.com. 86400 IN A 192.0.2.80
+
+;; AUTHORITY SECTION:
+example.com. 86400 IN NS ns.example.com.
+
+;; ADDITIONAL SECTION:
+ns.example.com. 86400 IN A 192.0.2.1
+
+;; TSIG PSEUDOSECTION:
+www.example.com. 0 ANY TSIG hmac-md5.sig-alg.reg.int. 1304384318 300 16 UlfIA5by+pWyDHeummUvsg== 10140 NOERROR 0
diff --git a/src/lib/dns/tests/testdata/message_toWire2.spec b/src/lib/dns/tests/testdata/message_toWire2.spec
new file mode 100644
index 0000000..d256052
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_toWire2.spec
@@ -0,0 +1,21 @@
+#
+# A simple DNS query message with TSIG signed
+#
+
+[custom]
+sections: header:question:tsig
+[header]
+id: 0x2d65
+rd: 1
+arcount: 1
+[question]
+name: www.example.com
+[tsig]
+as_rr: True
+# TSIG QNAME won't be compressed
+rr_name: www.example.com
+algorithm: hmac-md5
+time_signed: 0x4da8877a
+mac_size: 16
+mac: 0x227026ad297beee721ce6c6fff1e9ef3
+original_id: 0x2d65
diff --git a/src/lib/dns/tests/testdata/message_toWire3.spec b/src/lib/dns/tests/testdata/message_toWire3.spec
new file mode 100644
index 0000000..c8e9453
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_toWire3.spec
@@ -0,0 +1,22 @@
+#
+# A simple DNS query message with EDNS and TSIG
+#
+
+[custom]
+sections: header:question:edns:tsig
+[header]
+id: 0x06cd
+rd: 1
+arcount: 2
+[question]
+name: www.example.com
+[edns]
+[tsig]
+as_rr: True
+# TSIG QNAME won't be compressed
+rr_name: www.example.com
+algorithm: hmac-md5
+time_signed: 0x4db60d1f
+mac_size: 16
+mac: 0x93444053881c83d7eb120e86f25b369e
+original_id: 0x06cd
diff --git a/src/lib/dns/tests/testdata/tsigrecord_toWire1.spec b/src/lib/dns/tests/testdata/tsigrecord_toWire1.spec
new file mode 100644
index 0000000..a25dc46
--- /dev/null
+++ b/src/lib/dns/tests/testdata/tsigrecord_toWire1.spec
@@ -0,0 +1,16 @@
+#
+# A simple TSIG RR (some of the parameters are taken from a live example
+# and don't have a specific meaning)
+#
+
+[custom]
+sections: tsig
+[tsig]
+as_rr: True
+# TSIG QNAME won't be compressed
+rr_name: www.example.com
+algorithm: hmac-md5
+time_signed: 0x4da8877a
+mac_size: 16
+mac: 0xdadadadadadadadadadadadadadadada
+original_id: 0x2d65
diff --git a/src/lib/dns/tests/testdata/tsigrecord_toWire2.spec b/src/lib/dns/tests/testdata/tsigrecord_toWire2.spec
new file mode 100644
index 0000000..f667e4c
--- /dev/null
+++ b/src/lib/dns/tests/testdata/tsigrecord_toWire2.spec
@@ -0,0 +1,19 @@
+#
+# TSIG RR after some names that could (unexpectedly) cause name compression
+#
+
+[custom]
+sections: name/1:name/2:tsig
+[name/1]
+name: hmac-md5.sig-alg.reg.int
+[name/2]
+name: foo.example.com
+[tsig]
+as_rr: True
+# TSIG QNAME won't be compressed
+rr_name: www.example.com
+algorithm: hmac-md5
+time_signed: 0x4da8877a
+mac_size: 16
+mac: 0xdadadadadadadadadadadadadadadada
+original_id: 0x2d65
diff --git a/src/lib/dns/tests/tsig_unittest.cc b/src/lib/dns/tests/tsig_unittest.cc
new file mode 100644
index 0000000..efa0490
--- /dev/null
+++ b/src/lib/dns/tests/tsig_unittest.cc
@@ -0,0 +1,505 @@
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <time.h>
+#include <string>
+#include <stdexcept>
+#include <vector>
+
+#include <boost/scoped_ptr.hpp>
+
+#include <gtest/gtest.h>
+
+#include <exceptions/exceptions.h>
+
+#include <util/buffer.h>
+#include <util/encode/base64.h>
+#include <util/unittests/newhook.h>
+#include <util/time_utilities.h>
+
+#include <dns/message.h>
+#include <dns/messagerenderer.h>
+#include <dns/question.h>
+#include <dns/opcode.h>
+#include <dns/rcode.h>
+#include <dns/rrclass.h>
+#include <dns/rrtype.h>
+#include <dns/tsig.h>
+#include <dns/tsigkey.h>
+#include <dns/tsigrecord.h>
+
+#include <dns/tests/unittest_util.h>
+
+using namespace std;
+using namespace isc;
+using namespace isc::dns;
+using namespace isc::util;
+using namespace isc::util::encode;
+using namespace isc::dns::rdata;
+using isc::UnitTestUtil;
+
+// See dnssectime.cc
+namespace isc {
+namespace util {
+namespace detail {
+extern int64_t (*gettimeFunction)();
+}
+}
+}
+
+namespace {
+// See dnssectime_unittest.cc
+template <int64_t NOW>
+int64_t
+testGetTime() {
+    return (NOW);
+}
+
+class TSIGTest : public ::testing::Test {
+protected:
+    TSIGTest() :
+        tsig_ctx(NULL), qid(0x2d65), test_name("www.example.com"),
+        test_class(RRClass::IN()), test_ttl(86400), message(Message::RENDER),
+        buffer(0), renderer(buffer)
+    {
+        // Make sure we use the system time by default so that we won't be
+        // confused due to other tests that tweak the time.
+        isc::util::detail::gettimeFunction = NULL;
+
+        decodeBase64("SFuWd/q99SzF8Yzd1QbB9g==", secret);
+        tsig_ctx.reset(new TSIGContext(TSIGKey(test_name,
+                                               TSIGKey::HMACMD5_NAME(),
+                                               &secret[0], secret.size())));
+        tsig_verify_ctx.reset(new TSIGContext(TSIGKey(test_name,
+                                                      TSIGKey::HMACMD5_NAME(),
+                                                      &secret[0],
+                                                      secret.size())));
+    }
+    ~TSIGTest() {
+        isc::util::detail::gettimeFunction = NULL;
+    }
+
+    // Many of the tests below create some DNS message and sign it under
+    // some specific TSIG context.  This helper method unifies the common
+    // logic with slightly different parameters.
+    ConstTSIGRecordPtr createMessageAndSign(uint16_t qid, const Name& qname,
+                                            TSIGContext* ctx,
+                                            unsigned int message_flags =
+                                            RD_FLAG,
+                                            RRType qtype = RRType::A(),
+                                            const char* answer_data = NULL,
+                                            const RRType* answer_type = NULL,
+                                            bool add_question = true,
+                                            Rcode rcode = Rcode::NOERROR());
+
+    // bit-wise constant flags to configure DNS header flags for test
+    // messages.
+    static const unsigned int QR_FLAG = 0x1;
+    static const unsigned int AA_FLAG = 0x2;
+    static const unsigned int RD_FLAG = 0x4;
+
+    boost::scoped_ptr<TSIGContext> tsig_ctx;
+    boost::scoped_ptr<TSIGContext> tsig_verify_ctx;
+    const uint16_t qid;
+    const Name test_name;
+    const RRClass test_class;
+    const RRTTL test_ttl;
+    Message message;
+    OutputBuffer buffer;
+    MessageRenderer renderer;
+    vector<uint8_t> secret;
+};
+
+ConstTSIGRecordPtr
+TSIGTest::createMessageAndSign(uint16_t id, const Name& qname,
+                               TSIGContext* ctx, unsigned int message_flags,
+                               RRType qtype, const char* answer_data,
+                               const RRType* answer_type, bool add_question,
+                               Rcode rcode)
+{
+    message.clear(Message::RENDER);
+    message.setQid(id);
+    message.setOpcode(Opcode::QUERY());
+    message.setRcode(rcode);
+    if ((message_flags & QR_FLAG) != 0) {
+        message.setHeaderFlag(Message::HEADERFLAG_QR);
+    }
+    if ((message_flags & AA_FLAG) != 0) {
+        message.setHeaderFlag(Message::HEADERFLAG_AA);
+    }
+    if ((message_flags & RD_FLAG) != 0) {
+        message.setHeaderFlag(Message::HEADERFLAG_RD);
+    }
+    if (add_question) {
+        message.addQuestion(Question(qname, test_class, qtype));
+    }
+    if (answer_data != NULL) {
+        if (answer_type == NULL) {
+            answer_type = &qtype;
+        }
+        RRsetPtr answer_rrset(new RRset(qname, test_class, *answer_type,
+                                        test_ttl));
+        answer_rrset->addRdata(createRdata(*answer_type, test_class,
+                                           answer_data));
+        message.addRRset(Message::SECTION_ANSWER, answer_rrset);
+    }
+    renderer.clear();
+    message.toWire(renderer);
+
+    ConstTSIGRecordPtr tsig = ctx->sign(id, renderer.getData(),
+                                        renderer.getLength());
+    EXPECT_EQ(TSIGContext::SIGNED, ctx->getState());
+
+    return (tsig);
+}
+
+void
+commonTSIGChecks(ConstTSIGRecordPtr tsig, uint16_t expected_qid,
+                 uint64_t expected_timesigned,
+                 const uint8_t* expected_mac, size_t expected_maclen,
+                 uint16_t expected_error = 0,
+                 uint16_t expected_otherlen = 0,
+                 const uint8_t* expected_otherdata = NULL,
+                 const Name& expected_algorithm = TSIGKey::HMACMD5_NAME())
+{
+    ASSERT_TRUE(tsig != NULL);
+    const any::TSIG& tsig_rdata = tsig->getRdata();
+
+    EXPECT_EQ(expected_algorithm, tsig_rdata.getAlgorithm());
+    EXPECT_EQ(expected_timesigned, tsig_rdata.getTimeSigned());
+    EXPECT_EQ(300, tsig_rdata.getFudge());
+    EXPECT_EQ(expected_maclen, tsig_rdata.getMACSize());
+    EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
+                        tsig_rdata.getMAC(), tsig_rdata.getMACSize(),
+                        expected_mac, expected_maclen);
+    EXPECT_EQ(expected_qid, tsig_rdata.getOriginalID());
+    EXPECT_EQ(expected_error, tsig_rdata.getError());
+    EXPECT_EQ(expected_otherlen, tsig_rdata.getOtherLen());
+    EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
+                        tsig_rdata.getOtherData(), tsig_rdata.getOtherLen(),
+                        expected_otherdata, expected_otherlen);
+}
+
+TEST_F(TSIGTest, initialState) {
+    // Until signing or verifying, the state should be INIT
+    EXPECT_EQ(TSIGContext::INIT, tsig_ctx->getState());
+
+    // And there should be no error code.
+    EXPECT_EQ(TSIGError(Rcode::NOERROR()), tsig_ctx->getError());
+}
+
+// Example output generated by
+// "dig -y www.example.com:SFuWd/q99SzF8Yzd1QbB9g== www.example.com
+// QID: 0x2d65
+// Time Signed: 0x00004da8877a
+// MAC: 227026ad297beee721ce6c6fff1e9ef3
+const uint8_t common_expected_mac[] = {
+    0x22, 0x70, 0x26, 0xad, 0x29, 0x7b, 0xee, 0xe7,
+    0x21, 0xce, 0x6c, 0x6f, 0xff, 0x1e, 0x9e, 0xf3
+};
+TEST_F(TSIGTest, sign) {
+    isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>;
+
+    {
+        SCOPED_TRACE("Sign test for query");
+        commonTSIGChecks(createMessageAndSign(qid, test_name, tsig_ctx.get()),
+                         qid, 0x4da8877a, common_expected_mac,
+                         sizeof(common_expected_mac));
+    }
+}
+
+// Same test as sign, but specifying the key name with upper-case (i.e.
+// non canonical) characters.  The digest must be the same.  It should actually
+// be ensured at the level of TSIGKey, but we confirm that at this level, too.
+TEST_F(TSIGTest, signUsingUpperCasedKeyName) {
+    isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>;
+
+    TSIGContext cap_ctx(TSIGKey(Name("WWW.EXAMPLE.COM"),
+                                TSIGKey::HMACMD5_NAME(),
+                                &secret[0], secret.size()));
+
+    {
+        SCOPED_TRACE("Sign test for query using non canonical key name");
+        commonTSIGChecks(createMessageAndSign(qid, test_name, &cap_ctx), qid,
+                         0x4da8877a, common_expected_mac,
+                         sizeof(common_expected_mac));
+    }
+}
+
+// Same as the previous test, but for the algorithm name.
+TEST_F(TSIGTest, signUsingUpperCasedAlgorithmName) {
+    isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>;
+
+    TSIGContext cap_ctx(TSIGKey(test_name,
+                                Name("HMAC-md5.SIG-alg.REG.int"),
+                                &secret[0], secret.size()));
+
+    {
+        SCOPED_TRACE("Sign test for query using non canonical algorithm name");
+        commonTSIGChecks(createMessageAndSign(qid, test_name, &cap_ctx), qid,
+                         0x4da8877a, common_expected_mac,
+                         sizeof(common_expected_mac));
+    }
+}
+
+TEST_F(TSIGTest, signAtActualTime) {
+    // Sign the message using the actual time, and check the accuracy of it.
+    // We cannot reasonably predict the expected MAC, so don't bother to
+    // check it.
+    const uint64_t now = static_cast<uint64_t>(time(NULL));
+
+    {
+        SCOPED_TRACE("Sign test for query at actual time");
+        ConstTSIGRecordPtr tsig = createMessageAndSign(qid, test_name,
+                                                       tsig_ctx.get());
+        const any::TSIG& tsig_rdata = tsig->getRdata();
+
+        // Check the resulted time signed is in the range of [now, now + 5]
+        // (5 is an arbitrary choice).  Note that due to the order of the call
+        // to time() and sign(), time signed must not be smaller than the
+        // current time.
+        EXPECT_LE(now, tsig_rdata.getTimeSigned());
+        EXPECT_GE(now + 5, tsig_rdata.getTimeSigned());
+    }
+}
+
+TEST_F(TSIGTest, signBadData) {
+    // some specific bad data should be rejected proactively.
+    const unsigned char dummy_data = 0;
+    EXPECT_THROW(tsig_ctx->sign(0, NULL, 10), InvalidParameter);
+    EXPECT_THROW(tsig_ctx->sign(0, &dummy_data, 0), InvalidParameter);
+}
+
+#ifdef ENABLE_CUSTOM_OPERATOR_NEW
+// We enable this test only when we enable custom new/delete at build time
+// We could enable/disable the test runtime using the gtest filter, but
+// we'd basically like to minimize the number of disabled tests (they
+// should generally be considered tests that temporarily fail and should
+// be fixed).
+TEST_F(TSIGTest, signExceptionSafety) {
+    // Check sign() provides the strong exception guarantee for the simpler
+    // case (with a key error and empty MAC).  The general case is more
+    // complicated and involves more memory allocation, so the test result
+    // won't be reliable.
+
+    tsig_verify_ctx->verifyTentative(createMessageAndSign(qid, test_name,
+                                                          tsig_ctx.get()),
+                                     TSIGError::BAD_KEY());
+    // At this point the state should be changed to "CHECKED"
+    ASSERT_EQ(TSIGContext::CHECKED, tsig_verify_ctx->getState());
+    try {
+        int dummydata;
+        isc::util::unittests::force_throw_on_new = true;
+        isc::util::unittests::throw_size_on_new = sizeof(TSIGRecord);
+        tsig_verify_ctx->sign(0, &dummydata, sizeof(dummydata));
+        isc::util::unittests::force_throw_on_new = false;
+        ASSERT_FALSE(true) << "Expected throw on new, but it didn't happen";
+    } catch (const std::bad_alloc&) {
+        isc::util::unittests::force_throw_on_new = false;
+
+        // sign() threw, so the state should still be "CHECKED".
+        EXPECT_EQ(TSIGContext::CHECKED, tsig_verify_ctx->getState());
+    }
+    isc::util::unittests::force_throw_on_new = false;
+}
+#endif  // ENABLE_CUSTOM_OPERATOR_NEW
+
+// Same test as "sign" but use a different algorithm just to confirm we don't
+// naively hardcode constants specific to a particular algorithm.
+// Test data generated by
+// "dig -y hmac-sha1:www.example.com:MA+QDhXbyqUak+qnMFyTyEirzng= www.example.com"
+//   QID: 0x0967, RDflag
+//   Current Time: 00004da8be86
+//   Time Signed:  00004dae7d5f
+//   HMAC Size: 20
+//   HMAC: 415340c7daf824ed684ee586f7b5a67a2febc0d3
+TEST_F(TSIGTest, signUsingHMACSHA1) {
+    isc::util::detail::gettimeFunction = testGetTime<0x4dae7d5f>;
+
+    secret.clear();
+    decodeBase64("MA+QDhXbyqUak+qnMFyTyEirzng=", secret);
+    TSIGContext sha1_ctx(TSIGKey(test_name, TSIGKey::HMACSHA1_NAME(),
+                                 &secret[0], secret.size()));
+
+    const uint16_t sha1_qid = 0x0967;
+    const uint8_t expected_mac[] = {
+        0x41, 0x53, 0x40, 0xc7, 0xda, 0xf8, 0x24, 0xed, 0x68, 0x4e,
+        0xe5, 0x86, 0xf7, 0xb5, 0xa6, 0x7a, 0x2f, 0xeb, 0xc0, 0xd3
+    };
+    {
+        SCOPED_TRACE("Sign test using HMAC-SHA1");
+        commonTSIGChecks(createMessageAndSign(sha1_qid, test_name, &sha1_ctx),
+                         sha1_qid, 0x4dae7d5f, expected_mac,
+                         sizeof(expected_mac), 0, 0, NULL,
+                         TSIGKey::HMACSHA1_NAME());
+    }
+}
+
+// An example response to the signed query used for the "sign" test.
+// Answer: www.example.com. 86400 IN A 192.0.2.1
+// MAC: 8fcda66a7cd1a3b9948eb1869d384a9f
+TEST_F(TSIGTest, signResponse) {
+    isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>;
+
+    ConstTSIGRecordPtr tsig = createMessageAndSign(qid, test_name,
+                                                   tsig_ctx.get());
+    tsig_verify_ctx->verifyTentative(tsig);
+    EXPECT_EQ(TSIGContext::CHECKED, tsig_verify_ctx->getState());
+
+    // Transform the original message to a response, then sign the response
+    // with the context of "verified state".
+    tsig = createMessageAndSign(qid, test_name, tsig_verify_ctx.get(),
+                                QR_FLAG|AA_FLAG|RD_FLAG,
+                                RRType::A(), "192.0.2.1");
+    const uint8_t expected_mac[] = {
+        0x8f, 0xcd, 0xa6, 0x6a, 0x7c, 0xd1, 0xa3, 0xb9,
+        0x94, 0x8e, 0xb1, 0x86, 0x9d, 0x38, 0x4a, 0x9f
+    };
+    {
+        SCOPED_TRACE("Sign test for response");
+        commonTSIGChecks(tsig, qid, 0x4da8877a,
+                         expected_mac, sizeof(expected_mac));
+    }
+}
+
+// Example of signing multiple messages in a single TCP stream,
+// taken from data using BIND 9's "one-answer" transfer-format.
+// First message:
+//   QID: 0x3410, flags QR, AA
+//   Question: example.com/IN/AXFR
+//   Answer: example.com. 86400 IN SOA ns.example.com. root.example.com. (
+//                          2011041503 7200 3600 2592000 1200)
+//   Time Signed: 0x4da8e951
+// Second message:
+//    Answer: example.com. 86400 IN NS ns.example.com.
+//    MAC: 102458f7f62ddd7d638d746034130968
+TEST_F(TSIGTest, signContinuation) {
+    isc::util::detail::gettimeFunction = testGetTime<0x4da8e951>;
+
+    const uint16_t axfr_qid = 0x3410;
+    const Name zone_name("example.com");
+
+    // Create and sign the AXFR request, then verify it.
+    tsig_verify_ctx->verifyTentative(createMessageAndSign(axfr_qid, zone_name,
+                                                          tsig_ctx.get(), 0,
+                                                          RRType::AXFR()));
+    EXPECT_EQ(TSIGContext::CHECKED, tsig_verify_ctx->getState());
+
+    // Create and sign the first response message (we don't need the result
+    // for the purpose of this test)
+    createMessageAndSign(axfr_qid, zone_name, tsig_verify_ctx.get(),
+                         AA_FLAG|QR_FLAG, RRType::AXFR(),
+                         "ns.example.com. root.example.com. "
+                         "2011041503 7200 3600 2592000 1200",
+                         &RRType::SOA());
+
+    // Create and sign the second response message
+    const uint8_t expected_mac[] = {
+        0x10, 0x24, 0x58, 0xf7, 0xf6, 0x2d, 0xdd, 0x7d,
+        0x63, 0x8d, 0x74, 0x60, 0x34, 0x13, 0x09, 0x68
+    };
+    {
+        SCOPED_TRACE("Sign test for continued response in TCP stream");
+        commonTSIGChecks(createMessageAndSign(axfr_qid, zone_name,
+                                              tsig_verify_ctx.get(),
+                                              AA_FLAG|QR_FLAG, RRType::AXFR(),
+                                              "ns.example.com.", &RRType::NS(),
+                                              false),
+                         axfr_qid, 0x4da8e951,
+                         expected_mac, sizeof(expected_mac));
+    }
+}
+
+// BADTIME example, taken from data using specially hacked BIND 9's nsupdate
+// Query:
+//   QID: 0x1830, RD flag
+//   Current Time: 00004da8be86
+//   Time Signed:  00004da8b9d6
+//   Question: www.example.com/IN/SOA
+//(mac) 8406 7d50 b8e7 d054 3d50 5bd9 de2a bb68
+// Response:
+//   QRbit, RCODE=9(NOTAUTH)
+//   Time Signed: 00004da8b9d6 (the one in the query)
+//   MAC: d4b043f6f44495ec8a01260e39159d76
+//   Error: 0x12 (BADTIME), Other Len: 6
+//   Other data: 00004da8be86
+TEST_F(TSIGTest, badtimeResponse) {
+    isc::util::detail::gettimeFunction = testGetTime<0x4da8b9d6>;
+
+    const uint16_t test_qid = 0x7fc4;
+    ConstTSIGRecordPtr tsig = createMessageAndSign(test_qid, test_name,
+                                                   tsig_ctx.get(), 0,
+                                                   RRType::SOA());
+
+    // "advance the clock" and try validating, which should fail due to BADTIME
+    // (verifyTentative actually doesn't check the time, though)
+    isc::util::detail::gettimeFunction = testGetTime<0x4da8be86>;
+    tsig_verify_ctx->verifyTentative(tsig, TSIGError::BAD_TIME());
+    EXPECT_EQ(TSIGError::BAD_TIME(), tsig_verify_ctx->getError());
+
+    // make and sign a response in the context of TSIG error.
+    tsig = createMessageAndSign(test_qid, test_name, tsig_verify_ctx.get(),
+                                QR_FLAG, RRType::SOA(), NULL, NULL,
+                                true, Rcode::NOTAUTH());
+    const uint8_t expected_otherdata[] = { 0, 0, 0x4d, 0xa8, 0xbe, 0x86 };
+    const uint8_t expected_mac[] = {
+        0xd4, 0xb0, 0x43, 0xf6, 0xf4, 0x44, 0x95, 0xec,
+        0x8a, 0x01, 0x26, 0x0e, 0x39, 0x15, 0x9d, 0x76
+    };
+    {
+        SCOPED_TRACE("Sign test for response with BADTIME");
+        commonTSIGChecks(tsig, message.getQid(), 0x4da8b9d6,
+                         expected_mac, sizeof(expected_mac),
+                         18,     // error: BADTIME
+                         sizeof(expected_otherdata),
+                         expected_otherdata);
+    }
+}
+
+TEST_F(TSIGTest, badsigResponse) {
+    isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>;
+
+    // Sign a simple message, and force the verification to fail with
+    // BADSIG.
+    tsig_verify_ctx->verifyTentative(createMessageAndSign(qid, test_name,
+                                                          tsig_ctx.get()),
+                                     TSIGError::BAD_SIG());
+
+    // Sign the same message (which doesn't matter for this test) with the
+    // context of "checked state".
+    {
+        SCOPED_TRACE("Sign test for response with BADSIG error");
+        commonTSIGChecks(createMessageAndSign(qid, test_name,
+                                              tsig_verify_ctx.get()),
+                         message.getQid(), 0x4da8877a, NULL, 0,
+                         16);   // 16: BADSIG
+    }
+}
+
+TEST_F(TSIGTest, badkeyResponse) {
+    // A similar test as badsigResponse but for BADKEY
+    isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>;
+    tsig_verify_ctx->verifyTentative(createMessageAndSign(qid, test_name,
+                                                          tsig_ctx.get()),
+                                     TSIGError::BAD_KEY());
+    {
+        SCOPED_TRACE("Sign test for response with BADKEY error");
+        commonTSIGChecks(createMessageAndSign(qid, test_name,
+                                              tsig_verify_ctx.get()),
+                         message.getQid(), 0x4da8877a, NULL, 0,
+                         17);   // 17: BADKEYSIG
+    }
+}
+
+} // end namespace
diff --git a/src/lib/dns/tests/tsigerror_unittest.cc b/src/lib/dns/tests/tsigerror_unittest.cc
new file mode 100644
index 0000000..5866587
--- /dev/null
+++ b/src/lib/dns/tests/tsigerror_unittest.cc
@@ -0,0 +1,102 @@
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <string>
+#include <ostream>
+
+#include <gtest/gtest.h>
+
+#include <exceptions/exceptions.h>
+
+#include <dns/rcode.h>
+#include <dns/tsigerror.h>
+
+using namespace std;
+using namespace isc;
+using namespace isc::dns;
+
+namespace {
+TEST(TSIGErrorTest, constructFromErrorCode) {
+    // These are pretty trivial, and also test getCode();
+    EXPECT_EQ(0, TSIGError(0).getCode());
+    EXPECT_EQ(18, TSIGError(18).getCode());
+    EXPECT_EQ(65535, TSIGError(65535).getCode());
+}
+
+TEST(TSIGErrorTest, constructFromRcode) {
+    // We use RCODE for code values from 0-15.
+    EXPECT_EQ(0, TSIGError(Rcode::NOERROR()).getCode());
+    EXPECT_EQ(15, TSIGError(Rcode(15)).getCode());
+
+    // From error code 16 TSIG errors define a separate space, so passing
+    // corresponding RCODE for such code values should be prohibited.
+    EXPECT_THROW(TSIGError(Rcode(16)).getCode(), OutOfRange);
+}
+
+TEST(TSIGErrorTest, constants) {
+    // We'll only test arbitrarily chosen subsets of the codes.
+    // This class is quite simple, so it should be suffice.
+
+    EXPECT_EQ(TSIGError::BAD_SIG_CODE, TSIGError(16).getCode());
+    EXPECT_EQ(TSIGError::BAD_KEY_CODE, TSIGError(17).getCode());
+    EXPECT_EQ(TSIGError::BAD_TIME_CODE, TSIGError(18).getCode());
+
+    EXPECT_EQ(0, TSIGError::NOERROR().getCode());
+    EXPECT_EQ(9, TSIGError::NOTAUTH().getCode());
+    EXPECT_EQ(14, TSIGError::RESERVED14().getCode());
+    EXPECT_EQ(TSIGError::BAD_SIG_CODE, TSIGError::BAD_SIG().getCode());
+    EXPECT_EQ(TSIGError::BAD_KEY_CODE, TSIGError::BAD_KEY().getCode());
+    EXPECT_EQ(TSIGError::BAD_TIME_CODE, TSIGError::BAD_TIME().getCode());
+}
+
+TEST(TSIGErrorTest, equal) {
+    EXPECT_TRUE(TSIGError::NOERROR() == TSIGError(Rcode::NOERROR()));
+    EXPECT_TRUE(TSIGError(Rcode::NOERROR()) == TSIGError::NOERROR());
+    EXPECT_TRUE(TSIGError::NOERROR().equals(TSIGError(Rcode::NOERROR())));
+    EXPECT_TRUE(TSIGError::NOERROR().equals(TSIGError(Rcode::NOERROR())));
+
+    EXPECT_TRUE(TSIGError::BAD_SIG() == TSIGError(16));
+    EXPECT_TRUE(TSIGError(16) == TSIGError::BAD_SIG());
+    EXPECT_TRUE(TSIGError::BAD_SIG().equals(TSIGError(16)));
+    EXPECT_TRUE(TSIGError(16).equals(TSIGError::BAD_SIG()));
+}
+
+TEST(TSIGErrorTest, nequal) {
+    EXPECT_TRUE(TSIGError::BAD_KEY() != TSIGError(Rcode::NOERROR()));
+    EXPECT_TRUE(TSIGError(Rcode::NOERROR()) != TSIGError::BAD_KEY());
+    EXPECT_TRUE(TSIGError::BAD_KEY().nequals(TSIGError(Rcode::NOERROR())));
+    EXPECT_TRUE(TSIGError(Rcode::NOERROR()).nequals(TSIGError::BAD_KEY()));
+}
+
+TEST(TSIGErrorTest, toText) {
+    // TSIGError derived from the standard Rcode
+    EXPECT_EQ("NOERROR", TSIGError(Rcode::NOERROR()).toText());
+
+    // Well known TSIG errors
+    EXPECT_EQ("BADSIG", TSIGError::BAD_SIG().toText());
+    EXPECT_EQ("BADKEY", TSIGError::BAD_KEY().toText());
+    EXPECT_EQ("BADTIME", TSIGError::BAD_TIME().toText());
+
+    // Unknown (or not yet supported) codes.  Simply converted as numeric.
+    EXPECT_EQ("19", TSIGError(19).toText());
+    EXPECT_EQ("65535", TSIGError(65535).toText());
+}
+
+// test operator<<.  We simply confirm it appends the result of toText().
+TEST(TSIGErrorTest, LeftShiftOperator) {
+    ostringstream oss;
+    oss << TSIGError::BAD_KEY();
+    EXPECT_EQ(TSIGError::BAD_KEY().toText(), oss.str());
+}
+} // end namespace
diff --git a/src/lib/dns/tests/tsigkey_unittest.cc b/src/lib/dns/tests/tsigkey_unittest.cc
index 6b2b8c5..96696d5 100644
--- a/src/lib/dns/tests/tsigkey_unittest.cc
+++ b/src/lib/dns/tests/tsigkey_unittest.cc
@@ -18,6 +18,8 @@
 
 #include <exceptions/exceptions.h>
 
+#include <cryptolink/cryptolink.h>
+
 #include <dns/tsigkey.h>
 
 #include <dns/tests/unittest_util.h>
@@ -38,6 +40,15 @@ TEST_F(TSIGKeyTest, algorithmNames) {
     EXPECT_EQ(Name("hmac-md5.sig-alg.reg.int"), TSIGKey::HMACMD5_NAME());
     EXPECT_EQ(Name("hmac-sha1"), TSIGKey::HMACSHA1_NAME());
     EXPECT_EQ(Name("hmac-sha256"), TSIGKey::HMACSHA256_NAME());
+
+    // Also check conversion to cryptolink definitions
+    EXPECT_EQ(isc::cryptolink::MD5, TSIGKey(key_name, TSIGKey::HMACMD5_NAME(),
+                                            NULL, 0).getAlgorithm());
+    EXPECT_EQ(isc::cryptolink::SHA1, TSIGKey(key_name, TSIGKey::HMACSHA1_NAME(),
+                                             NULL, 0).getAlgorithm());
+    EXPECT_EQ(isc::cryptolink::SHA256, TSIGKey(key_name,
+                                               TSIGKey::HMACSHA256_NAME(),
+                                               NULL, 0).getAlgorithm());
 }
 
 TEST_F(TSIGKeyTest, construct) {
@@ -58,6 +69,11 @@ TEST_F(TSIGKeyTest, construct) {
                       secret.c_str(),
                       secret.size()).getAlgorithmName().toText());
 
+    EXPECT_EQ("example.com.",
+              TSIGKey(Name("EXAMPLE.CoM."), TSIGKey::HMACSHA256_NAME(),
+                      secret.c_str(),
+                      secret.size()).getKeyName().toText());
+
     // Invalid combinations of secret and secret_len:
     EXPECT_THROW(TSIGKey(key_name, TSIGKey::HMACSHA1_NAME(), secret.c_str(), 0),
                  isc::InvalidParameter);
@@ -227,4 +243,31 @@ TEST_F(TSIGKeyRingTest, findFromSome) {
               keyring.find(Name("noexist.example")).key);
 }
 
+TEST(TSIGStringTest, TSIGKeyFromToString) {
+    TSIGKey k1 = TSIGKey("test.example:MSG6Ng==:hmac-md5.sig-alg.reg.int");
+    TSIGKey k2 = TSIGKey("test.example.:MSG6Ng==:hmac-md5.sig-alg.reg.int.");
+    TSIGKey k3 = TSIGKey("test.example:MSG6Ng==");
+    TSIGKey k4 = TSIGKey(Name("test.example."), Name("hmac-sha1."), NULL, 0);
+
+    EXPECT_EQ("test.example.:MSG6Ng==:hmac-md5.sig-alg.reg.int.",
+              k1.toText());
+    EXPECT_EQ("test.example.:MSG6Ng==:hmac-md5.sig-alg.reg.int.",
+              k2.toText());
+    EXPECT_EQ("test.example.:MSG6Ng==:hmac-md5.sig-alg.reg.int.",
+              k3.toText());
+    EXPECT_EQ("test.example.::hmac-sha1.", k4.toText());
+
+    EXPECT_THROW(TSIGKey(""), isc::InvalidParameter);
+    EXPECT_THROW(TSIGKey(":"), isc::InvalidParameter);
+    EXPECT_THROW(TSIGKey("::"), isc::InvalidParameter);
+    EXPECT_THROW(TSIGKey("..:aa:"), isc::InvalidParameter);
+    EXPECT_THROW(TSIGKey("test.example:xxxx:"), isc::InvalidParameter);
+    EXPECT_THROW(TSIGKey("test.example.::"), isc::InvalidParameter);
+    EXPECT_THROW(TSIGKey("test.example.:"), isc::InvalidParameter);
+    EXPECT_THROW(TSIGKey("test.example.:MSG6Ng==:"), isc::InvalidParameter);
+    EXPECT_THROW(TSIGKey("test.example.:MSG6Ng==:unknown"), isc::InvalidParameter);
+
+}
+
+
 } // end namespace
diff --git a/src/lib/dns/tests/tsigrecord_unittest.cc b/src/lib/dns/tests/tsigrecord_unittest.cc
new file mode 100644
index 0000000..a932b7f
--- /dev/null
+++ b/src/lib/dns/tests/tsigrecord_unittest.cc
@@ -0,0 +1,160 @@
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <vector>
+#include <sstream>
+
+#include <gtest/gtest.h>
+
+#include <util/buffer.h>
+
+#include <dns/exceptions.h>
+#include <dns/messagerenderer.h>
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/tsig.h>
+#include <dns/tsigkey.h>
+#include <dns/tsigrecord.h>
+
+#include <dns/tests/unittest_util.h>
+
+using namespace std;
+using namespace isc::util;
+using namespace isc::dns;
+using namespace isc::dns::rdata;
+using isc::UnitTestUtil;
+
+namespace {
+class TSIGRecordTest : public ::testing::Test {
+protected:
+    TSIGRecordTest() :
+        test_name("www.example.com"), test_mac(16, 0xda),
+        test_rdata(any::TSIG(TSIGKey::HMACMD5_NAME(), 0x4da8877a,
+                             TSIGContext::DEFAULT_FUDGE,
+                             test_mac.size(), &test_mac[0],
+                             0x2d65, 0, 0, NULL)),
+        test_record(test_name, test_rdata),
+        buffer(0), renderer(buffer)
+    {}
+    const Name test_name;
+    vector<unsigned char> test_mac;
+    const any::TSIG test_rdata;
+    const TSIGRecord test_record;
+    OutputBuffer buffer;
+    MessageRenderer renderer;
+    vector<unsigned char> data;
+};
+
+TEST_F(TSIGRecordTest, getName) {
+    EXPECT_EQ(test_name, test_record.getName());
+}
+
+TEST_F(TSIGRecordTest, getLength) {
+    // 85 = 17 + 26 + 16 + 26
+    // len(www.example.com) = 17
+    // len(hmac-md5.sig-alg.reg.int) = 26
+    // len(MAC) = 16
+    // the rest are fixed length fields (26 in total)
+    EXPECT_EQ(85, test_record.getLength());
+}
+
+TEST_F(TSIGRecordTest, fromParams) {
+    // Construct the same TSIG RR as test_record from parameters.
+    // See the getLength test for the magic number of 85 (although it
+    // actually doesn't matter)
+    const TSIGRecord record(test_name, TSIGRecord::getClass(),
+                            TSIGRecord::getTTL(), test_rdata, 85);
+    // Perform straight sanity checks
+    EXPECT_EQ(test_name, record.getName());
+    EXPECT_EQ(85, record.getLength());
+    EXPECT_EQ(0, test_rdata.compare(record.getRdata()));
+
+    // The constructor doesn't check the length...
+    EXPECT_NO_THROW(TSIGRecord(test_name, TSIGRecord::getClass(),
+                               TSIGRecord::getTTL(), test_rdata, 82));
+    // ...even for impossibly small values...
+    EXPECT_NO_THROW(TSIGRecord(test_name, TSIGRecord::getClass(),
+                               TSIGRecord::getTTL(), test_rdata, 1));
+    // ...or too large values.
+    EXPECT_NO_THROW(TSIGRecord(test_name, TSIGRecord::getClass(),
+                               TSIGRecord::getTTL(), test_rdata, 65536));
+
+    // RDATA must indeed be TSIG
+    EXPECT_THROW(TSIGRecord(test_name, TSIGRecord::getClass(),
+                            TSIGRecord::getTTL(), in::A("192.0.2.1"), 85),
+                 DNSMessageFORMERR);
+
+    // Unexpected class
+    EXPECT_THROW(TSIGRecord(test_name, RRClass::IN(), TSIGRecord::getTTL(),
+                            test_rdata, 85),
+                 DNSMessageFORMERR);
+
+    // Unexpected TTL (simply ignored)
+    EXPECT_NO_THROW(TSIGRecord(test_name, TSIGRecord::getClass(),
+                               RRTTL(3600), test_rdata, 85));
+}
+
+TEST_F(TSIGRecordTest, recordToWire) {
+    UnitTestUtil::readWireData("tsigrecord_toWire1.wire", data);
+    EXPECT_EQ(1, test_record.toWire(renderer));
+    EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
+                        renderer.getData(), renderer.getLength(),
+                        &data[0], data.size());
+
+    // Same test for a dumb buffer
+    buffer.clear();
+    EXPECT_EQ(1, test_record.toWire(buffer));
+    EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
+                        buffer.getData(), buffer.getLength(),
+                        &data[0], data.size());
+}
+
+TEST_F(TSIGRecordTest, recordToOLongToWire) {
+    // By setting the limit to "record length - 1", it will fail, and the
+    // renderer will be marked as "truncated".
+    renderer.setLengthLimit(test_record.getLength() - 1);
+    EXPECT_FALSE(renderer.isTruncated()); // not marked before render attempt
+    EXPECT_EQ(0, test_record.toWire(renderer));
+    EXPECT_TRUE(renderer.isTruncated());
+}
+
+TEST_F(TSIGRecordTest, recordToWireAfterNames) {
+    // A similar test but the TSIG RR follows some domain names that could
+    // cause name compression inside TSIG.  Our implementation shouldn't
+    // compress either owner (key) name or the algorithm name.  This test
+    // confirms that.
+
+    UnitTestUtil::readWireData("tsigrecord_toWire2.wire", data);
+    renderer.writeName(TSIGKey::HMACMD5_NAME());
+    renderer.writeName(Name("foo.example.com"));
+    EXPECT_EQ(1, test_record.toWire(renderer));
+    EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
+                        renderer.getData(), renderer.getLength(),
+                        &data[0], data.size());
+}
+
+TEST_F(TSIGRecordTest, toText) {
+    EXPECT_EQ("www.example.com. 0 ANY TSIG hmac-md5.sig-alg.reg.int. "
+              "1302890362 300 16 2tra2tra2tra2tra2tra2g== 11621 NOERROR 0\n",
+              test_record.toText());
+}
+
+// test operator<<.  We simply confirm it appends the result of toText().
+TEST_F(TSIGRecordTest, LeftShiftOperator) {
+    ostringstream oss;
+    oss << test_record;
+    EXPECT_EQ(test_record.toText(), oss.str());
+}
+} // end namespace
diff --git a/src/lib/dns/tsig.cc b/src/lib/dns/tsig.cc
new file mode 100644
index 0000000..8e8301d
--- /dev/null
+++ b/src/lib/dns/tsig.cc
@@ -0,0 +1,207 @@
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <sys/time.h>
+
+#include <stdint.h>
+
+#include <cassert>              // for the tentative verifyTentative()
+#include <vector>
+
+#include <boost/shared_ptr.hpp>
+
+#include <exceptions/exceptions.h>
+
+#include <util/buffer.h>
+#include <util/time_utilities.h>
+
+#include <dns/rdataclass.h>
+#include <dns/rrclass.h>
+#include <dns/tsig.h>
+#include <dns/tsigerror.h>
+#include <dns/tsigkey.h>
+
+#include <cryptolink/cryptolink.h>
+#include <cryptolink/crypto_hmac.h>
+
+using namespace std;
+using namespace isc::util;
+using namespace isc::cryptolink;
+using namespace isc::dns::rdata;
+
+namespace isc {
+namespace dns {
+namespace {
+typedef boost::shared_ptr<HMAC> HMACPtr;
+}
+
+struct TSIGContext::TSIGContextImpl {
+    TSIGContextImpl(const TSIGKey& key) :
+        state_(INIT), key_(key), error_(Rcode::NOERROR()),
+        previous_timesigned_(0)
+    {}
+    State state_;
+    TSIGKey key_;
+    vector<uint8_t> previous_digest_;
+    TSIGError error_;
+    uint64_t previous_timesigned_; // only meaningful for response with BADTIME
+};
+
+TSIGContext::TSIGContext(const TSIGKey& key) : impl_(new TSIGContextImpl(key))
+{
+}
+
+TSIGContext::~TSIGContext() {
+    delete impl_;
+}
+
+TSIGContext::State
+TSIGContext::getState() const {
+    return (impl_->state_);
+}
+
+TSIGError
+TSIGContext::getError() const {
+    return (impl_->error_);
+}
+
+ConstTSIGRecordPtr
+TSIGContext::sign(const uint16_t qid, const void* const data,
+                  const size_t data_len)
+{
+    if (data == NULL || data_len == 0) {
+        isc_throw(InvalidParameter, "TSIG sign error: empty data is given");
+    }
+
+    TSIGError error(TSIGError::NOERROR());
+    // TSIG uses 48-bit unsigned integer to represent time signed.
+    // Since gettimeofdayWrapper() returns a 64-bit *signed* integer, we
+    // make sure it's stored in an unsigned 64-bit integer variable and
+    // represents a value in the expected range.  (In reality, however,
+    // gettimeofdayWrapper() will return a positive integer that will fit
+    // in 48 bits)
+    const uint64_t now = (detail::gettimeWrapper() & 0x0000ffffffffffffULL);
+
+    // For responses adjust the error code.
+    if (impl_->state_ == CHECKED) {
+        error = impl_->error_;
+    }
+
+    // For errors related to key or MAC, return an unsigned response as
+    // specified in Section 4.3 of RFC2845.
+    if (error == TSIGError::BAD_SIG() || error == TSIGError::BAD_KEY()) {
+        ConstTSIGRecordPtr tsig(new TSIGRecord(
+                                    impl_->key_.getKeyName(),
+                                    any::TSIG(impl_->key_.getAlgorithmName(),
+                                              now, DEFAULT_FUDGE, 0, NULL,
+                                              qid, error.getCode(), 0, NULL)));
+        impl_->previous_digest_.clear();
+        impl_->state_ = SIGNED;
+        return (tsig);
+    }
+
+    OutputBuffer variables(0);
+    HMACPtr hmac(CryptoLink::getCryptoLink().createHMAC(
+                     impl_->key_.getSecret(),
+                     impl_->key_.getSecretLength(),
+                     impl_->key_.getAlgorithm()),
+                 deleteHMAC);
+
+    // If the context has previous MAC (either the Request MAC or its own
+    // previous MAC), digest it.
+    if (impl_->state_ != INIT) {
+        const uint16_t previous_digest_len(impl_->previous_digest_.size());
+        variables.writeUint16(previous_digest_len);
+        if (previous_digest_len != 0) {
+            variables.writeData(&impl_->previous_digest_[0],
+                                previous_digest_len);
+        }
+        hmac->update(variables.getData(), variables.getLength());
+    }
+
+    // Digest the message (without TSIG)
+    hmac->update(data, data_len);
+
+    //
+    // Digest TSIG variables.  If state_ is SIGNED we skip digesting them
+    // except for time related variables (RFC2845 4.4).
+    //
+    variables.clear();
+    if (impl_->state_ != SIGNED) {
+        impl_->key_.getKeyName().toWire(variables);
+        TSIGRecord::getClass().toWire(variables);
+        variables.writeUint32(TSIGRecord::TSIG_TTL);
+        impl_->key_.getAlgorithmName().toWire(variables);
+    }
+    const uint64_t time_signed = (error == TSIGError::BAD_TIME()) ?
+        impl_->previous_timesigned_ : now;
+    variables.writeUint16(time_signed >> 32);
+    variables.writeUint32(time_signed & 0xffffffff);
+    variables.writeUint16(DEFAULT_FUDGE);
+    hmac->update(variables.getData(), variables.getLength());
+    variables.clear();
+
+    if (impl_->state_ != SIGNED) {
+        variables.writeUint16(error.getCode());
+
+        // For BADTIME error, digest 6 bytes of other data.
+        // (6 bytes = size of time signed value)
+        variables.writeUint16((error == TSIGError::BAD_TIME()) ? 6 : 0);
+        hmac->update(variables.getData(), variables.getLength());
+
+        variables.clear();
+        if (error == TSIGError::BAD_TIME()) {
+            variables.writeUint16(now >> 32);
+            variables.writeUint32(now & 0xffffffff);
+            hmac->update(variables.getData(), variables.getLength());
+        }
+    }
+    const uint16_t otherlen = variables.getLength();
+
+    // Get the final digest, update internal state, then finish.
+    vector<uint8_t> digest = hmac->sign();
+    ConstTSIGRecordPtr tsig(new TSIGRecord(
+                                impl_->key_.getKeyName(),
+                                any::TSIG(impl_->key_.getAlgorithmName(),
+                                          time_signed, DEFAULT_FUDGE,
+                                          digest.size(), &digest[0],
+                                          qid, error.getCode(), otherlen,
+                                          otherlen == 0 ?
+                                          NULL : variables.getData())));
+    // Exception free from now on.
+    impl_->previous_digest_.swap(digest);
+    impl_->state_ = SIGNED;
+    return (tsig);
+}
+
+void
+TSIGContext::verifyTentative(ConstTSIGRecordPtr tsig, TSIGError error) {
+    const any::TSIG tsig_rdata = tsig->getRdata();
+
+    impl_->error_ = error;
+    if (error == TSIGError::BAD_TIME()) {
+        impl_->previous_timesigned_ = tsig_rdata.getTimeSigned();
+    }
+
+    // For simplicity we assume non empty digests.
+    assert(tsig_rdata.getMACSize() != 0);
+    impl_->previous_digest_.assign(
+        static_cast<const uint8_t*>(tsig_rdata.getMAC()),
+        static_cast<const uint8_t*>(tsig_rdata.getMAC()) +
+        tsig_rdata.getMACSize());
+
+    impl_->state_ = CHECKED;
+}
+} // namespace dns
+} // namespace isc
diff --git a/src/lib/dns/tsig.h b/src/lib/dns/tsig.h
new file mode 100644
index 0000000..fbcb1bb
--- /dev/null
+++ b/src/lib/dns/tsig.h
@@ -0,0 +1,232 @@
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#ifndef __TSIG_H
+#define __TSIG_H 1
+
+#include <boost/noncopyable.hpp>
+
+#include <dns/tsigerror.h>
+#include <dns/tsigkey.h>
+#include <dns/tsigrecord.h>
+
+namespace isc {
+namespace dns {
+/// TSIG session context.
+///
+/// The \c TSIGContext class maintains a context of a signed session of
+/// DNS transactions by TSIG.  In many cases a TSIG signed session consists
+/// of a single set of request (e.g. normal query) and reply (e.g. normal
+/// response), where the request is initially signed by the client, and the
+/// reply is signed by the server using the initial signature.  As mentioned
+/// in RFC2845, a session can consist of multiple exchanges in a TCP
+/// connection.  As also mentioned in the RFC, an AXFR response often contains
+/// multiple DNS messages, which can belong to the same TSIG session.
+/// This class supports all these cases.
+///
+/// A \c TSIGContext object is generally constructed with a TSIG key to be
+/// used for the session, and keeps track of various kinds of session specific
+/// information, such as the original digest while waiting for a response or
+/// verification error information that is to be used for a subsequent
+/// response.
+///
+/// This class has two main methods, \c sign() and \c verify().
+/// The \c sign() method signs given data (which is supposed to be a complete
+/// DNS message without the TSIG itself) using the TSIG key and other
+/// related information associated with the \c TSIGContext object.
+/// The \c verify() method verifies a given DNS message that contains a TSIG
+/// RR using the key and other internal information.
+///
+/// In general, a DNS client that wants to send a signed query will construct
+/// a \c TSIGContext object with the TSIG key that the client is intending to
+/// use, and sign the query with the context.  The client will keeps the
+/// context, and verify the response with it.
+///
+/// On the other hand, a DNS server will construct a \c TSIGContext object
+/// with the information of the TSIG RR included in a query with a set of
+/// possible keys (in the form of a \c TSIGKeyRing object).  The constructor
+/// in this mode will identify the appropriate TSIG key (or internally record
+/// an error if it doesn't find a key).  The server will then verify the
+/// query with the context, and generate a signed response using the same
+/// same context.  (Note: this mode is not yet implemented and may change,
+/// see below).
+///
+/// When multiple messages belong to the same TSIG session, either side
+/// (signer or verifier) will keep using the same context.  It records
+/// the latest session state (such as the previous digest) so that repeated
+/// calls to \c sign() or \c verify() work correctly in terms of the TSIG
+/// protocol.
+///
+/// \note The \c verify() method is not yet implemented.  The implementation
+/// and documentation should be updated in the corresponding task.
+///
+/// <b>TCP Consideration</b>
+///
+/// RFC2845 describes the case where a single TSIG session is used for
+/// multiple DNS messages (Section 4.4).  This class supports signing and
+/// verifying the messages in this scenario, but does not care if the messages
+/// were delivered over a TCP connection or not.  If, for example, the
+/// same \c TSIGContext object is used to sign two independent DNS queries
+/// sent over UDP, they will be considered to belong to the same TSIG
+/// session, and, as a result, verification will be likely to fail.
+///
+/// \b Copyability
+///
+/// This class is currently non copyable based on the observation of the
+/// typical usage as described above.  But there is no strong technical
+/// reason why this class cannot be copyable.  If we see the need for it
+/// in future we may change the implementation on this point.
+///
+/// <b>Note to developers:</b>
+/// One basic design choice is to make the \c TSIGContext class is as
+/// independent from the \c Message class.  This is because the latter is
+/// much more complicated, depending on many other classes, while TSIG is
+/// a very specific part of the entire DNS protocol set.  If the \c TSIGContext
+/// class depends on \c \c Message, it will be more vulnerable to changes
+/// to other classes, and will be more difficult to test due to the
+/// direct or indirect dependencies.  The interface of \c sign() that takes
+/// opaque data (instead of, e.g., a \c Message or \c MessageRenderer object)
+/// is therefore a deliberate design decision.
+class TSIGContext : boost::noncopyable {
+public:
+    /// Internal state of context
+    ///
+    /// The constants of this enum type define a specific state of
+    /// \c TSIGContext to adjust the behavior.  The definition is public
+    /// and the state can be seen via the \c getState() method, but this is
+    /// mostly private information.  It's publicly visible mainly for testing
+    /// purposes; there is no API for the application to change the state
+    /// directly.
+    enum State {
+        INIT,                   ///< Initial state
+        SIGNED,                 ///< Sign completed
+        CHECKED ///< Verification completed (may or may not successfully)
+    };
+
+    /// \name Constructors and destructor
+    ///
+    //@{
+    /// Constructor from a TSIG key.
+    ///
+    /// \exception std::bad_alloc Resource allocation for internal data fails
+    ///
+    /// \param key The TSIG key to be used for TSIG sessions with this context.
+    explicit TSIGContext(const TSIGKey& key);
+
+    /// The destructor.
+    ~TSIGContext();
+    //@}
+
+    /// Sign a DNS message.
+    ///
+    /// This method computes the TSIG MAC for the given data, which is
+    /// generally expected to be a complete, wire-format DNS message
+    /// that doesn't contain a TSIG RR, based on the TSIG key and
+    /// other context information of \c TSIGContext, and returns a
+    /// result in the form of a (pointer object pointing to)
+    /// \c TSIGRecord object.
+    ///
+    /// The caller of this method will use the returned value to render a
+    /// complete TSIG RR into the message that has been signed so that it
+    /// will become a complete TSIG-signed message.
+    ///
+    /// \note Normal applications are not expected to call this method
+    /// directly; they will usually use the \c Message::toWire() method
+    /// with a \c TSIGContext object being a parameter and have the
+    /// \c Message class create a complete signed message.
+    ///
+    /// This method treats the given data as opaque, even though it's generally
+    /// expected to represent a wire-format DNS message (see also the class
+    /// description), and doesn't inspect it in any way.  For example, it
+    /// doesn't check whether the data length is sane for a valid DNS message.
+    /// This is also the reason why this method takes the \c qid parameter,
+    /// which will be used as the original ID of the resulting
+    /// \c TSIGRecordx object, even though this value should be stored in the
+    /// first two octets (in wire format) of the given data.
+    ///
+    /// \note This method still checks and rejects empty data (\c NULL pointer
+    /// data or the specified data length is 0) in order to avoid catastrophic
+    /// effect such as program crash.  Empty data is not necessarily invalid
+    /// for HMAC computation, but obviously it doesn't make sense for a DNS
+    /// message.
+    ///
+    /// This method provides the strong exception guarantee; unless the method
+    /// returns (without an exception being thrown), the internal state of
+    /// the \c TSIGContext won't be modified.
+    ///
+    /// \exception InvalidParameter \c data is NULL or \c data_len is 0
+    /// \exception cryptolink::LibraryError Some unexpected error in the
+    /// underlying crypto operation
+    /// \exception std::bad_alloc Temporary resource allocation failure
+    ///
+    /// \param qid The QID to be as the value of the original ID field of
+    /// the resulting TSIG record
+    /// \param data Points to the wire-format data to be signed
+    /// \param data_len The length of \c data in bytes
+    ///
+    /// \return A TSIG record for the given data along with the context.
+    ConstTSIGRecordPtr sign(const uint16_t qid, const void* const data,
+                            const size_t data_len);
+
+    /// Return the current state of the context
+    ///
+    /// \note
+    /// The states are visible in public mainly for testing purposes.
+    /// Normal applications won't have to deal with them.
+    ///
+    /// \exception None
+    State getState() const;
+
+    /// Return the TSIG error as a result of the latest verification
+    ///
+    /// This method can be called even before verifying anything, but the
+    /// returned value is meaningless in that case.
+    ///
+    /// \exception None
+    TSIGError getError() const;
+
+    // This method is tentatively added for testing until a complete
+    // verify() method is implemented.  Once it's done this should be
+    // removed, and corresponding tests should be updated.
+    //
+    // This tentative "verify" method changes the internal state of
+    // the TSIGContext to the CHECKED as if it were verified (though possibly
+    // unsuccessfully) with given tsig_rdata.  If the error parameter is
+    // given and not NOERROR, it's recorded inside the context so that the
+    // subsequent sign() will behave accordingly.
+    void verifyTentative(ConstTSIGRecordPtr tsig,
+                         TSIGError error = TSIGError::NOERROR());
+
+    /// \name Protocol constants and defaults
+    ///
+    //@{
+    /// The recommended fudge value (in seconds) by RFC2845.
+    ///
+    /// Right now fudge is not tunable, and all TSIGs generated by this API
+    /// will have this value of fudge.
+    static const uint16_t DEFAULT_FUDGE = 300;
+    //@}
+
+private:
+    struct TSIGContextImpl;
+    TSIGContextImpl* impl_;
+};
+}
+}
+
+#endif  // __TSIG_H
+
+// Local Variables:
+// mode: c++
+// End:
diff --git a/src/lib/dns/tsigerror.cc b/src/lib/dns/tsigerror.cc
new file mode 100644
index 0000000..e63c9ab
--- /dev/null
+++ b/src/lib/dns/tsigerror.cc
@@ -0,0 +1,57 @@
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <ostream>
+#include <string>
+
+#include <boost/lexical_cast.hpp>
+
+#include <exceptions/exceptions.h>
+
+#include <dns/rcode.h>
+#include <dns/tsigerror.h>
+
+namespace isc {
+namespace dns {
+namespace {
+const char* const tsigerror_text[] = {
+    "BADSIG",
+    "BADKEY",
+    "BADTIME"
+};
+}
+
+TSIGError::TSIGError(Rcode rcode) : code_(rcode.getCode()) {
+    if (code_ > MAX_RCODE_FOR_TSIGERROR) {
+        isc_throw(OutOfRange, "Invalid RCODE for TSIG Error: " << rcode);
+    }
+}
+
+std::string
+TSIGError::toText() const {
+    if (code_ <= MAX_RCODE_FOR_TSIGERROR) {
+        return (Rcode(code_).toText());
+    } else if (code_ <= BAD_TIME_CODE) {
+        return (tsigerror_text[code_ - (MAX_RCODE_FOR_TSIGERROR + 1)]);
+    } else {
+        return (boost::lexical_cast<std::string>(code_));
+    }
+}
+
+std::ostream&
+operator<<(std::ostream& os, const TSIGError& error) {
+    return (os << error.toText());
+}
+} // namespace dns
+} // namespace isc
diff --git a/src/lib/dns/tsigerror.h b/src/lib/dns/tsigerror.h
new file mode 100644
index 0000000..4463daf
--- /dev/null
+++ b/src/lib/dns/tsigerror.h
@@ -0,0 +1,328 @@
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#ifndef __TSIGERROR_H
+#define __TSIGERROR_H 1
+
+#include <ostream>
+#include <string>
+
+#include <dns/rcode.h>
+
+namespace isc {
+namespace dns {
+
+class RRClass;
+
+/// TSIG errors
+///
+/// The \c TSIGError class objects represent standard errors related to
+/// TSIG protocol operations as defined in related specifications, mainly
+/// in RFC2845.
+///
+/// (RCODEs) of the header section of DNS messages, and extended response
+/// codes as defined in the EDNS specification.
+class TSIGError {
+public:
+    /// Constants for pre-defined TSIG error values.
+    ///
+    /// Code values from 0 through 15 (inclusive) are derived from those of
+    /// RCODE and are not defined here.  See the \c Rcode class.
+    ///
+    /// \note Unfortunately some systems define "BADSIG" as a macro in a public
+    /// header file.  To avoid conflict with it we add an underscore to our
+    /// definitions.
+    enum CodeValue {
+        BAD_SIG_CODE = 16, ///< 16: TSIG verification failure
+        BAD_KEY_CODE = 17, ///< 17: TSIG key is not recognized
+        BAD_TIME_CODE = 18 ///< 18: Current time and time signed are too different
+    };
+
+    /// \name Constructors
+    ///
+    /// We use the default versions of destructor, copy constructor,
+    /// and assignment operator.
+    //@{
+    /// Constructor from the code value.
+    ///
+    /// \exception None
+    ///
+    /// \param code The underlying 16-bit error code value of the \c TSIGError.
+    explicit TSIGError(uint16_t error_code) : code_(error_code) {}
+
+    /// Constructor from \c Rcode.
+    ///
+    /// As defined in RFC2845, error code values from 0 to 15 (inclusive) are
+    /// derived from the DNS RCODEs, which are represented via the \c Rcode
+    /// class in this library.  This constructor works as a converter from
+    /// these RCODEs to corresponding TSIGError objects.
+    ///
+    /// \exception isc::OutOfRange Given rcode is not convertible to
+    /// TSIGErrors.
+    ///
+    /// \param rcode the \c Rcode from which the TSIGError should be derived.
+    explicit TSIGError(Rcode rcode);
+    //@}
+
+    /// \brief Returns the \c TSIGCode error code value.
+    ///
+    /// \exception None
+    ///
+    /// \return The underlying code value corresponding to the \c TSIGError.
+    uint16_t getCode() const { return (code_); }
+
+    /// \brief Return true iff two \c TSIGError objects are equal.
+    ///
+    /// Two TSIGError objects are equal iff their error codes are equal.
+    ///
+    /// \exception None
+    ///
+    /// \param other the \c TSIGError object to compare against.
+    /// \return true if the two TSIGError are equal; otherwise false.
+    bool equals(const TSIGError& other) const
+    { return (code_ == other.code_); }
+
+    /// \brief Same as \c equals().
+    bool operator==(const TSIGError& other) const { return (equals(other)); }
+
+    /// \brief Return true iff two \c TSIGError objects are not equal.
+    ///
+    /// \exception None
+    ///
+    /// \param other the \c TSIGError object to compare against.
+    /// \return true if the two TSIGError objects are not equal;
+    /// otherwise false.
+    bool nequals(const TSIGError& other) const
+    { return (code_ != other.code_); }
+
+    /// \brief Same as \c nequals().
+    bool operator!=(const TSIGError& other) const { return (nequals(other)); }
+
+    /// \brief Convert the \c TSIGError to a string.
+    ///
+    /// For codes derived from RCODEs up to 15, this method returns the
+    /// same string as \c Rcode::toText() for the corresponding code.
+    /// For other pre-defined code values (see TSIGError::CodeValue),
+    /// this method returns a string representation of the "mnemonic' used
+    /// for the enum and constant objects as defined in RFC2845.
+    /// For example, the string for code value 16 is "BADSIG", etc.
+    /// For other code values it returns a string representation of the decimal
+    /// number of the value, e.g. "32", "100", etc.
+    ///
+    /// \exception std::bad_alloc Resource allocation for the string fails
+    ///
+    /// \return A string representation of the \c TSIGError.
+    std::string toText() const;
+
+    /// A constant TSIG error object derived from \c Rcode::NOERROR()
+    static const TSIGError& NOERROR();
+
+    /// A constant TSIG error object derived from \c Rcode::FORMERR()
+    static const TSIGError& FORMERR();
+
+    /// A constant TSIG error object derived from \c Rcode::SERVFAIL()
+    static const TSIGError& SERVFAIL();
+
+    /// A constant TSIG error object derived from \c Rcode::NXDOMAIN()
+    static const TSIGError& NXDOMAIN();
+
+    /// A constant TSIG error object derived from \c Rcode::NOTIMP()
+    static const TSIGError& NOTIMP();
+
+    /// A constant TSIG error object derived from \c Rcode::REFUSED()
+    static const TSIGError& REFUSED();
+
+    /// A constant TSIG error object derived from \c Rcode::YXDOMAIN()
+    static const TSIGError& YXDOMAIN();
+
+    /// A constant TSIG error object derived from \c Rcode::YXRRSET()
+    static const TSIGError& YXRRSET();
+
+    /// A constant TSIG error object derived from \c Rcode::NXRRSET()
+    static const TSIGError& NXRRSET();
+
+    /// A constant TSIG error object derived from \c Rcode::NOTAUTH()
+    static const TSIGError& NOTAUTH();
+
+    /// A constant TSIG error object derived from \c Rcode::NOTZONE()
+    static const TSIGError& NOTZONE();
+
+    /// A constant TSIG error object derived from \c Rcode::RESERVED11()
+    static const TSIGError& RESERVED11();
+
+    /// A constant TSIG error object derived from \c Rcode::RESERVED12()
+    static const TSIGError& RESERVED12();
+
+    /// A constant TSIG error object derived from \c Rcode::RESERVED13()
+    static const TSIGError& RESERVED13();
+
+    /// A constant TSIG error object derived from \c Rcode::RESERVED14()
+    static const TSIGError& RESERVED14();
+
+    /// A constant TSIG error object derived from \c Rcode::RESERVED15()
+    static const TSIGError& RESERVED15();
+
+    /// A constant TSIG error object for the BADSIG code
+    /// (see \c TSIGError::BAD_SIG_CODE).
+    static const TSIGError& BAD_SIG();
+
+    /// A constant TSIG error object for the BADKEY code
+    /// (see \c TSIGError::BAD_KEY_CODE).
+    static const TSIGError& BAD_KEY();
+
+    /// A constant TSIG error object for the BADTIME code
+    /// (see \c TSIGError::BAD_TIME_CODE).
+    static const TSIGError& BAD_TIME();
+
+private:
+    // This is internally used to specify the maximum possible RCODE value
+    // that can be convertible to TSIGErrors.
+    static const int MAX_RCODE_FOR_TSIGERROR = 15;
+
+    uint16_t code_;
+};
+
+inline const TSIGError&
+TSIGError::NOERROR() {
+    static TSIGError e(Rcode::NOERROR());
+    return (e);
+}
+
+inline const TSIGError&
+TSIGError::FORMERR() {
+    static TSIGError e(Rcode::FORMERR());
+    return (e);
+}
+
+inline const TSIGError&
+TSIGError::SERVFAIL() {
+    static TSIGError e(Rcode::SERVFAIL());
+    return (e);
+}
+
+inline const TSIGError&
+TSIGError::NXDOMAIN() {
+    static TSIGError e(Rcode::NXDOMAIN());
+    return (e);
+}
+
+inline const TSIGError&
+TSIGError::NOTIMP() {
+    static TSIGError e(Rcode::NOTIMP());
+    return (e);
+}
+
+inline const TSIGError&
+TSIGError::REFUSED() {
+    static TSIGError e(Rcode::REFUSED());
+    return (e);
+}
+
+inline const TSIGError&
+TSIGError::YXDOMAIN() {
+    static TSIGError e(Rcode::YXDOMAIN());
+    return (e);
+}
+
+inline const TSIGError&
+TSIGError::YXRRSET() {
+    static TSIGError e(Rcode::YXRRSET());
+    return (e);
+}
+
+inline const TSIGError&
+TSIGError::NXRRSET() {
+    static TSIGError e(Rcode::NXRRSET());
+    return (e);
+}
+
+inline const TSIGError&
+TSIGError::NOTAUTH() {
+    static TSIGError e(Rcode::NOTAUTH());
+    return (e);
+}
+
+inline const TSIGError&
+TSIGError::NOTZONE() {
+    static TSIGError e(Rcode::NOTZONE());
+    return (e);
+}
+
+inline const TSIGError&
+TSIGError::RESERVED11() {
+    static TSIGError e(Rcode::RESERVED11());
+    return (e);
+}
+
+inline const TSIGError&
+TSIGError::RESERVED12() {
+    static TSIGError e(Rcode::RESERVED12());
+    return (e);
+}
+
+inline const TSIGError&
+TSIGError::RESERVED13() {
+    static TSIGError e(Rcode::RESERVED13());
+    return (e);
+}
+
+inline const TSIGError&
+TSIGError::RESERVED14() {
+    static TSIGError e(Rcode::RESERVED14());
+    return (e);
+}
+
+inline const TSIGError&
+TSIGError::RESERVED15() {
+    static TSIGError e(Rcode::RESERVED15());
+    return (e);
+}
+
+inline const TSIGError&
+TSIGError::BAD_SIG() {
+    static TSIGError e(BAD_SIG_CODE);
+    return (e);
+}
+
+inline const TSIGError&
+TSIGError::BAD_KEY() {
+    static TSIGError e(BAD_KEY_CODE);
+    return (e);
+}
+
+inline const TSIGError&
+TSIGError::BAD_TIME() {
+    static TSIGError e(BAD_TIME_CODE);
+    return (e);
+}
+
+/// Insert the \c TSIGError as a string into stream.
+///
+/// This method convert \c tsig_error into a string and inserts it into the
+/// output stream \c os.
+///
+/// \param os A \c std::ostream object on which the insertion operation is
+/// performed.
+/// \param tsig_error An \c TSIGError object output by the operation.
+/// \return A reference to the same \c std::ostream object referenced by
+/// parameter \c os after the insertion operation.
+std::ostream& operator<<(std::ostream& os, const TSIGError& tsig_error);
+}
+}
+
+#endif  // __TSIGERROR_H
+
+// Local Variables:
+// mode: c++
+// End:
diff --git a/src/lib/dns/tsigkey.cc b/src/lib/dns/tsigkey.cc
index 057191d..c899423 100644
--- a/src/lib/dns/tsigkey.cc
+++ b/src/lib/dns/tsigkey.cc
@@ -15,50 +15,112 @@
 #include <map>
 #include <utility>
 #include <vector>
+#include <sstream>
 
 #include <exceptions/exceptions.h>
 
+#include <cryptolink/cryptolink.h>
+
 #include <dns/name.h>
+#include <util/encode/base64.h>
 #include <dns/tsigkey.h>
 
 using namespace std;
+using namespace isc::cryptolink;
 
 namespace isc {
 namespace dns {
+namespace {
+    HashAlgorithm
+    convertAlgorithmName(const isc::dns::Name& name) {
+        if (name == TSIGKey::HMACMD5_NAME()) {
+            return (isc::cryptolink::MD5);
+        }
+        if (name == TSIGKey::HMACSHA1_NAME()) {
+            return (isc::cryptolink::SHA1);
+        }
+        if (name == TSIGKey::HMACSHA256_NAME()) {
+            return (isc::cryptolink::SHA256);
+        }
+        isc_throw(InvalidParameter,
+                  "Unknown TSIG algorithm is specified: " << name);
+    }
+}
+
 struct
 TSIGKey::TSIGKeyImpl {
     TSIGKeyImpl(const Name& key_name, const Name& algorithm_name,
+                isc::cryptolink::HashAlgorithm algorithm,
                 const void* secret, size_t secret_len) :
         key_name_(key_name), algorithm_name_(algorithm_name),
+        algorithm_(algorithm),
         secret_(static_cast<const uint8_t*>(secret),
                 static_cast<const uint8_t*>(secret) + secret_len)
     {
-        // Convert the name to the canonical form.
+        // Convert the key and algorithm names to the canonical form.
+        key_name_.downcase();
         algorithm_name_.downcase();
     }
-    const Name key_name_;
+    Name key_name_;
     Name algorithm_name_;
+    const isc::cryptolink::HashAlgorithm algorithm_;
     const vector<uint8_t> secret_;
 };
 
 TSIGKey::TSIGKey(const Name& key_name, const Name& algorithm_name,
                  const void* secret, size_t secret_len) : impl_(NULL)
 {
-    if (algorithm_name != HMACMD5_NAME() &&
-        algorithm_name != HMACSHA1_NAME() &&
-        algorithm_name != HMACSHA256_NAME()) {
-        isc_throw(InvalidParameter, "Unknown TSIG algorithm is specified: " <<
-                  algorithm_name);
-    }
+    const HashAlgorithm algorithm = convertAlgorithmName(algorithm_name);
     if ((secret != NULL && secret_len == 0) ||
         (secret == NULL && secret_len != 0)) {
         isc_throw(InvalidParameter,
                   "TSIGKey secret and its length are inconsistent");
     }
-
-    impl_ = new TSIGKeyImpl(key_name, algorithm_name, secret, secret_len);
+    impl_ = new TSIGKeyImpl(key_name, algorithm_name, algorithm, secret,
+                            secret_len);
+}
+
+TSIGKey::TSIGKey(const std::string& str) : impl_(NULL) {
+    try {
+        istringstream iss(str);
+
+        string keyname_str;
+        getline(iss, keyname_str, ':');
+        if (iss.fail() || iss.bad() || iss.eof()) {
+            isc_throw(InvalidParameter, "Invalid TSIG key string: " << str);
+        }
+
+        string secret_str;
+        getline(iss, secret_str, ':');
+        if (iss.fail() || iss.bad()) {
+            isc_throw(InvalidParameter, "Invalid TSIG key string: " << str);
+        }
+
+        string algo_str;
+        if (!iss.eof()) {
+            getline(iss, algo_str);
+        }
+        if (iss.fail() || iss.bad()) {
+            isc_throw(InvalidParameter, "Invalid TSIG key string: " << str);
+        }
+
+        const Name algo_name(algo_str.empty() ? "hmac-md5.sig-alg.reg.int" :
+                             algo_str);
+        const HashAlgorithm algorithm = convertAlgorithmName(algo_name);
+
+        vector<uint8_t> secret;
+        isc::util::encode::decodeBase64(secret_str, secret);
+
+        impl_ = new TSIGKeyImpl(Name(keyname_str), algo_name, algorithm,
+                                &secret[0], secret.size());
+    } catch (const Exception& e) {
+        // 'reduce' the several types of exceptions name parsing and
+        // Base64 decoding can throw to just the InvalidParameter
+        isc_throw(InvalidParameter, e.what());
+    }
 }
 
+
 TSIGKey::TSIGKey(const TSIGKey& source) : impl_(new TSIGKeyImpl(*source.impl_))
 {}
 
@@ -89,6 +151,11 @@ TSIGKey::getAlgorithmName() const {
     return (impl_->algorithm_name_);
 }
 
+isc::cryptolink::HashAlgorithm
+TSIGKey::getAlgorithm() const {
+    return (impl_->algorithm_);
+}
+
 const void*
 TSIGKey::getSecret() const {
     return ((impl_->secret_.size() > 0) ? &impl_->secret_[0] : NULL);
@@ -99,6 +166,17 @@ TSIGKey::getSecretLength() const {
     return (impl_->secret_.size());
 }
 
+std::string
+TSIGKey::toText() const {
+    const vector<uint8_t> secret_v(static_cast<const uint8_t*>(getSecret()),
+                                   static_cast<const uint8_t*>(getSecret()) +
+                                   getSecretLength());
+    std::string secret_str = isc::util::encode::encodeBase64(secret_v);
+
+    return (getKeyName().toText() + ":" + secret_str + ":" +
+            getAlgorithmName().toText());
+}
+
 const
 Name& TSIGKey::HMACMD5_NAME() {
     static Name alg_name("hmac-md5.sig-alg.reg.int");
diff --git a/src/lib/dns/tsigkey.h b/src/lib/dns/tsigkey.h
index e56fa88..02dd423 100644
--- a/src/lib/dns/tsigkey.h
+++ b/src/lib/dns/tsigkey.h
@@ -15,6 +15,8 @@
 #ifndef __TSIGKEY_H
 #define __TSIGKEY_H 1
 
+#include <cryptolink/cryptolink.h>
+
 namespace isc {
 namespace dns {
 
@@ -90,6 +92,25 @@ public:
     TSIGKey(const Name& key_name, const Name& algorithm_name,
             const void* secret, size_t secret_len);
 
+    /// \brief Constructor from an input string
+    ///
+    /// The string must be of the form:
+    /// <name>:<secret>[:<algorithm>]
+    /// Where <name> is a domain name for the key, <secret> is a
+    /// base64 representation of the key secret, and the optional
+    /// algorithm is an algorithm identifier as specified in RFC4635
+    /// The default algorithm is hmac-md5.sig-alg.reg.int.
+    ///
+    /// Since ':' is used as a separator here, it is not possible to
+    /// use this constructor to create keys with a ':' character in
+    /// their name.
+    ///
+    /// \exception InvalidParameter exception if the input string is
+    /// invalid.
+    ///
+    /// \param str The string to make a TSIGKey from
+    explicit TSIGKey(const std::string& str);
+
     /// \brief The copy constructor.
     ///
     /// It internally allocates a resource, and if it fails a corresponding
@@ -123,6 +144,9 @@ public:
     /// Return the algorithm name.
     const Name& getAlgorithmName() const;
 
+    /// Return the hash algorithm name in the form of cryptolink::HashAlgorithm
+    isc::cryptolink::HashAlgorithm getAlgorithm() const;
+
     /// Return the length of the TSIG secret in bytes.
     size_t getSecretLength() const;
 
@@ -139,6 +163,18 @@ public:
     const void* getSecret() const;
     //@}
 
+    /// \brief Converts the TSIGKey to a string value
+    ///
+    /// The resulting string will be of the form
+    /// name:secret:algorithm
+    /// Where <name> is a domain name for the key, <secret> is a
+    /// base64 representation of the key secret, and algorithm is
+    /// an algorithm identifier as specified in RFC4635
+    ///
+    /// \param key the TSIG key to convert
+    /// \return The string representation of the given TSIGKey.
+    std::string toText() const;
+
     ///
     /// \name Well known algorithm names as defined in RFC2845 and RFC4635.
     ///
diff --git a/src/lib/dns/tsigrecord.cc b/src/lib/dns/tsigrecord.cc
new file mode 100644
index 0000000..40ea6c2
--- /dev/null
+++ b/src/lib/dns/tsigrecord.cc
@@ -0,0 +1,145 @@
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <ostream>
+#include <string>
+
+#include <util/buffer.h>
+
+#include <dns/exceptions.h>
+#include <dns/messagerenderer.h>
+#include <dns/rrclass.h>
+#include <dns/rrttl.h>
+#include <dns/tsigrecord.h>
+
+using namespace isc::util;
+using namespace isc::dns::rdata;
+
+namespace {
+// Internally used constants:
+
+// Size in octets for the RR type, class TTL, RDLEN fields.
+const size_t RR_COMMON_LEN = 10;
+
+// Size in octets for the fixed part of TSIG RDATAs.
+// - Time Signed (6)
+// - Fudge (2)
+// - MAC Size (2)
+// - Original ID (2)
+// - Error (2)
+// - Other Len (2)
+const size_t RDATA_COMMON_LEN = 16;
+}
+
+namespace isc {
+namespace dns {
+TSIGRecord::TSIGRecord(const Name& key_name,
+                       const rdata::any::TSIG& tsig_rdata) :
+    key_name_(key_name), rdata_(tsig_rdata),
+    length_(RR_COMMON_LEN + RDATA_COMMON_LEN + key_name_.getLength() +
+            rdata_.getAlgorithm().getLength() +
+            rdata_.getMACSize() + rdata_.getOtherLen())
+{}
+
+namespace {
+// This is a straightforward wrapper of dynamic_cast<const any::TSIG&>.
+// We use this so that we can throw the DNSMessageFORMERR exception when
+// unexpected type of RDATA is detected in the member initialization list
+// of the constructor below.
+const any::TSIG&
+castToTSIGRdata(const rdata::Rdata& rdata) {
+    try {
+        return (dynamic_cast<const any::TSIG&>(rdata));
+    } catch (std::bad_cast&) {
+        isc_throw(DNSMessageFORMERR,
+                  "TSIG record is being constructed from "
+                  "incompatible RDATA:" << rdata.toText());
+    }
+}
+}
+
+TSIGRecord::TSIGRecord(const Name& name, const RRClass& rrclass,
+                       const RRTTL&, // we ignore TTL
+                       const rdata::Rdata& rdata,
+                       size_t length) :
+    key_name_(name), rdata_(castToTSIGRdata(rdata)), length_(length)
+{
+    if (rrclass != getClass()) {
+        isc_throw(DNSMessageFORMERR, "Unexpected TSIG RR class: " << rrclass);
+    }
+}
+
+const RRClass&
+TSIGRecord::getClass() {
+    return (RRClass::ANY());
+}
+
+const RRTTL&
+TSIGRecord::getTTL() {
+    static RRTTL ttl(TSIG_TTL);
+    return (ttl);
+}
+
+namespace {
+template <typename OUTPUT>
+void
+toWireCommon(OUTPUT& output, const rdata::any::TSIG& rdata) {
+    // RR type, class, TTL are fixed constants.
+    RRType::TSIG().toWire(output);
+    TSIGRecord::getClass().toWire(output);
+    output.writeUint32(TSIGRecord::TSIG_TTL);
+
+    // RDLEN
+    output.writeUint16(RDATA_COMMON_LEN + rdata.getAlgorithm().getLength() +
+                       rdata.getMACSize() + rdata.getOtherLen());
+
+    // TSIG RDATA
+    rdata.toWire(output);
+}
+}
+
+int
+TSIGRecord::toWire(AbstractMessageRenderer& renderer) const {
+    // If adding the TSIG would exceed the size limit, don't do it.
+    if (renderer.getLength() + length_ > renderer.getLengthLimit()) {
+        renderer.setTruncated();
+        return (0);
+    }
+
+    // key name = owner.  note that we disable compression.
+    renderer.writeName(key_name_, false);
+    toWireCommon(renderer, rdata_);
+    return (1);
+}
+
+int
+TSIGRecord::toWire(OutputBuffer& buffer) const {
+    key_name_.toWire(buffer);
+    toWireCommon(buffer, rdata_);
+    return (1);
+}
+
+std::string
+TSIGRecord::toText() const {
+    return (key_name_.toText() + " " + RRTTL(TSIG_TTL).toText() + " " +
+            getClass().toText() + " " + RRType::TSIG().toText() + " " +
+            rdata_.toText() + "\n");
+}
+
+std::ostream&
+operator<<(std::ostream& os, const TSIGRecord& record) {
+    return (os << record.toText());
+}
+} // namespace dns
+} // namespace isc
diff --git a/src/lib/dns/tsigrecord.h b/src/lib/dns/tsigrecord.h
new file mode 100644
index 0000000..e42edf1
--- /dev/null
+++ b/src/lib/dns/tsigrecord.h
@@ -0,0 +1,285 @@
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#ifndef __TSIGRECORD_H
+#define __TSIGRECORD_H 1
+
+#include <ostream>
+#include <string>
+
+#include <boost/shared_ptr.hpp>
+
+#include <util/buffer.h>
+
+#include <dns/name.h>
+#include <dns/rdataclass.h>
+
+namespace isc {
+namespace util {
+class OutputBuffer;
+}
+namespace dns {
+class AbstractMessageRenderer;
+
+/// TSIG resource record.
+///
+/// A \c TSIGRecord class object represents a TSIG resource record and is
+/// responsible for conversion to and from wire format TSIG record based on
+/// the protocol specification (RFC2845).
+/// This class is provided so that other classes and applications can handle
+/// TSIG without knowing protocol details of TSIG, such as that it uses a
+/// fixed constant of TTL.
+///
+/// \todo So the plan is to eventually provide  the "from wire" constructor.
+/// It's not yet provided in the current phase of development.
+///
+/// \note
+/// This class could be a derived class of \c AbstractRRset.  That way
+/// it would be able to be used in a polymorphic way; for example,
+/// an application can construct a TSIG RR by itself and insert it to a
+/// \c Message object as a generic RRset.  On the other hand, it would mean
+/// this class would have to implement an \c RdataIterator (even though it
+/// can be done via straightforward forwarding) while the iterator is mostly
+/// redundant since there should be one and only one RDATA for a valid TSIG
+/// RR.  Likewise, some methods such as \c setTTL() method wouldn't be well
+/// defined due to such special rules for TSIG as using a fixed TTL.
+/// Overall, TSIG is a very special RR type that simply uses the compatible
+/// resource record format, and it will be unlikely that a user wants to
+/// handle it through a generic interface in a polymorphic way.
+/// We therefore chose to define it as a separate class.  This is also
+/// similar to why \c EDNS is a separate class.
+class TSIGRecord {
+public:
+    ///
+    /// \name Constructors
+    ///
+    /// We use the default copy constructor, default copy assignment operator,
+    /// (and default destructor) intentionally.
+    //@{
+    /// Constructor from TSIG key name and RDATA
+    ///
+    /// \exception std::bad_alloc Resource allocation for copying the name or
+    /// RDATA fails
+    TSIGRecord(const Name& key_name, const rdata::any::TSIG& tsig_rdata);
+
+    /// Constructor from resource record (RR) parameters.
+    ///
+    /// This constructor is intended to be used in the context of parsing
+    /// an incoming DNS message that contains a TSIG.  The parser would
+    /// first extract the owner name, RR type (which is TSIG) class, TTL and
+    /// the TSIG RDATA from the message.  This constructor is expected to
+    /// be given these RR parameters (except the RR type, because it must be
+    /// TSIG).
+    ///
+    /// According to RFC2845, a TSIG RR uses fixed RR class (ANY) and TTL (0).
+    /// If the RR class is different from the expected one, this
+    /// implementation considers it an invalid record and throws an exception
+    /// of class \c DNSMessageFORMERR.  On the other hand, the TTL is simply
+    /// ignored (in that sense we could even omit that parameter, but it's
+    /// still included if and when we want to change the policy).  RFC2845
+    /// is silent about what the receiver should do if it sees an unexpected
+    /// RR class or TTL in a TSIG RR.  This implementation simply follows what
+    /// BIND 9 does (it is not clear why BIND 9 employs the "inconsistent"
+    /// policy).
+    ///
+    /// Likewise, if \c rdata is not of type \c any::TSIG, an exception of
+    /// class DNSMessageFORMERR will be thrown.  When the caller is a
+    /// DNS message parser and builds \c rdata from incoming wire format
+    /// data as described above, this case happens when the RR class is
+    /// different from ANY (in the implementation, the type check takes place
+    /// before the explicit check against the RR class explained in the
+    /// previous paragraph).
+    ///
+    /// The \c length parameter is intended to be the length of the TSIG RR
+    /// (from the beginning of the owner name to the end of the RDATA) when
+    /// the caller is a DNS message parser.  Note that it is the actual length
+    /// for the RR in the format; if the owner name or the algorithm name
+    /// (in the RDATA) is compressed (although the latter should not be
+    /// compressed according to RFC3597), the length must be the size of the
+    /// compressed data.  The length is recorded inside the class and will
+    /// be returned via subsequent calls to \c getLength().  It's intended to
+    /// be used in the context TSIG verification; in the verify process
+    /// the MAC computation must be performed for the original data without
+    /// TSIG, so, to avoid parsing the entire data in the verify process
+    /// again, it's necessary to record information that can identify the
+    /// length to be digested for the MAC.  This parameter serves for that
+    /// purpose.
+    ///
+    /// \note Since the constructor doesn't take the wire format data per se,
+    /// it doesn't (and cannot) check the validity of \c length, and simply
+    /// accepts any given value.  It even accepts obviously invalid values
+    /// such as 0.  It's caller's responsibility to provide a valid value of
+    /// length, and, the verifier's responsibility to use the length safely.
+    ///
+    /// <b>DISCUSSION:</b> this design is fragile in that it introduces
+    /// a tight coupling between message parsing and TSIG verification via
+    /// the \c TSIGRecord class.  In terms of responsibility decoupling,
+    /// the ideal way to have \c TSIGRecord remember the entire wire data
+    /// along with the length of the TSIG.  Then in the TSIG verification
+    /// we could refer to the necessary potion of data solely from a
+    /// \c TSIGRecord object.  However, this approach would require expensive
+    /// heavy copy of the original data or introduce another kind of coupling
+    /// between the data holder and this class (if the original data is freed
+    /// while a \c TSIGRecord object referencing the data still exists, the
+    /// result will be catastrophic).  As a "best current compromise", we
+    /// use the current design.  We may reconsider it if it turns out to
+    /// cause a big problem or we come up with a better idea.
+    ///
+    /// \exception DNSMessageFORMERR Given RR parameters are invalid for TSIG.
+    /// \exception std::bad_alloc Internal resource allocation fails.
+    ///
+    /// \param name The owner name of the TSIG RR
+    /// \param rrclass The RR class of the RR.  Must be \c RRClass::ANY()
+    /// (see above)
+    /// \param ttl The TTL of the RR.  Expected to be a zero TTL, but
+    /// actually ignored in this implementation.
+    /// \param rdata The RDATA of the RR.  Must be of type \c any::TSIG.
+    /// \param length The size of the RR (see above)
+    TSIGRecord(const Name& name, const RRClass& rrclass, const RRTTL& ttl,
+               const rdata::Rdata& rdata, size_t length);
+    //@}
+
+    /// Return the owner name of the TSIG RR, which is the TSIG key name
+    ///
+    /// \exception None
+    const Name& getName() const { return (key_name_); }
+
+    /// Return the RDATA of the TSIG RR
+    ///
+    /// \exception None
+    const rdata::any::TSIG& getRdata() const { return (rdata_); }
+
+    /// \name Protocol constants and defaults
+    ///
+    //@{
+    /// Return the RR class of TSIG
+    ///
+    /// TSIG always uses the ANY RR class.  This static method returns it,
+    /// when, though unlikely, an application wants to know which class TSIG
+    /// is supposed to use.
+    ///
+    /// \exception None
+    static const RRClass& getClass();
+
+    /// Return the TTL value of TSIG
+    ///
+    /// TSIG always uses 0 TTL.  This static method returns it,
+    /// when, though unlikely, an application wants to know the TTL TSIG
+    /// is supposed to use.
+    ///
+    /// \exception None
+    static const RRTTL& getTTL();
+    //@}
+
+    /// Return the length of the TSIG record
+    ///
+    /// When constructed from the key name and RDATA, it is the length of
+    /// the record when it is rendered by the \c toWire() method.
+    ///
+    /// \note When constructed "from wire", that will mean the length of
+    /// the wire format data for the TSIG RR.  The length will be necessary
+    /// to verify the message once parse is completed.
+    ///
+    /// \exception None
+    size_t getLength() const { return (length_); }
+
+    /// \brief Render the \c TSIG RR in the wire format.
+    ///
+    /// This method renders the TSIG record as a form of a DNS TSIG RR
+    /// via \c renderer, which encapsulates output buffer and other rendering
+    /// contexts.
+    ///
+    /// Normally this version of \c toWire() method tries to compress the
+    /// owner name of the RR whenever possible, but this method intentionally
+    /// skips owner name compression.  This is due to a report that some
+    /// Windows clients refuse a TSIG if its owner name is compressed
+    /// (See http://marc.info/?l=bind-workers&m=126637138430819&w=2).
+    /// Reportedly this seemed to be specific to GSS-TSIG, but this
+    /// implementation skip compression regardless of the algorithm.
+    ///
+    /// If by adding the TSIG RR the message size would exceed the limit
+    /// maintained in \c renderer, this method skips rendering the RR
+    /// and returns 0 and mark \c renderer as "truncated" (so that a
+    /// subsequent call to \c isTruncated() on \c renderer will result in
+    /// \c true); otherwise it returns 1, which is the number of RR
+    /// rendered.
+    ///
+    /// \note If the caller follows the specification of adding TSIG
+    /// as described in RFC2845, this should not happen; the caller is
+    /// generally expected to leave a sufficient room in the message for
+    /// the TSIG.  But this method checks the unexpected case nevertheless.
+    ///
+    /// \exception std::bad_alloc Internal resource allocation fails (this
+    /// should be rare).
+    ///
+    /// \param renderer DNS message rendering context that encapsulates the
+    /// output buffer and name compression information.
+    /// \return 1 if the TSIG RR fits in the message size limit; otherwise 0.
+    int toWire(AbstractMessageRenderer& renderer) const;
+
+    /// \brief Render the \c TSIG RR in the wire format.
+    ///
+    /// This method is same as \c toWire(AbstractMessageRenderer&)const
+    /// except it renders the RR in an \c OutputBuffer and therefore
+    /// does not care about message size limit.
+    /// As a consequence it always returns 1.
+    int toWire(isc::util::OutputBuffer& buffer) const;
+
+    /// Convert the TSIG record to a string.
+    ///
+    /// The output format is the same as the result of \c toText() for
+    /// other normal types of RRsets (with always using the same RR class
+    /// and TTL).  It also ends with a newline.
+    ///
+    /// \exception std::bad_alloc Internal resource allocation fails (this
+    /// should be rare).
+    ///
+    /// \return A string representation of \c TSIG record
+    std::string toText() const;
+
+    /// The TTL value to be used in TSIG RRs.
+    static const uint32_t TSIG_TTL = 0;
+    //@}
+
+private:
+    const Name key_name_;
+    const rdata::any::TSIG rdata_;
+    const size_t length_;
+};
+
+/// A pointer-like type pointing to a \c TSIGRecord object.
+typedef boost::shared_ptr<TSIGRecord> TSIGRecordPtr;
+
+/// A pointer-like type pointing to an immutable \c TSIGRecord object.
+typedef boost::shared_ptr<const TSIGRecord> ConstTSIGRecordPtr;
+
+/// Insert the \c TSIGRecord as a string into stream.
+///
+/// This method convert \c record into a string and inserts it into the
+/// output stream \c os.
+///
+/// \param os A \c std::ostream object on which the insertion operation is
+/// performed.
+/// \param record A \c TSIGRecord object output by the operation.
+/// \return A reference to the same \c std::ostream object referenced by
+/// parameter \c os after the insertion operation.
+std::ostream& operator<<(std::ostream& os, const TSIGRecord& record);
+}
+}
+
+#endif  // __TSIGRECORD_H
+
+// Local Variables:
+// mode: c++
+// End:
diff --git a/src/lib/log/Makefile.am b/src/lib/log/Makefile.am
index 5770564..c27b3e4 100644
--- a/src/lib/log/Makefile.am
+++ b/src/lib/log/Makefile.am
@@ -16,11 +16,13 @@ liblog_la_SOURCES += logger_impl.cc logger_impl.h
 liblog_la_SOURCES += logger_support.cc logger_support.h
 liblog_la_SOURCES += messagedef.cc messagedef.h
 liblog_la_SOURCES += message_dictionary.cc message_dictionary.h
-liblog_la_SOURCES += message_exception.h message_exception.cc
+liblog_la_SOURCES += message_exception.h
 liblog_la_SOURCES += message_initializer.cc message_initializer.h
 liblog_la_SOURCES += message_reader.cc message_reader.h
 liblog_la_SOURCES += message_types.h
 liblog_la_SOURCES += root_logger_name.cc root_logger_name.h
+liblog_la_SOURCES += log_formatter.h log_formatter.cc
+liblog_la_SOURCES += macros.h
 
 EXTRA_DIST  = README
 EXTRA_DIST += messagedef.mes
diff --git a/src/lib/log/README b/src/lib/log/README
index ed11b5b..529eefc 100644
--- a/src/lib/log/README
+++ b/src/lib/log/README
@@ -44,7 +44,7 @@ stored definitions; this updated text is logged.  However, to aid support,
 the message identifier so in the example above, the message finally logged
 would be something like:
 
-    OPENIN, unable to open a.txt for input
+    FAC_OPENIN, unable to open a.txt for input
 
 
 Using The System
@@ -55,17 +55,15 @@ The steps in using the system are:
    mnemonic for the message, typically 6-12 characters long - and a message.
    The file is described in more detail below.
 
-   Ideally the file should have a file type of ".msg".
+   Ideally the file should have a file type of ".mes".
 
-2. Run it through the message compiler to produce the .h and .cc files.  It
-   is intended that this step be included in the build process.  However,
-   for now run the compiler (found in the "compiler" subdirectory) manually.
-   The only argument is the name of the message file: it will produce as
-   output two files, having the same name as the input file but with file
-   types of ".h" and ".cc".
-
-   The compiler is built in the "compiler" subdirectory of the "src/lib/log"
-   directory.
+2. Run it through the message compiler to produce the .h and .cc files.  This
+   step should be included in the build process. (For an example of how to
+   do this, see src/lib/nsas/Makefile.am.) During development though, the
+   message compiler (found in the "src/lib/log/compiler" directory) will need
+   to be run manually.  The only argument is the name of the message file: it
+   will produce as output two files in the default directory, having the same
+   name as the input file but with file types of ".h" and ".cc".
 
 3. Include the .h file in your source code to define message symbols, and
    make sure that the .cc file is compiled and linked into your program -
@@ -96,11 +94,12 @@ An example file could be:
 
 $PREFIX TEST_
 $NAMESPACE isc::log
-TEST1       message %s is much too large
-+ This message is a test for the general message code
 
-UNKNOWN     unknown message
-+ Issued when the message is unknown.
+% TEST1       message %1 is much too large
+This message is a test for the general message code
+
+% UNKNOWN     unknown message
+Issued when the message is unknown.
 
 -- END --
 
@@ -117,23 +116,31 @@ Points to note:
 
 * Lines starting $ are directives.  At present, two directives are recognised:
 
-  * $PREFIX, which has one argument: the string used to prefix symbols.  If
-    absent, there is no prefix to the symbols. (Prefixes are explained below.)
+  * $PREFIX, which has one optional argument: the string used to prefix symbols.
+    If absent, there is no prefix to the symbols. (Prefixes are explained below.)
+
   * $NAMESPACE, which has one argument: the namespace in which the symbols are
-    created.  In the absence of a $NAMESPACE directive, symbols will be put
-    in the global namespace.
+    created.  In the absence of a $NAMESPACE directive, symbols will be put in
+    the anonymous namespace.
 
-* Lines starting + indicate an explanation for the preceding message.  These
-  are intended to be processed by a separate program and used to generate
-  an error messages manual.  However they are treated like comments by the
-  message compiler.  As with comments, these must be on a line by themselves;
-  if inline, the text (including the leading "+") will be interpreted as
-  part of the line.
+* Message lines.  These start with a "%" and are followed by the message
+  identification and the message text, the latter including zero or more
+  replacement tokens, e.g.
 
-* Message lines.  These comprise a symbol name and a message, which may
-  include zero or more printf-style tokens.  Symbol names will be upper-cased
-  by the compiler.
+     % TEST  message %1 is larger than the permitted length of %2
 
+  * There may be zero or more spaces between the leading "%" and the message
+    identification (which, in the example above, is the word "TEST").
+
+  * The replacement tokens are the strings "%1", "%2" etc.  When a message
+    is logged, these are replaced with the arguments passed to the logging
+    call: %1 refers to the first argument, %2 to the second etc.  Within the
+    message text, the placeholders can appear in any order, and placeholders
+    can be repeated.
+     
+* Remaining lines indicate an explanation for the preceding message.  These
+  are intended to be processed by a separate program and used to generate
+  an error messages manual.  They are ignored by the message compiler.
 
 Message Compiler
 ----------------
@@ -153,9 +160,8 @@ the form:
       :
    }
 
-The symbols define the keys in the global message dictionary.
-
-The namespace enclosing the symbols is set by the $NAMESPACE directive.
+The symbols define the keys in the global message dictionary, with the
+namespace enclosing the symbols set by the $NAMESPACE directive.
 
 The "PREFIX_" part of the symbol name is the string defined in the $PREFIX
 the argument to the directive.  So "$PREFIX MSG_" would prefix the identifier
@@ -163,12 +169,20 @@ ABC with "MSG_" to give the symbol MSG_ABC.  Similarly "$PREFIX E" would
 prefix it with "E" to give the symbol EABC.  If no $PREFIX is given, no
 prefix appears (so the symbol in this example would be ABC).
 
+The prefix is "syntactic sugar".  Generally all symbols in a given message file
+will be prefixed with the same set of letters.  By extracting these into
+a separate prefix, it becomes easier to disambiguate the different symbols.
+
+There may be multiple $PREFIX directives in a file.  A $PREFIX directive applies
+to all message definitions between it an the next $PREFIX directive.  A $PREFIX
+directive with no arguments clears the current prefix.
+
 2) A C++ source file (called <message-file-name>.cc) that holds the definitions
 of the global symbols and code to insert the symbols and messages into the map.
 
 Symbols are defined to be equal to strings holding the identifier, e.g.
 
-   extern const isc::log::MessageID MSG_DUPLNS = "DUPLNS";
+   extern const isc::log::MessageID MSG_DUPLNS = "MSG_DUPLNS";
 
 (The implementation allows symbols to be compared.  However, use of strings
 should not be assumed - a future implementation may change this.)
@@ -243,27 +257,49 @@ To use the current version of the logging:
       highest-level debug messages and 99 for the lowest-level (and typically
       more verbose) messages.
 
-   c) Name of an external message file.  This is the same as a standard message
-      file, although it should not include any directives. (A single directive
-      of a particular type will be ignored; multiple directives will cause the
-      read of the file to fail with an error.)  If a message is replaced, the
-      message should include the same printf-format directives in the same order
-      as the original message.
+   c) The external message file.  If present, this is the same as a standard
+      message file, although it should not include any directives. (A single
+      directive of a particular type will be ignored; multiple directives will
+      cause the read of the file to fail with an error.)
 
 4. Issue logging calls using methods on logger, e.g.
 
-       logger.error(DPS_NSTIMEOUT, "isc.org");
+       logger.error(DPS_NSTIMEOUT).arg("isc.org");
 
    (where, in the example above we might have defined the symbol in the message
    file with something along the lines of:
 
        $PREFIX DPS_
            :
-       NSTIMEOUT  queries to all nameservers for %s have timed out
+       NSTIMEOUT  queries to all nameservers for %1 have timed out
 
    At present, the only logging is to the console.
 
 
+Efficiency Considerations
+-------------------------
+A common pattern in logging is a debug call of the form:
+
+   logger.debug(dbglevel, MSGID).arg(expensive_call()).arg(...
+
+... where "expensive_call()" is a function call to obtain logging information
+that may be computationally intensive.  Although the cost may be justified
+when debugging is enabled, the cost is still incurred even if debugging is
+disabled and the debug() method returns without outputting anything.  (The
+same may be true of other logging levels, although there are likely to be
+fewer calls to logger.info(), logger.error() etc. throughout the code and
+they are less likely to be disabled.)
+
+For this reason, a set of macros is provided and are called using the
+construct:
+
+   LOG_DEBUG(logger, dbglevel, MSGID).arg(expensive_call()).arg(...
+   LOG_INFO(logger, MSGID).arg(expensive_call()...)
+
+If these are used, the arguments passed to the arg() method are not evaluated
+if the relevant logging level is disabled.
+
+
 Severity Guidelines
 ===================
 When using logging, the question arises, what severity should a message be
@@ -361,9 +397,6 @@ is only one piece of code that does this functionality.
 Outstanding Issues
 ==================
 * Ability to configure system according to configuration database.
-* Update the build procedure to create .cc and .h files from the .msg file
-  during the build process. (Requires that the message compiler is built
-  first.)
 
 
 log4cxx Issues
diff --git a/src/lib/log/compiler/message.cc b/src/lib/log/compiler/message.cc
index ef4bafd..457a62e 100644
--- a/src/lib/log/compiler/message.cc
+++ b/src/lib/log/compiler/message.cc
@@ -50,17 +50,13 @@ static const char* VERSION = "1.0-0";
 /// \li A .cc file containing code that adds the messages to the program's
 /// message dictionary at start-up time.
 ///
-/// Alternatively, the program can produce a .py file that contains the
-/// message definitions.
-///
-
 /// \b Invocation<BR>
 /// The program is invoked with the command:
 ///
 /// <tt>message [-v | -h | \<message-file\>]</tt>
 ///
-/// It reads the message file and writes out two files of the same name but with
-/// extensions of .h and .cc.
+/// It reads the message file and writes out two files of the same name in the
+/// default directory but with extensions of .h and .cc.
 ///
 /// \-v causes it to print the version number and exit. \-h prints a help
 /// message (and exits).
@@ -251,17 +247,16 @@ writeClosingNamespace(ostream& output, const vector<string>& ns) {
 ///
 /// \param file Name of the message file.  The header file is written to a
 /// file of the same name but with a .h suffix.
-/// \param prefix Prefix string to use in symbols
 /// \param ns Namespace in which the definitions are to be placed.  An empty
 /// string indicates no namespace.
 /// \param dictionary Dictionary holding the message definitions.
 
 void
-writeHeaderFile(const string& file, const string& prefix,
-        const vector<string>& ns_components, MessageDictionary& dictionary)
+writeHeaderFile(const string& file, const vector<string>& ns_components,
+                MessageDictionary& dictionary)
 {
     Filename message_file(file);
-    Filename header_file(message_file.useAsDefault(".h"));
+    Filename header_file(Filename(message_file.name()).useAsDefault(".h"));
 
     // Text to use as the sentinels.
     string sentinel_text = sentinel(header_file);
@@ -271,7 +266,7 @@ writeHeaderFile(const string& file, const string& prefix,
 
     try {
         if (hfile.fail()) {
-            throw MessageException(MSG_OPNMSGOUT, header_file.fullName(),
+            throw MessageException(MSG_OPENOUT, header_file.fullName(),
                 strerror(errno));
         }
 
@@ -294,7 +289,7 @@ writeHeaderFile(const string& file, const string& prefix,
         vector<string> idents = sortedIdentifiers(dictionary);
         for (vector<string>::const_iterator j = idents.begin();
             j != idents.end(); ++j) {
-            hfile << "extern const isc::log::MessageID " << prefix << *j << ";\n";
+            hfile << "extern const isc::log::MessageID " << *j << ";\n";
         }
         hfile << "\n";
 
@@ -305,7 +300,7 @@ writeHeaderFile(const string& file, const string& prefix,
 
         // Report errors (if any) and exit
         if (hfile.fail()) {
-            throw MessageException(MSG_MSGWRTERR, header_file.fullName(),
+            throw MessageException(MSG_WRITERR, header_file.fullName(),
                 strerror(errno));
         }
 
@@ -354,17 +349,17 @@ replaceNonAlphaNum(char c) {
 /// to it.  But until BIND-10 is ported to Windows, we won't know.
 
 void
-writeProgramFile(const string& file, const string& prefix,
-    const vector<string>& ns_components, MessageDictionary& dictionary)
+writeProgramFile(const string& file, const vector<string>& ns_components,
+                 MessageDictionary& dictionary)
 {
     Filename message_file(file);
-    Filename program_file(message_file.useAsDefault(".cc"));
+    Filename program_file(Filename(message_file.name()).useAsDefault(".cc"));
 
     // Open the output file for writing
     ofstream ccfile(program_file.fullName().c_str());
     try {
         if (ccfile.fail()) {
-            throw MessageException(MSG_OPNMSGOUT, program_file.fullName(),
+            throw MessageException(MSG_OPENOUT, program_file.fullName(),
                 strerror(errno));
         }
 
@@ -387,7 +382,7 @@ writeProgramFile(const string& file, const string& prefix,
         vector<string> idents = sortedIdentifiers(dictionary);
         for (vector<string>::const_iterator j = idents.begin();
             j != idents.end(); ++j) {
-            ccfile << "extern const isc::log::MessageID " << prefix << *j <<
+            ccfile << "extern const isc::log::MessageID " << *j <<
                 " = \"" << *j << "\";\n";
         }
         ccfile << "\n";
@@ -422,7 +417,7 @@ writeProgramFile(const string& file, const string& prefix,
 
         // Report errors (if any) and exit
         if (ccfile.fail()) {
-            throw MessageException(MSG_MSGWRTERR, program_file.fullName(),
+            throw MessageException(MSG_WRITERR, program_file.fullName(),
                 strerror(errno));
         }
 
@@ -518,13 +513,10 @@ main(int argc, char* argv[]) {
         vector<string> ns_components = splitNamespace(reader.getNamespace());
 
         // Write the header file.
-        writeHeaderFile(message_file, reader.getPrefix(), ns_components,
-            dictionary);
+        writeHeaderFile(message_file, ns_components, dictionary);
 
         // Write the file that defines the message symbols and text
-        writeProgramFile(message_file, reader.getPrefix(), ns_components,
-            dictionary);
-
+        writeProgramFile(message_file, ns_components, dictionary);
 
         // Finally, warn of any duplicates encountered.
         warnDuplicates(reader);
@@ -535,9 +527,12 @@ main(int argc, char* argv[]) {
         string text = e.id();
         text += ", ";
         text += global.getText(e.id());
-
         // Format with arguments
-        text = isc::util::str::format(text, e.arguments());
+        vector<string> args(e.arguments());
+        for (size_t i(0); i < args.size(); ++ i) {
+            replacePlaceholder(&text, args[i], i + 1);
+        }
+
         cerr << text << "\n";
 
         return 1;
diff --git a/src/lib/log/log_formatter.cc b/src/lib/log/log_formatter.cc
new file mode 100644
index 0000000..18c4741
--- /dev/null
+++ b/src/lib/log/log_formatter.cc
@@ -0,0 +1,42 @@
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <log/log_formatter.h>
+
+using namespace std;
+using namespace boost;
+
+namespace isc {
+namespace log {
+
+void
+replacePlaceholder(string* message, const string& arg,
+                   const unsigned placeholder)
+{
+    string mark("%" + lexical_cast<string>(placeholder));
+    size_t pos(message->find(mark));
+    if (pos != string::npos) {
+        do {
+            message->replace(pos, mark.size(), arg);
+            pos = message->find(mark, pos + arg.size());
+        } while (pos != string::npos);
+    } else {
+        // We're missing the placeholder, so add some complain
+        message->append(" @@Missing placeholder " + mark + " for '" + arg +
+                        "'@@");
+    }
+}
+
+}
+}
diff --git a/src/lib/log/log_formatter.h b/src/lib/log/log_formatter.h
new file mode 100644
index 0000000..07a024c
--- /dev/null
+++ b/src/lib/log/log_formatter.h
@@ -0,0 +1,146 @@
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#ifndef __LOG_FORMATTER_H
+#define __LOG_FORMMATER_H
+
+#include <string>
+#include <boost/lexical_cast.hpp>
+
+namespace isc {
+namespace log {
+
+/// \brief The internal replacement routine
+///
+/// This is used internally by the Formatter. Replaces a placeholder
+/// in the message by replacement. If the placeholder is not found,
+/// it adds a complain at the end.
+void
+replacePlaceholder(std::string* message, const std::string& replacement,
+                   const unsigned placeholder);
+
+///
+/// \brief The log message formatter
+///
+/// This class allows us to format logging messages conveniently. We
+/// call something like logger.warn(WARN_MSG).arg(15).arg(dnsMsg). This
+/// outputs some text with placeholders replaced by the arguments, if
+/// the logging verbosity is at WARN level or more.
+///
+/// To make this work, we use the Formatter. The warn (or whatever logging
+/// function) returns a Formatter object. That one holds the string to be
+/// output with the placeholders. It also remembers if there should be any
+/// output at all (eg. if the logging is enabled for this level). When there's
+/// no .arg call on the object, it is destroyed right away and we use the
+/// destructor to output the text (but only in case we should output anything).
+///
+/// If there's an .arg call, we return reference to the same object, so another
+/// .arg can be called on it. After the last .arg call is done, the object is
+/// destroyed and, again, we can produce the output.
+///
+/// Of course, if the logging is turned off, we don't bother with any replacing
+/// and just return.
+///
+/// User of logging code should not really care much about this class, only
+/// call the .arg method to generate the correct output.
+///
+/// The class is a template to allow easy testing. Also, we want everything
+/// here in the header anyway and it doesn't depend on the details of what
+/// Logger really is, so it doesn't hurt anything.
+///
+/// Also, if you are interested in the internals, you might find the copy
+/// constructor a bit strange. It deactivates the original formatter. We don't
+/// really want to support copying of the Formatter by user, but C++ needs a
+/// copy constructor when returning from the logging functions, so we need one.
+/// And if we did not deactivate the original Formatter, that one would get
+/// destroyed before any call to .arg, producing an output, and then the one
+/// the .arg calls are called on would get destroyed as well, producing output
+/// again. So, think of this behaviour as soul moving from one to another.
+template<class Logger> class Formatter {
+private:
+    /// \brief The logger we will use to output the final message.
+    ///
+    /// If NULL, we are not active and should not produce anything.
+    mutable Logger* logger_;
+    /// \brief Prefix (eg. "ERROR", "DEBUG" or like that)
+    const char* prefix_;
+    /// \brief The messages with %1, %2... placeholders
+    std::string* message_;
+    /// \brief Which will be the next placeholder to replace
+    unsigned nextPlaceholder_;
+    Formatter& operator =(const Formatter& other);
+public:
+    /// \brief Constructor of "active" formatter
+    ///
+    /// This will create a formatter. If the arguments are set, it
+    /// will be active (will produce output). If you leave them all as NULL,
+    /// it will create an inactive Formatter -- one that'll produce no output.
+    ///
+    /// It is not expected to be called by user of logging system directly.
+    ///
+    /// \param prefix The severity prefix, like "ERROR" or "DEBUG"
+    /// \param message The message with placeholders. We take ownership of
+    ///     it and we will modify the string. Must not be NULL unless
+    ///     logger is also NULL, but it's not checked.
+    /// \param logger The logger where the final output will go, or NULL
+    ///     if no output is wanted.
+    Formatter(const char* prefix = NULL, std::string* message = NULL,
+              Logger* logger = NULL) :
+        logger_(logger), prefix_(prefix), message_(message),
+        nextPlaceholder_(1)
+    {
+    }
+
+    Formatter(const Formatter& other) :
+        logger_(other.logger_), prefix_(other.prefix_),
+        message_(other.message_), nextPlaceholder_(other.nextPlaceholder_)
+    {
+        other.logger_ = false;
+    }
+    /// \brief Destructor.
+    //
+    /// This is the place where output happens if the formatter is active.
+    ~ Formatter() {
+        if (logger_) {
+            logger_->output(prefix_, *message_);
+            delete message_;
+        }
+    }
+    /// \brief Replaces another placeholder
+    ///
+    /// Replaces another placeholder and returns a new formatter with it.
+    /// Deactivates the current formatter. In case the formatter is not active,
+    /// only produces another inactive formatter.
+    ///
+    /// \param arg The argument to place into the placeholder.
+    template<class Arg> Formatter& arg(const Arg& value) {
+        return (arg(boost::lexical_cast<std::string>(value)));
+    }
+    /// \brief String version of arg.
+    Formatter& arg(const std::string& arg) {
+        if (logger_) {
+            // FIXME: This logic has a problem. If we had a message like
+            // "%1 %2" and called .arg("%2").arg(42), we would get "42 %2".
+            // But we consider this to be rare enough not to complicate
+            // matters.
+            replacePlaceholder(message_, arg, nextPlaceholder_ ++);
+        }
+        return (*this);
+    }
+};
+
+}
+}
+
+#endif
diff --git a/src/lib/log/logger.cc b/src/lib/log/logger.cc
index 99dc3a1..c340315 100644
--- a/src/lib/log/logger.cc
+++ b/src/lib/log/logger.cc
@@ -112,52 +112,57 @@ Logger::isFatalEnabled() {
 // Output methods
 
 void
-Logger::debug(int dbglevel, const isc::log::MessageID& ident, ...) {
+Logger::output(const char* sevText, const string& message) {
+    getLoggerPtr()->outputRaw(sevText, message);
+}
+
+Logger::Formatter
+Logger::debug(int dbglevel, const isc::log::MessageID& ident) {
     if (isDebugEnabled(dbglevel)) {
-        va_list ap;
-        va_start(ap, ident);
-        getLoggerPtr()->debug(ident, ap);
-        va_end(ap);
+        return (Formatter("DEBUG", getLoggerPtr()->lookupMessage(ident),
+                          this));
+    } else {
+        return (Formatter());
     }
 }
 
-void
-Logger::info(const isc::log::MessageID& ident, ...) {
+Logger::Formatter
+Logger::info(const isc::log::MessageID& ident) {
     if (isInfoEnabled()) {
-        va_list ap;
-        va_start(ap, ident);
-        getLoggerPtr()->info(ident, ap);
-        va_end(ap);
+        return (Formatter("INFO ", getLoggerPtr()->lookupMessage(ident),
+                          this));
+    } else {
+        return (Formatter());
     }
 }
 
-void
-Logger::warn(const isc::log::MessageID& ident, ...) {
+Logger::Formatter
+Logger::warn(const isc::log::MessageID& ident) {
     if (isWarnEnabled()) {
-        va_list ap;
-        va_start(ap, ident);
-        getLoggerPtr()->warn(ident, ap);
-        va_end(ap);
+        return (Formatter("WARN ", getLoggerPtr()->lookupMessage(ident),
+                          this));
+    } else {
+        return (Formatter());
     }
 }
 
-void
-Logger::error(const isc::log::MessageID& ident, ...) {
+Logger::Formatter
+Logger::error(const isc::log::MessageID& ident) {
     if (isErrorEnabled()) {
-        va_list ap;
-        va_start(ap, ident);
-        getLoggerPtr()->error(ident, ap);
-        va_end(ap);
+        return (Formatter("ERROR", getLoggerPtr()->lookupMessage(ident),
+                          this));
+    } else {
+        return (Formatter());
     }
 }
 
-void
-Logger::fatal(const isc::log::MessageID& ident, ...) {
+Logger::Formatter
+Logger::fatal(const isc::log::MessageID& ident) {
     if (isFatalEnabled()) {
-        va_list ap;
-        va_start(ap, ident);
-        getLoggerPtr()->fatal(ident, ap);
-        va_end(ap);
+        return (Formatter("FATAL", getLoggerPtr()->lookupMessage(ident),
+                          this));
+    } else {
+        return (Formatter());
     }
 }
 
diff --git a/src/lib/log/logger.h b/src/lib/log/logger.h
index 88e88e2..6bd8924 100644
--- a/src/lib/log/logger.h
+++ b/src/lib/log/logger.h
@@ -21,6 +21,7 @@
 #include <log/debug_levels.h>
 #include <log/logger_levels.h>
 #include <log/message_types.h>
+#include <log/log_formatter.h>
 
 namespace isc {
 namespace log {
@@ -83,10 +84,11 @@ public:
         loggerptr_(NULL), name_(name), infunc_(infunc)
     {}
 
-
     /// \brief Destructor
     virtual ~Logger();
 
+    /// \brief The formatter used to replace placeholders
+    typedef isc::log::Formatter<Logger> Formatter;
 
     /// \brief Get Name of Logger
     ///
@@ -157,36 +159,31 @@ public:
     /// \param dbglevel Debug level, ranging between 0 and 99.  Higher numbers
     /// are used for more verbose output.
     /// \param ident Message identification.
-    /// \param ... Optional arguments for the message.
-    void debug(int dbglevel, const MessageID& ident, ...);
+    Formatter debug(int dbglevel, const MessageID& ident);
 
 
     /// \brief Output Informational Message
     ///
     /// \param ident Message identification.
-    /// \param ... Optional arguments for the message.
-    void info(const MessageID& ident, ...);
+    Formatter info(const MessageID& ident);
 
 
     /// \brief Output Warning Message
     ///
     /// \param ident Message identification.
-    /// \param ... Optional arguments for the message.
-    void warn(const MessageID& ident, ...);
+    Formatter warn(const MessageID& ident);
 
 
     /// \brief Output Error Message
     ///
     /// \param ident Message identification.
-    /// \param ... Optional arguments for the message.
-    void error(const MessageID& ident, ...);
+    Formatter error(const MessageID& ident);
 
 
     /// \brief Output Fatal Message
     ///
     /// \param ident Message identification.
-    /// \param ... Optional arguments for the message.
-    void fatal(const MessageID& ident, ...);
+    Formatter fatal(const MessageID& ident);
 
     /// \brief Equality
     ///
@@ -205,6 +202,12 @@ protected:
     static void reset();
 
 private:
+    friend class isc::log::Formatter<Logger>;
+    /// \brief Raw output function
+    ///
+    /// This is used by the formatter to output formatted output.
+    void output(const char* sevText, const std::string& message);
+
     /// \brief Copy Constructor
     ///
     /// Disabled (marked private) as it makes no sense to copy the logger -
diff --git a/src/lib/log/logger_impl.cc b/src/lib/log/logger_impl.cc
index 41153e9..b30f835 100644
--- a/src/lib/log/logger_impl.cc
+++ b/src/lib/log/logger_impl.cc
@@ -13,6 +13,7 @@
 // PERFORMANCE OF THIS SOFTWARE
 
 #include <iostream>
+#include <iomanip>
 #include <algorithm>
 
 #include <stdarg.h>
@@ -194,17 +195,14 @@ LoggerImpl::isDebugEnabled(int dbglevel) {
 }
 
 // Output a general message
+string*
+LoggerImpl::lookupMessage(const MessageID& ident) {
+    return (new string(string(ident) + ", " +
+                       MessageDictionary::globalDictionary().getText(ident)));
+}
 
 void
-LoggerImpl::output(const char* sev_text, const MessageID& ident,
-    va_list ap)
-{
-    char message[512];      // Should be large enough for any message
-
-    // Obtain text of the message and substitute arguments.
-    const string format = MessageDictionary::globalDictionary().getText(ident);
-    vsnprintf(message, sizeof(message), format.c_str(), ap);
-
+LoggerImpl::outputRaw(const char* sevText, const string& message) {
     // Get the time in a struct tm format, and convert to text
     time_t t_time;
     time(&t_time);
@@ -214,8 +212,8 @@ LoggerImpl::output(const char* sev_text, const MessageID& ident,
     (void) strftime(chr_time, sizeof(chr_time), "%Y-%m-%d %H:%M:%S", tm_time);
 
     // Now output.
-    std::cout << chr_time << " " << sev_text << " [" << getName() << "] " <<
-        ident << ", " << message << "\n";
+    cout << chr_time << " " << sevText << " [" << getName() << "] " <<
+        message << endl;
 }
 
 } // namespace log
diff --git a/src/lib/log/logger_impl.h b/src/lib/log/logger_impl.h
index 9fc9cf9..187e478 100644
--- a/src/lib/log/logger_impl.h
+++ b/src/lib/log/logger_impl.h
@@ -167,64 +167,16 @@ public:
         }
     }
 
-
-    /// \brief Output General Message
-    ///
-    /// The message is formatted to include the date and time, the severity
-    /// and the logger generating the message.
+    /// \brief Raw output
     ///
-    /// \param sev_text Severity level as a text string
-    /// \param ident Message identification
-    /// \param ap Variable argument list holding message arguments
-    void output(const char* sev_text, const MessageID& ident,
-        va_list ap);
-
+    /// Writes the message with time into the log. Used by the Formatter
+    /// to produce output.
+    void outputRaw(const char* sev_text, const std::string& message);
 
-    /// \brief Output Debug Message
+    /// \brief Look up message text in dictionary
     ///
-    /// \param ident Message identification.
-    /// \param text Text to log
-    /// \param ap Variable argument list holding message arguments
-    void debug(const MessageID& ident, va_list ap) {
-        output("DEBUG", ident, ap);
-    }
-
-
-    /// \brief Output Informational Message
-    ///
-    /// \param ident Message identification.
-    /// \param text Text to log
-    /// \param ap Variable argument list holding message arguments
-    void info(const MessageID& ident, va_list ap) {
-        output("INFO ", ident, ap);
-    }
-
-    /// \brief Output Warning Message
-    ///
-    /// \param ident Message identification.
-    /// \param text Text to log
-    /// \param ap Variable argument list holding message arguments
-    void warn(const MessageID& ident, va_list ap) {
-        output("WARN ", ident, ap);
-    }
-
-    /// \brief Output Error Message
-    ///
-    /// \param ident Message identification.
-    /// \param text Text to log
-    /// \param ap Variable argument list holding message arguments
-    void error(const MessageID& ident, va_list ap) {
-        output("ERROR", ident, ap);
-    }
-
-    /// \brief Output Fatal Message
-    ///
-    /// \param ident Message identification.
-    /// \param text Text to log
-    /// \param ap Variable argument list holding message arguments
-    void fatal(const MessageID& ident, va_list ap) {
-        output("FATAL", ident, ap);
-    }
+    /// This gets you the unformatted text of message for given ID.
+    std::string* lookupMessage(const MessageID& id);
 
     /// \brief Equality
     ///
diff --git a/src/lib/log/logger_support.cc b/src/lib/log/logger_support.cc
index f8bf075..e17c47d 100644
--- a/src/lib/log/logger_support.cc
+++ b/src/lib/log/logger_support.cc
@@ -24,7 +24,9 @@
 /// These functions will be replaced once the code has been written to obtain
 /// the logging parameters from the configuration database.
 
+#include <iostream>
 #include <algorithm>
+#include <iostream>
 #include <string>
 #include <vector>
 #include <boost/lexical_cast.hpp>
@@ -62,7 +64,7 @@ readLocalMessageFile(const char* file) {
     MessageDictionary& dictionary = MessageDictionary::globalDictionary();
     MessageReader reader(&dictionary);
     try {
-        logger.info(MSG_RDLOCMES, file);
+        logger.info(MSG_RDLOCMES).arg(file);
         reader.readFile(file, MessageReader::REPLACE);
 
         // File successfully read, list the duplicates
@@ -70,7 +72,7 @@ readLocalMessageFile(const char* file) {
         for (MessageReader::MessageIDCollection::const_iterator
             i = unknown.begin(); i != unknown.end(); ++i) {
             string message_id = boost::lexical_cast<string>(*i);
-                logger.warn(MSG_IDNOTFND, message_id.c_str());
+                logger.warn(MSG_IDNOTFND).arg(message_id);
         }
     }
     catch (MessageException& e) {
@@ -82,11 +84,15 @@ readLocalMessageFile(const char* file) {
             break;
 
         case 1:
-            logger.error(ident, args[0].c_str());
+            logger.error(ident).arg(args[0]);
             break;
 
-        default:    // 2 or more (2 should be the maximum)
-            logger.error(ident, args[0].c_str(), args[1].c_str());
+        case 2:
+            logger.error(ident).arg(args[0]).arg(args[1]);
+            break;
+
+        default:    // 3 or more (3 should be the maximum)
+            logger.error(ident).arg(args[0]).arg(args[1]).arg(args[2]);
         }
     }
 }
@@ -117,7 +123,7 @@ initLogger(const string& root, isc::log::Severity severity, int dbglevel,
         vector<string>::iterator new_end =
             unique(duplicates.begin(), duplicates.end());
         for (vector<string>::iterator i = duplicates.begin(); i != new_end; ++i) {
-            logger.warn(MSG_DUPMSGID, i->c_str());
+            logger.warn(MSG_DUPMSGID).arg(*i);
         }
 
     }
@@ -128,5 +134,76 @@ initLogger(const string& root, isc::log::Severity severity, int dbglevel,
     }
 }
 
+/// Logger Run-Time Initialization via Environment Variables
+void initLogger() {
+
+    // Root logger name is defined by the environment variable B10_LOGGER_ROOT.
+    // If not present, the name is "b10root".
+    const char* DEFAULT_ROOT = "b10root";
+    const char* root = getenv("B10_LOGGER_ROOT");
+    if (! root) {
+        root = DEFAULT_ROOT;
+    }
+
+    // Set the logging severity.  The environment variable is
+    // B10_LOGGER_SEVERITY, and can be one of "DEBUG", "INFO", "WARN", "ERROR"
+    // of "FATAL".  Note that the string must be in upper case with no leading
+    // of trailing blanks.
+    isc::log::Severity severity = isc::log::DEFAULT;
+    const char* sev_char = getenv("B10_LOGGER_SEVERITY");
+    if (sev_char) {
+        string sev_string(sev_char);
+        if (sev_string == "DEBUG") {
+            severity = isc::log::DEBUG;
+        } else if (sev_string == "INFO") {
+            severity = isc::log::INFO;
+        } else if (sev_string == "WARN") {
+            severity = isc::log::WARN;
+        } else if (sev_string == "ERROR") {
+            severity = isc::log::ERROR;
+        } else if (sev_string == "FATAL") {
+            severity = isc::log::FATAL;
+        } else {
+            std::cerr << "**ERROR** unrecognised logger severity of '"
+                      << sev_string << "' - default severity will be used\n";
+        }
+    }
+
+    // If the severity is debug, get the debug level (environment variable
+    // B10_LOGGER_DBGLEVEL), which should be in the range 0 to 99.
+    int dbglevel = 0;
+    if (severity == isc::log::DEBUG) {
+        const char* dbg_char = getenv("B10_LOGGER_DBGLEVEL");
+        if (dbg_char) {
+            int level = 0;
+            try {
+                level = boost::lexical_cast<int>(dbg_char);
+                if (level < MIN_DEBUG_LEVEL) {
+                    std::cerr << "**ERROR** debug level of " << level
+                              << " is invalid - a value of " << MIN_DEBUG_LEVEL
+                              << " will be used\n";
+                    level = MIN_DEBUG_LEVEL;
+                } else if (level > MAX_DEBUG_LEVEL) {
+                    std::cerr << "**ERROR** debug level of " << level
+                              << " is invalid - a value of " << MAX_DEBUG_LEVEL
+                              << " will be used\n";
+                    level = MAX_DEBUG_LEVEL;
+                }
+            } catch (...) {
+                // Error, but not fatal to the test
+                std::cerr << "**ERROR** Unable to translate "
+                             "B10_LOGGER_DBGLEVEL - a value of 0 will be used\n";
+            }
+            dbglevel = level;
+        }
+    }
+
+    /// Set the local message file
+    const char* localfile = getenv("B10_LOGGER_LOCALMSG");
+
+    // Initialize logging
+    initLogger(root, severity, dbglevel, localfile);
+}
+
 } // namespace log
 } // namespace isc
diff --git a/src/lib/log/logger_support.h b/src/lib/log/logger_support.h
index 6b5fdec..f4861b2 100644
--- a/src/lib/log/logger_support.h
+++ b/src/lib/log/logger_support.h
@@ -39,6 +39,37 @@ namespace log {
 void initLogger(const std::string& root, isc::log::Severity severity,
     int dbglevel, const char* file);
 
+
+/// \brief Run-Time Initialization from Environment
+///
+/// Performs run-time initialization of the logger via the setting of
+/// environment variables.  These are:
+///
+/// B10_LOGGER_ROOT
+/// Name of the root logger.  If not given, the string "b10root" will be used.
+///
+/// B10_LOGGER_SEVERITY
+/// Severity of messages that will be logged.  This must be one of the strings
+/// "DEBUG", "INFO", "WARN", "ERROR", "FATAL". (Must be upper case and must
+/// not contain leading or trailing spaces.)  If not specified (or if
+/// specified but incorrect), the default for the logging system will be used
+/// (currently INFO).
+///
+/// B10_LOGGER_DBGLEVEL
+/// Ignored if the level is not DEBUG, this should be a number between 0 and
+/// 99 indicating the logging severity.  The default is 0.  If outside these
+/// limits or if not a number, a value of 0 is used.
+///
+/// B10_LOGGER_LOCALMSG
+/// If defined, the path specification of a file that contains message
+/// definitions replacing ones in the default dictionary.
+///
+/// Any errors in the settings cause messages to be output to stderr.
+///
+/// This function is most likely to be called from unit test programs.
+
+void initLogger();
+
 } // namespace log
 } // namespace isc
 
diff --git a/src/lib/log/macros.h b/src/lib/log/macros.h
new file mode 100644
index 0000000..3128131
--- /dev/null
+++ b/src/lib/log/macros.h
@@ -0,0 +1,50 @@
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#ifndef __LOG_MACROS_H
+#define __LOG_MACROS_H
+
+#include <log/logger.h>
+
+/// \brief Macro to conveniently test debug output and log it
+#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE) \
+    if (!(LOGGER).isDebugEnabled((LEVEL))) { \
+    } else \
+        (LOGGER).debug((LEVEL), (MESSAGE))
+
+/// \brief Macro to conveniently test info output and log it
+#define LOG_INFO(LOGGER, MESSAGE) \
+    if (!(LOGGER).isInfoEnabled()) { \
+    } else \
+        (LOGGER).info((MESSAGE))
+
+/// \brief Macro to conveniently test warn output and log it
+#define LOG_WARN(LOGGER, MESSAGE) \
+    if (!(LOGGER).isWarnEnabled()) { \
+    } else \
+        (LOGGER).warn((MESSAGE))
+
+/// \brief Macro to conveniently test error output and log it
+#define LOG_ERROR(LOGGER, MESSAGE) \
+    if (!(LOGGER).isErrorEnabled()) { \
+    } else \
+        (LOGGER).error((MESSAGE))
+
+/// \brief Macro to conveniently test fatal output and log it
+#define LOG_FATAL(LOGGER, MESSAGE) \
+    if (!(LOGGER).isFatalEnabled()) { \
+    } else \
+        (LOGGER).fatal((MESSAGE))
+
+#endif
diff --git a/src/lib/log/message_exception.cc b/src/lib/log/message_exception.cc
deleted file mode 100644
index 1a69ca5..0000000
--- a/src/lib/log/message_exception.cc
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
-// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
-// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-// PERFORMANCE OF THIS SOFTWARE.
-
-/// \brief Body of Virtual Destructor
-
-#include <log/message_exception.h>
-
-namespace isc {
-namespace log {
-
-MessageException::~MessageException() throw() {
-}
-
-} // namespace log
-} // namespace isc
diff --git a/src/lib/log/message_exception.h b/src/lib/log/message_exception.h
index 30c6618..eebee89 100644
--- a/src/lib/log/message_exception.h
+++ b/src/lib/log/message_exception.h
@@ -19,6 +19,7 @@
 #include <string>
 #include <vector>
 
+#include <boost/lexical_cast.hpp>
 #include <log/message_types.h>
 
 namespace isc {
@@ -35,33 +36,47 @@ public:
 
     /// \brief Constructor
     ///
-    /// \param id Message identification
-    MessageException(MessageID id) : id_(id)
-    {}
+    /// \param id Message identification.
+    /// \param lineno Line number on which error occurred (if > 0).
+    MessageException(MessageID id, int lineno = 0) : id_(id)
+    {
+        if (lineno > 0) {
+            args_.push_back(boost::lexical_cast<std::string>(lineno));
+        }
+    }
 
     /// \brief Constructor
     ///
-    /// \param id Message identification
-    /// \param arg1 First message argument
-    MessageException(MessageID id, const std::string& arg1) : id_(id)
+    /// \param id Message identification.
+    /// \param arg1 First message argument.
+    /// \param lineno Line number on which error occurred (if > 0).
+    MessageException(MessageID id, const std::string& arg1, int lineno = 0)
+        : id_(id)
     {
+        if (lineno > 0) {
+            args_.push_back(boost::lexical_cast<std::string>(lineno));
+        }
         args_.push_back(arg1);
     }
 
     /// \brief Constructor
     ///
-    /// \param id Message identification
-    /// \param arg1 First message argument
-    /// \param arg2 Second message argument
+    /// \param id Message identification.
+    /// \param arg1 First message argument.
+    /// \param arg2 Second message argument.
+    /// \param lineno Line number on which error occurred (if > 0).
     MessageException(MessageID id, const std::string& arg1,
-        const std::string& arg2) : id_(id)
+        const std::string& arg2, int lineno = 0) : id_(id)
     {
+        if (lineno > 0) {
+            args_.push_back(boost::lexical_cast<std::string>(lineno));
+        }
         args_.push_back(arg1);
         args_.push_back(arg2);
     }
 
     /// \brief Destructor
-    virtual ~MessageException() throw();
+    ~MessageException() throw() {}
 
     /// \brief Return Message ID
     ///
diff --git a/src/lib/log/message_reader.cc b/src/lib/log/message_reader.cc
index 7281346..1a0b242 100644
--- a/src/lib/log/message_reader.cc
+++ b/src/lib/log/message_reader.cc
@@ -12,8 +12,10 @@
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // PERFORMANCE OF THIS SOFTWARE.
 
+#include <cassert>
 #include <errno.h>
 #include <string.h>
+#include <iostream>
 
 #include <iostream>
 #include <fstream>
@@ -25,45 +27,50 @@
 
 using namespace std;
 
-namespace isc {
-namespace log {
-
-// Virtual destructor.
-MessageReader::~MessageReader() {
+namespace {
+const char DIRECTIVE_FLAG = '$';    // Starts each directive
+const char MESSAGE_FLAG = '%';      // Starts each message
 }
 
 
+namespace isc {
+namespace log {
+
 // Read the file.
 
 void
 MessageReader::readFile(const string& file, MessageReader::Mode mode) {
 
-    // Ensure the non-added collection is empty: this object might be
-    // being reused.
+    // Ensure the non-added collection is empty: we could be re-using this
+    // object.
     not_added_.clear();
 
-    // Open the file
+    // Open the file.
     ifstream infile(file.c_str());
     if (infile.fail()) {
-        throw MessageException(MSG_OPNMSGIN, file, strerror(errno));
+        throw MessageException(MSG_OPENIN, file, strerror(errno));
     }
 
-    // Loop round reading it.
+    // Loop round reading it.  As we process the file one line at a time,
+    // keep a track of line number of aid diagnosis of problems.
     string line;
     getline(infile, line);
+    lineno_ = 0;
+
     while (infile.good()) {
+        ++lineno_;
         processLine(line, mode);
         getline(infile, line);
     }
 
     // Why did the loop terminate?
     if (!infile.eof()) {
-        throw MessageException(MSG_MSGRDERR, file, strerror(errno));
+        throw MessageException(MSG_READERR, file, strerror(errno));
     }
     infile.close();
 }
 
-// Parse a line of the file
+// Parse a line of the file.
 
 void
 MessageReader::processLine(const string& line, MessageReader::Mode mode) {
@@ -74,15 +81,16 @@ MessageReader::processLine(const string& line, MessageReader::Mode mode) {
     if (text.empty()) {
         ;                           // Ignore blank lines
 
-    } else if ((text[0] == '#') || (text[0] == '+')) {
-        ;                           // Ignore comments or descriptions
-
-    } else if (text[0] == '$') {
+    } else if (text[0] == DIRECTIVE_FLAG) {
         parseDirective(text);       // Process directives
 
-    } else {
-        parseMessage(text, mode);   // Process other lines
 
+    } else if (text[0] == MESSAGE_FLAG) {
+        parseMessage(text, mode);   // Process message definition line
+
+    } else {
+        ;                           // Other lines are extended message
+                                    // description so are ignored
     }
 }
 
@@ -99,130 +107,162 @@ MessageReader::parseDirective(const std::string& text) {
     isc::util::str::uppercase(tokens[0]);
     if (tokens[0] == string("$PREFIX")) {
         parsePrefix(tokens);
+
     } else if (tokens[0] == string("$NAMESPACE")) {
         parseNamespace(tokens);
+
     } else {
-        throw MessageException(MSG_UNRECDIR, tokens[0]);
+
+        // Unrecognised directive
+        throw MessageException(MSG_UNRECDIR, tokens[0], lineno_);
     }
 }
 
 // Process $PREFIX
-
 void
 MessageReader::parsePrefix(const vector<string>& tokens) {
 
-    // Check argument count
-
-    static string valid = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_";
-    if (tokens.size() < 2) {
-        throw MessageException(MSG_PRFNOARG);
-    } else if (tokens.size() > 2) {
-        throw MessageException(MSG_PRFEXTRARG);
-
-    }
+    // Should not get here unless there is something in the tokens array.
+    assert(tokens.size() > 0);
 
-    // As a style, we are going to have the symbols in uppercase
-    string prefix = tokens[1];
-    isc::util::str::uppercase(prefix);
+    // Process $PREFIX.  With no arguments, the prefix is set to the empty
+    // string.  One argument sets the prefix to the to its value and more than
+    // one argument is invalid.
+    if (tokens.size() == 1) {
+        prefix_ = "";
 
-    // Token is potentially valid providing it only contains alphabetic
-    // and numeric characters (and underscores) and does not start with a
-    // digit.
-    if ((prefix.find_first_not_of(valid) != string::npos) ||
-        (std::isdigit(prefix[0]))) {
+    } else if (tokens.size() == 2) {
+        prefix_ = tokens[1];
 
-        // Invalid character in string or it starts with a digit.
-        throw MessageException(MSG_PRFINVARG, tokens[1]);
-    }
+        // Token is potentially valid providing it only contains alphabetic
+        // and numeric characters (and underscores) and does not start with a
+        // digit.
+        if (invalidSymbol(prefix_)) {
+            throw MessageException(MSG_PRFINVARG, prefix_, lineno_);
+        }
 
-    // All OK - unless the prefix has already been set.
+    } else {
 
-    if (prefix_.size() != 0) {
-        throw MessageException(MSG_DUPLPRFX);
+        // Too many arguments
+        throw MessageException(MSG_PRFEXTRARG, lineno_);
     }
+}
 
-    // Prefix has not been set, so set it and return success.
-
-    prefix_ = prefix;
+// Check if string is an invalid C++ symbol.  It is valid if comprises only
+// alphanumeric characters and underscores, and does not start with a digit.
+// (Owing to the logic of the rest of the code, we check for its invalidity,
+// not its validity.)
+bool
+MessageReader::invalidSymbol(const string& symbol) {
+    static const string valid_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+                                      "abcdefghijklmnopqrstuvwxyz"
+                                      "0123456789_";
+    return ( symbol.empty() ||
+            (symbol.find_first_not_of(valid_chars) != string::npos) ||
+            (std::isdigit(symbol[0])));
 }
 
 // Process $NAMESPACE.  A lot of the processing is similar to that of $PREFIX,
 // except that only limited checks will be done on the namespace (to avoid a
-// lot of parsing and separating out of the namespace components.)
+// lot of parsing and separating out of the namespace components.)  Also, unlike
+// $PREFIX, there can only be one $NAMESPACE in a file.
 
 void
 MessageReader::parseNamespace(const vector<string>& tokens) {
 
     // Check argument count
-
-    static string valid = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_:"
-        "abcdefghijklmnopqrstuvwxyz";
-
     if (tokens.size() < 2) {
-        throw MessageException(MSG_NSNOARG);
+        throw MessageException(MSG_NSNOARG, lineno_);
 
     } else if (tokens.size() > 2) {
-        throw MessageException(MSG_NSEXTRARG);
+        throw MessageException(MSG_NSEXTRARG, lineno_);
 
     }
 
     // Token is potentially valid providing it only contains alphabetic
-    // and numeric characters (and underscores and colons).
-    if (tokens[1].find_first_not_of(valid) != string::npos) {
-
-        // Invalid character in string or it starts with a digit.
-        throw MessageException(MSG_NSINVARG, tokens[1]);
+    // and numeric characters (and underscores and colons).  As noted above,
+    // we won't be exhaustive - after all, and code containing the resultant
+    // namespace will have to be compiled, and the compiler will catch errors.
+    static const string valid_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+                                      "abcdefghijklmnopqrstuvwxyz"
+                                      "0123456789_:";
+    if (tokens[1].find_first_not_of(valid_chars) != string::npos) {
+        throw MessageException(MSG_NSINVARG, tokens[1], lineno_);
     }
 
     // All OK - unless the namespace has already been set.
     if (ns_.size() != 0) {
-        throw MessageException(MSG_DUPLNS);
+        throw MessageException(MSG_DUPLNS, lineno_);
     }
 
     // Prefix has not been set, so set it and return success.
-
     ns_ = tokens[1];
 }
 
 // Process message.  By the time this method is called, the line has been
-// stripped of leading and trailing spaces, and we believe that it is a line
-// defining a message.  The first token on the line is converted to uppercase
-// and becomes the message ID; the rest of the line is the message text.
+// stripped of leading and trailing spaces.  The first character of the string
+// is the message introducer, so we can get rid of that.  The remainder is
+// a line defining a message.
+//
+// The first token on the line, when concatenated to the prefix and converted to
+// upper-case, is the message ID.  The first of the line from the next token
+// on is the message text.
 
 void
 MessageReader::parseMessage(const std::string& text, MessageReader::Mode mode) {
 
     static string delimiters("\t\n ");   // Delimiters
 
+    // The line passed should be at least one character long and start with the
+    // message introducer (else we should not have got here).
+    assert((text.size() >= 1) && (text[0] == MESSAGE_FLAG));
+
+    // A line comprising just the message introducer is not valid.
+    if (text.size() == 1) {
+        throw MessageException(MSG_NOMSGID, text, lineno_);
+    }
+
+    // Strip off the introducer and any leading space after that.
+    string message_line = isc::util::str::trim(text.substr(1));
+
     // Look for the first delimiter.
-    size_t first_delim = text.find_first_of(delimiters);
+    size_t first_delim = message_line.find_first_of(delimiters);
     if (first_delim == string::npos) {
 
         // Just a single token in the line - this is not valid
-        throw MessageException(MSG_NOMSGTXT, text);
+        throw MessageException(MSG_NOMSGTXT, message_line, lineno_);
     }
 
-    // Extract the first token into the message ID
-    string ident = text.substr(0, first_delim);
+    // Extract the first token into the message ID, preceding it with the
+    // current prefix, then convert to upper-case.  If the prefix is not set,
+    // perform the valid character check now - the string will become a C++
+    // symbol so we may as well identify problems early.
+    string ident = prefix_ + message_line.substr(0, first_delim);
+    if (prefix_.empty()) {
+        if (invalidSymbol(ident)) {
+            throw MessageException(MSG_INVMSGID, ident, lineno_);
+        }
+    }
+    isc::util::str::uppercase(ident);
 
     // Locate the start of the message text
-    size_t first_text = text.find_first_not_of(delimiters, first_delim);
+    size_t first_text = message_line.find_first_not_of(delimiters, first_delim);
     if (first_text == string::npos) {
 
         // ?? This happens if there are trailing delimiters, which should not
         // occur as we have stripped trailing spaces off the line.  Just treat
         // this as a single-token error for simplicity's sake.
-        throw MessageException(MSG_NOMSGTXT, text);
+        throw MessageException(MSG_NOMSGTXT, message_line, lineno_);
     }
 
     // Add the result to the dictionary and to the non-added list if the add to
     // the dictionary fails.
     bool added;
     if (mode == ADD) {
-        added = dictionary_->add(ident, text.substr(first_text));
+        added = dictionary_->add(ident, message_line.substr(first_text));
     }
     else {
-        added = dictionary_->replace(ident, text.substr(first_text));
+        added = dictionary_->replace(ident, message_line.substr(first_text));
     }
     if (!added) {
         not_added_.push_back(ident);
diff --git a/src/lib/log/message_reader.h b/src/lib/log/message_reader.h
index d07c7f2..eded9c6 100644
--- a/src/lib/log/message_reader.h
+++ b/src/lib/log/message_reader.h
@@ -64,10 +64,9 @@ public:
         dictionary_(dictionary)
     {}
 
-
     /// \brief Virtual Destructor
-    virtual ~MessageReader();
-
+    virtual ~MessageReader()
+    {}
 
     /// \brief Get Dictionary
     ///
@@ -188,10 +187,24 @@ private:
     /// \param tokens $NAMESPACE line split into tokens
     void parseNamespace(const std::vector<std::string>& tokens);
 
+    /// \brief Check for invalid C++ symbol name
+    ///
+    /// The message ID (or concatenation of prefix and message ID) will be used
+    /// as the name of a symbol in C++ code.  This function checks if the name
+    /// is invalid (contains anything other than alphanumeric characters or
+    /// underscores, or starts with a digit).
+    ///
+    /// \param symbol name to check to see if it is an invalid C++ symbol.
+    ///
+    /// \return true if the name is invalid, false if it is valid.
+    bool invalidSymbol(const std::string& symbol);
+
+
 
     /// Attributes
     MessageDictionary*  dictionary_;    ///< Dictionary to add messages to
     MessageIDCollection not_added_;     ///< List of IDs not added
+    int                 lineno_;        ///< Number of last line read
     std::string         prefix_;        ///< Argument of $PREFIX statement
     std::string         ns_;            ///< Argument of $NAMESPACE statement
 };
diff --git a/src/lib/log/messagedef.cc b/src/lib/log/messagedef.cc
index f680a74..5cc89b3 100644
--- a/src/lib/log/messagedef.cc
+++ b/src/lib/log/messagedef.cc
@@ -1,4 +1,4 @@
-// File created from messagedef.mes on Mon Feb 14 11:07:45 2011
+// File created from messagedef.mes on Mon May  9 13:52:54 2011
 
 #include <cstddef>
 #include <log/message_types.h>
@@ -7,23 +7,23 @@
 namespace isc {
 namespace log {
 
-extern const isc::log::MessageID MSG_DUPLNS = "DUPLNS";
-extern const isc::log::MessageID MSG_DUPLPRFX = "DUPLPRFX";
-extern const isc::log::MessageID MSG_DUPMSGID = "DUPMSGID";
-extern const isc::log::MessageID MSG_IDNOTFND = "IDNOTFND";
-extern const isc::log::MessageID MSG_MSGRDERR = "MSGRDERR";
-extern const isc::log::MessageID MSG_MSGWRTERR = "MSGWRTERR";
-extern const isc::log::MessageID MSG_NOMSGTXT = "NOMSGTXT";
-extern const isc::log::MessageID MSG_NSEXTRARG = "NSEXTRARG";
-extern const isc::log::MessageID MSG_NSINVARG = "NSINVARG";
-extern const isc::log::MessageID MSG_NSNOARG = "NSNOARG";
-extern const isc::log::MessageID MSG_OPNMSGIN = "OPNMSGIN";
-extern const isc::log::MessageID MSG_OPNMSGOUT = "OPNMSGOUT";
-extern const isc::log::MessageID MSG_PRFEXTRARG = "PRFEXTRARG";
-extern const isc::log::MessageID MSG_PRFINVARG = "PRFINVARG";
-extern const isc::log::MessageID MSG_PRFNOARG = "PRFNOARG";
-extern const isc::log::MessageID MSG_RDLOCMES = "RDLOCMES";
-extern const isc::log::MessageID MSG_UNRECDIR = "UNRECDIR";
+extern const isc::log::MessageID MSG_DUPLNS = "MSG_DUPLNS";
+extern const isc::log::MessageID MSG_DUPMSGID = "MSG_DUPMSGID";
+extern const isc::log::MessageID MSG_IDNOTFND = "MSG_IDNOTFND";
+extern const isc::log::MessageID MSG_INVMSGID = "MSG_INVMSGID";
+extern const isc::log::MessageID MSG_NOMSGID = "MSG_NOMSGID";
+extern const isc::log::MessageID MSG_NOMSGTXT = "MSG_NOMSGTXT";
+extern const isc::log::MessageID MSG_NSEXTRARG = "MSG_NSEXTRARG";
+extern const isc::log::MessageID MSG_NSINVARG = "MSG_NSINVARG";
+extern const isc::log::MessageID MSG_NSNOARG = "MSG_NSNOARG";
+extern const isc::log::MessageID MSG_OPENIN = "MSG_OPENIN";
+extern const isc::log::MessageID MSG_OPENOUT = "MSG_OPENOUT";
+extern const isc::log::MessageID MSG_PRFEXTRARG = "MSG_PRFEXTRARG";
+extern const isc::log::MessageID MSG_PRFINVARG = "MSG_PRFINVARG";
+extern const isc::log::MessageID MSG_RDLOCMES = "MSG_RDLOCMES";
+extern const isc::log::MessageID MSG_READERR = "MSG_READERR";
+extern const isc::log::MessageID MSG_UNRECDIR = "MSG_UNRECDIR";
+extern const isc::log::MessageID MSG_WRITERR = "MSG_WRITERR";
 
 } // namespace log
 } // namespace isc
@@ -31,23 +31,23 @@ extern const isc::log::MessageID MSG_UNRECDIR = "UNRECDIR";
 namespace {
 
 const char* values[] = {
-    "DUPLNS", "duplicate $NAMESPACE directive found",
-    "DUPLPRFX", "duplicate $PREFIX directive found",
-    "DUPMSGID", "duplicate message ID (%s) in compiled code",
-    "IDNOTFND", "could not replace message for '%s': no such message identification",
-    "MSGRDERR", "error reading from message file %s: %s",
-    "MSGWRTERR", "error writing to %s: %s",
-    "NOMSGTXT", "a line containing a message ID ('%s') and nothing else was found",
-    "NSEXTRARG", "$NAMESPACE directive has too many arguments",
-    "NSINVARG", "$NAMESPACE directive has an invalid argument ('%s')",
-    "NSNOARG", "no arguments were given to the $NAMESPACE directive",
-    "OPNMSGIN", "unable to open message file %s for input: %s",
-    "OPNMSGOUT", "unable to open %s for output: %s",
-    "PRFEXTRARG", "$PREFIX directive has too many arguments",
-    "PRFINVARG", "$PREFIX directive has an invalid argument ('%s')",
-    "PRFNOARG", "no arguments were given to the $PREFIX directive",
-    "RDLOCMES", "reading local message file %s",
-    "UNRECDIR", "unrecognised directive '%s'",
+    "MSG_DUPLNS", "line %1: duplicate $NAMESPACE directive found",
+    "MSG_DUPMSGID", "duplicate message ID (%1) in compiled code",
+    "MSG_IDNOTFND", "could not replace message text for '%1': no such message",
+    "MSG_INVMSGID", "line %1: invalid message identification '%2'",
+    "MSG_NOMSGID", "line %1: message definition line found without a message ID",
+    "MSG_NOMSGTXT", "line %1: line found containing a message ID ('%2') and no text",
+    "MSG_NSEXTRARG", "line %1: $NAMESPACE directive has too many arguments",
+    "MSG_NSINVARG", "line %1: $NAMESPACE directive has an invalid argument ('%2')",
+    "MSG_NSNOARG", "line %1: no arguments were given to the $NAMESPACE directive",
+    "MSG_OPENIN", "unable to open message file %1 for input: %2",
+    "MSG_OPENOUT", "unable to open %1 for output: %2",
+    "MSG_PRFEXTRARG", "line %1: $PREFIX directive has too many arguments",
+    "MSG_PRFINVARG", "line %1: $PREFIX directive has an invalid argument ('%2')",
+    "MSG_RDLOCMES", "reading local message file %1",
+    "MSG_READERR", "error reading from message file %1: %2",
+    "MSG_UNRECDIR", "line %1: unrecognised directive '%2'",
+    "MSG_WRITERR", "error writing to %1: %2",
     NULL
 };
 
diff --git a/src/lib/log/messagedef.h b/src/lib/log/messagedef.h
index eb8f4ea..79c8bab 100644
--- a/src/lib/log/messagedef.h
+++ b/src/lib/log/messagedef.h
@@ -1,4 +1,4 @@
-// File created from messagedef.mes on Mon Feb 14 11:07:45 2011
+// File created from messagedef.mes on Mon May  9 13:52:54 2011
 
 #ifndef __MESSAGEDEF_H
 #define __MESSAGEDEF_H
@@ -9,22 +9,22 @@ namespace isc {
 namespace log {
 
 extern const isc::log::MessageID MSG_DUPLNS;
-extern const isc::log::MessageID MSG_DUPLPRFX;
 extern const isc::log::MessageID MSG_DUPMSGID;
 extern const isc::log::MessageID MSG_IDNOTFND;
-extern const isc::log::MessageID MSG_MSGRDERR;
-extern const isc::log::MessageID MSG_MSGWRTERR;
+extern const isc::log::MessageID MSG_INVMSGID;
+extern const isc::log::MessageID MSG_NOMSGID;
 extern const isc::log::MessageID MSG_NOMSGTXT;
 extern const isc::log::MessageID MSG_NSEXTRARG;
 extern const isc::log::MessageID MSG_NSINVARG;
 extern const isc::log::MessageID MSG_NSNOARG;
-extern const isc::log::MessageID MSG_OPNMSGIN;
-extern const isc::log::MessageID MSG_OPNMSGOUT;
+extern const isc::log::MessageID MSG_OPENIN;
+extern const isc::log::MessageID MSG_OPENOUT;
 extern const isc::log::MessageID MSG_PRFEXTRARG;
 extern const isc::log::MessageID MSG_PRFINVARG;
-extern const isc::log::MessageID MSG_PRFNOARG;
 extern const isc::log::MessageID MSG_RDLOCMES;
+extern const isc::log::MessageID MSG_READERR;
 extern const isc::log::MessageID MSG_UNRECDIR;
+extern const isc::log::MessageID MSG_WRITERR;
 
 } // namespace log
 } // namespace isc
diff --git a/src/lib/log/messagedef.mes b/src/lib/log/messagedef.mes
index 3599388..51c04fa 100644
--- a/src/lib/log/messagedef.mes
+++ b/src/lib/log/messagedef.mes
@@ -12,108 +12,108 @@
 # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 # PERFORMANCE OF THIS SOFTWARE.
 
-$PREFIX MSG_
-$NAMESPACE isc::log
-
 # \brief Message Utility Message File
 #
-# This is the source of the set of messages generated by the message and logging
-# components.  The associated .h and .cc files are created by hand from this
-# file though and are not built during the build process; this is to avoid the
-# chicken-and-egg situation where we need the files to build the message
+# This is the source of the set of messages generated by the message and
+# logging components.  The associated .h and .cc files are created by hand from
+# this file though and are not built during the build process; this is to avoid
+# the chicken-and-egg situation where we need the files to build the message
 # compiler, yet we need the compiler to build the files.
 
-DUPMSGID  duplicate message ID (%s) in compiled code
-+ Indicative of a programming error, when it started up, BIND10 detected that
-+ the given message ID had been registered by one or more modules.  (All message
-+ IDs should be unique throughout BIND10.)  This has no impact on the operation
-+ of the server other that erroneous messages may be logged.  (When BIND10 loads
-+ the message IDs (and their associated text), if a duplicate ID is found it is
-+ discarded.  However, when the module that supplied the duplicate ID logs that
-+ particular message, the text supplied by the module that added the original
-+ ID will be output - something that may bear no relation to the condition being
-+ logged.
-
-DUPLNS    duplicate $NAMESPACE directive found
-+ When reading a message file, more than one $NAMESPACE directive was found.  In
-+ this version of the code, such a condition is regarded as an error and the
-+ read will be abandoned.
-
-DUPLPRFX    duplicate $PREFIX directive found
-+ When reading a message file, more than one $PREFIX directive was found.  In
-+ this version of the code, such a condition is regarded as an error and the
-+ read will be abandoned.
-
-IDNOTFND    could not replace message for '%s': no such message identification
-+ During start-up a local message file was read.  A line with the listed
-+ message identification was found in the file, but the identification is not
-+ one contained in the compiled-in message dictionary.  Either the message
-+ identification has been mis-spelled in the file, or the local file was used
-+ for an earlier version of the software and the message with that
-+ identification has been removed.
-+
-+ This message may appear a number of times in the file, once for every such
-+ unknown message identification.
-
-MSGRDERR    error reading from message file %s: %s
-+ The specified error was encountered reading from the named message file.
-
-MSGWRTERR   error writing to %s: %s
-+ The specified error was encountered by the message compiler when writing to
-+ the named output file.
-
-NSEXTRARG  $NAMESPACE directive has too many arguments
-+ The $NAMESPACE directive takes a single argument, a namespace in which all the
-+ generated symbol names are placed.  This error is generated when the
-+ compiler finds a $NAMESPACE directive with more than one argument.
-
-NSINVARG    $NAMESPACE directive has an invalid argument ('%s')
-+ The $NAMESPACE argument should be a valid C++ namespace.  The reader does a
-+ cursory check on its validity, checking that the characters in the namespace
-+ are correct.  The error is generated when the reader finds an invalid
-+ character. (Valid are alphanumeric characters, underscores and colons.)
-
-NOMSGTXT    a line containing a message ID ('%s') and nothing else was found
-+ Message definitions comprise lines starting with a message identification (a
-+ symbolic name for the message) and followed by the text of the message.  This
-+ error is generated when a line is found in the message file that contains just
-+ the message identification and no text.
-
-NSNOARG     no arguments were given to the $NAMESPACE directive
-+ The $NAMESPACE directive takes a single argument, a namespace in which all the
-+ generated symbol names are placed.  This error is generated when the
-+ compiler finds a $NAMESPACE directive with no arguments.
-
-OPNMSGIN     unable to open message file %s for input: %s
-+ The program was not able to open the specified input message file for the
-+ reason given.
-
-OPNMSGOUT   unable to open %s for output: %s
-+ The program was not able to open the specified output file for the reason
-+ given.
-
-PRFEXTRARG  $PREFIX directive has too many arguments
-+ The $PREFIX directive takes a single argument, a prefix to be added to the
-+ symbol names when a C++ .h file is created.  This error is generated when the
-+ compiler finds a $PREFIX directive with more than one argument.
-
-PRFINVARG   $PREFIX directive has an invalid argument ('%s')
-+ The $PREFIX argument is used in a symbol name in a C++ header file.  As such,
-+ it must adhere to restrictions on C++ symbol names (e.g. may only contain
-+ alphanumeric characters or underscores, and may nor start with a digit).  A
-+ $PREFIX directive was found with an argument (given in the message) that
-+ violates those restictions.
-
-PRFNOARG    no arguments were given to the $PREFIX directive
-+ The $PREFIX directive takes a single argument, a prefix to be added to the
-+ symbol names when a C++ .h file is created.  This error is generated when the
-+ compiler finds a $PREFIX directive with no arguments.
-
-RDLOCMES    reading local message file %s
-+ This is an informational message output by BIND10 when it starts to read a
-+ local message file.  (A local message file may replace the text of one of more
-+ messages; the ID of the message will not be changed though.)
-
-UNRECDIR    unrecognised directive '%s'
-+ A line starting with a dollar symbol was found, but the first word on the line
-+ (shown in the message) was not a recognised message compiler directive.
+$PREFIX MSG_
+$NAMESPACE isc::log
+
+% DUPMSGID      duplicate message ID (%1) in compiled code
+Indicative of a programming error, when it started up, BIND10 detected that
+the given message ID had been registered by one or more modules.  (All message
+IDs should be unique throughout BIND10.)  This has no impact on the operation
+of the server other that erroneous messages may be logged.  (When BIND10 loads
+the message IDs (and their associated text), if a duplicate ID is found it is
+discarded.  However, when the module that supplied the duplicate ID logs that
+particular message, the text supplied by the module that added the original
+ID will be output - something that may bear no relation to the condition being
+logged.
+
+% DUPLNS        line %1: duplicate $NAMESPACE directive found
+When reading a message file, more than one $NAMESPACE directive was found.  In
+this version of the code, such a condition is regarded as an error and the
+read will be abandoned.
+
+% IDNOTFND      could not replace message text for '%1': no such message
+During start-up a local message file was read.  A line with the listed
+message identification was found in the file, but the identification is not
+one contained in the compiled-in message dictionary.  Either the message
+identification has been mis-spelled in the file, or the local file was used
+for an earlier version of the software and the message with that
+identification has been removed.
+
+This message may appear a number of times in the file, once for every such
+unknown message identification.
+
+% INVMSGID      line %1: invalid message identification '%2'
+The concatenation of the prefix and the message identification is used as
+a symbol in the C++ module; as such it may only contain 
+
+% NOMSGID       line %1: message definition line found without a message ID
+Message definition lines are lines starting with a "%".  The rest of the line
+should comprise the message ID and text describing the message.  This error
+indicates the message compiler found a line in the message file comprising
+just the "%" and nothing else.
+
+% NOMSGTXT      line %1: line found containing a message ID ('%2') and no text
+Message definition lines are lines starting with a "%".  The rest of the line
+should comprise the message ID and text describing the message.  This error
+is generated when a line is found in the message file that contains the
+leading "%" and the message identification but no text.
+
+% NSEXTRARG     line %1: $NAMESPACE directive has too many arguments
+The $NAMESPACE directive takes a single argument, a namespace in which all the
+generated symbol names are placed.  This error is generated when the
+compiler finds a $NAMESPACE directive with more than one argument.
+
+% NSINVARG      line %1: $NAMESPACE directive has an invalid argument ('%2')
+The $NAMESPACE argument should be a valid C++ namespace.  The reader does a
+cursory check on its validity, checking that the characters in the namespace
+are correct.  The error is generated when the reader finds an invalid
+character. (Valid are alphanumeric characters, underscores and colons.)
+
+% NSNOARG       line %1: no arguments were given to the $NAMESPACE directive
+The $NAMESPACE directive takes a single argument, a namespace in which all the
+generated symbol names are placed.  This error is generated when the
+compiler finds a $NAMESPACE directive with no arguments.
+
+% OPENIN        unable to open message file %1 for input: %2
+The program was not able to open the specified input message file for the
+reason given.
+
+% OPENOUT       unable to open %1 for output: %2
+The program was not able to open the specified output file for the reason
+given.
+
+% PRFEXTRARG    line %1: $PREFIX directive has too many arguments
+The $PREFIX directive takes a single argument, a prefix to be added to the
+symbol names when a C++ .h file is created.  This error is generated when the
+compiler finds a $PREFIX directive with more than one argument.
+
+% PRFINVARG     line %1: $PREFIX directive has an invalid argument ('%2')
+The $PREFIX argument is used in a symbol name in a C++ header file.  As such,
+it must adhere to restrictions on C++ symbol names (e.g. may only contain
+alphanumeric characters or underscores, and may nor start with a digit).
+A $PREFIX directive was found with an argument (given in the message) that
+violates those restictions.
+
+% RDLOCMES      reading local message file %1
+This is an informational message output by BIND10 when it starts to read a
+local message file.  (A local message file may replace the text of one of more
+messages; the ID of the message will not be changed though.)
+
+% READERR       error reading from message file %1: %2
+The specified error was encountered reading from the named message file.
+
+% WRITERR       error writing to %1: %2
+The specified error was encountered by the message compiler when writing to
+the named output file.
+
+% UNRECDIR      line %1: unrecognised directive '%2'
+A line starting with a dollar symbol was found, but the first word on the line
+(shown in the message) was not a recognised message compiler directive.
diff --git a/src/lib/log/tests/Makefile.am b/src/lib/log/tests/Makefile.am
index b9fe150..46065e8 100644
--- a/src/lib/log/tests/Makefile.am
+++ b/src/lib/log/tests/Makefile.am
@@ -22,6 +22,7 @@ run_unittests_SOURCES += message_reader_unittest.cc
 run_unittests_SOURCES += message_initializer_unittest.cc
 run_unittests_SOURCES += message_initializer_unittest_2.cc
 run_unittests_SOURCES += run_unittests.cc
+run_unittests_SOURCES += log_formatter_unittest.cc
 
 run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
 run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)
diff --git a/src/lib/log/tests/log_formatter_unittest.cc b/src/lib/log/tests/log_formatter_unittest.cc
new file mode 100644
index 0000000..b67831a
--- /dev/null
+++ b/src/lib/log/tests/log_formatter_unittest.cc
@@ -0,0 +1,125 @@
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <gtest/gtest.h>
+#include <log/log_formatter.h>
+
+#include <vector>
+#include <string>
+
+using namespace std;
+
+namespace {
+
+class FormatterTest : public ::testing::Test {
+protected:
+    typedef pair<const char*, string> Output;
+    typedef isc::log::Formatter<FormatterTest> Formatter;
+    vector<Output> outputs;
+public:
+    void output(const char* prefix, const string& message) {
+        outputs.push_back(Output(prefix, message));
+    }
+    // Just shortcut for new string
+    string* s(const char* text) {
+        return (new string(text));
+    }
+};
+
+// Create an inactive formatter and check it doesn't produce any output
+TEST_F(FormatterTest, inactive) {
+    Formatter();
+    EXPECT_EQ(0, outputs.size());
+}
+
+// Create an active formatter and check it produces output. Does no arg
+// substitution yet
+TEST_F(FormatterTest, active) {
+    Formatter("TEST", s("Text of message"), this);
+    ASSERT_EQ(1, outputs.size());
+    EXPECT_STREQ("TEST", outputs[0].first);
+    EXPECT_EQ("Text of message", outputs[0].second);
+}
+
+// No output even when we have an arg on the inactive formatter
+TEST_F(FormatterTest, inactiveArg) {
+    Formatter().arg("Hello");
+    EXPECT_EQ(0, outputs.size());
+}
+
+// Create an active formatter and replace a placeholder with string
+TEST_F(FormatterTest, stringArg) {
+    {
+        SCOPED_TRACE("C++ string");
+        Formatter("TEST", s("Hello %1"), this).arg(string("World"));
+        ASSERT_EQ(1, outputs.size());
+        EXPECT_STREQ("TEST", outputs[0].first);
+        EXPECT_EQ("Hello World", outputs[0].second);
+    }
+    {
+        SCOPED_TRACE("C++ string");
+        Formatter("TEST", s("Hello %1"), this).arg(string("Internet"));
+        ASSERT_EQ(2, outputs.size());
+        EXPECT_STREQ("TEST", outputs[1].first);
+        EXPECT_EQ("Hello Internet", outputs[1].second);
+    }
+}
+
+// Can convert to string
+TEST_F(FormatterTest, intArg) {
+    Formatter("TEST", s("The answer is %1"), this).arg(42);
+    ASSERT_EQ(1, outputs.size());
+    EXPECT_STREQ("TEST", outputs[0].first);
+    EXPECT_EQ("The answer is 42", outputs[0].second);
+}
+
+// Can use multiple arguments at different places
+TEST_F(FormatterTest, multiArg) {
+    Formatter("TEST", s("The %2 are %1"), this).arg("switched").
+        arg("arguments");
+    ASSERT_EQ(1, outputs.size());
+    EXPECT_STREQ("TEST", outputs[0].first);
+    EXPECT_EQ("The arguments are switched", outputs[0].second);
+}
+
+// Can survive and complains if placeholder is missing
+TEST_F(FormatterTest, missingPlace) {
+    EXPECT_NO_THROW(Formatter("TEST", s("Missing the first %2"), this).
+                    arg("missing").arg("argument"));
+    ASSERT_EQ(1, outputs.size());
+    EXPECT_STREQ("TEST", outputs[0].first);
+    EXPECT_EQ("Missing the first argument "
+              "@@Missing placeholder %1 for 'missing'@@", outputs[0].second);
+}
+
+// Can replace multiple placeholders
+TEST_F(FormatterTest, multiPlaceholder) {
+    Formatter("TEST", s("The %1 is the %1"), this).
+        arg("first rule of tautology club");
+    ASSERT_EQ(1, outputs.size());
+    EXPECT_STREQ("TEST", outputs[0].first);
+    EXPECT_EQ("The first rule of tautology club is "
+              "the first rule of tautology club", outputs[0].second);
+}
+
+// Test we can cope with replacement containing the placeholder
+TEST_F(FormatterTest, noRecurse) {
+    // If we recurse, this will probably eat all the memory and crash
+    Formatter("TEST", s("%1"), this).arg("%1 %1");
+    ASSERT_EQ(1, outputs.size());
+    EXPECT_STREQ("TEST", outputs[0].first);
+    EXPECT_EQ("%1 %1", outputs[0].second);
+}
+
+}
diff --git a/src/lib/log/tests/logger_support_test.cc b/src/lib/log/tests/logger_support_test.cc
index 4d8863e..0a2338b 100644
--- a/src/lib/log/tests/logger_support_test.cc
+++ b/src/lib/log/tests/logger_support_test.cc
@@ -23,6 +23,7 @@
 #include <iostream>
 
 #include <log/logger.h>
+#include <log/macros.h>
 #include <log/logger_support.h>
 #include <log/root_logger_name.h>
 
@@ -92,13 +93,14 @@ int main(int argc, char** argv) {
     initLogger("alpha", severity, dbglevel, localfile);
 
     // Log a few messages
-    logger_ex.fatal(MSG_MSGWRTERR, "test1", "42");
-    logger_ex.error(MSG_UNRECDIR, "false");
-    logger_dlm.warn(MSG_MSGRDERR, "a.txt", "dummy test");
-    logger_dlm.info(MSG_OPNMSGIN, "example.msg", "dummy test");
-    logger_ex.debug(0, MSG_UNRECDIR, "[abc]");
-    logger_ex.debug(24, MSG_UNRECDIR, "[24]");
-    logger_ex.debug(25, MSG_UNRECDIR, "[25]");
-    logger_ex.debug(26, MSG_UNRECDIR, "[26]");
+    LOG_FATAL(logger_ex, MSG_WRITERR).arg("test1").arg("42");
+    LOG_ERROR(logger_ex, MSG_RDLOCMES).arg("dummy/file");
+    LOG_WARN(logger_dlm, MSG_READERR).arg("a.txt").arg("dummy reason");
+    LOG_INFO(logger_dlm, MSG_OPENIN).arg("example.msg").arg("dummy reason");
+    LOG_DEBUG(logger_ex, 0, MSG_RDLOCMES).arg("dummy/0");
+    LOG_DEBUG(logger_ex, 24, MSG_RDLOCMES).arg("dummy/24");
+    LOG_DEBUG(logger_ex, 25, MSG_RDLOCMES).arg("dummy/25");
+    LOG_DEBUG(logger_ex, 26, MSG_RDLOCMES).arg("dummy/26");
+
     return (0);
 }
diff --git a/src/lib/log/tests/message_dictionary_unittest.cc b/src/lib/log/tests/message_dictionary_unittest.cc
index a92585c..ba33820 100644
--- a/src/lib/log/tests/message_dictionary_unittest.cc
+++ b/src/lib/log/tests/message_dictionary_unittest.cc
@@ -29,7 +29,7 @@ using namespace std;
 // and the latter should be present.
 
 static const char* values[] = {
-    "DUPLNS", "duplicate $NAMESPACE directive found",
+    "MSG_DUPLNS", "duplicate $NAMESPACE directive found",
     "NEWSYM", "new symbol added",
     NULL
 };
@@ -190,7 +190,7 @@ TEST_F(MessageDictionaryTest, GlobalTest) {
 TEST_F(MessageDictionaryTest, GlobalLoadTest) {
     vector<string>& duplicates = MessageInitializer::getDuplicates();
     ASSERT_EQ(1, duplicates.size());
-    EXPECT_EQ(string("DUPLNS"), duplicates[0]);
+    EXPECT_EQ(string("MSG_DUPLNS"), duplicates[0]);
 
     string text = MessageDictionary::globalDictionary().getText("NEWSYM");
     EXPECT_EQ(string("new symbol added"), text);
diff --git a/src/lib/log/tests/message_reader_unittest.cc b/src/lib/log/tests/message_reader_unittest.cc
index 36288f2..7b3ba5f 100644
--- a/src/lib/log/tests/message_reader_unittest.cc
+++ b/src/lib/log/tests/message_reader_unittest.cc
@@ -68,8 +68,8 @@ TEST_F(MessageReaderTest, BlanksAndComments) {
     EXPECT_NO_THROW(reader_.processLine(" \n "));
     EXPECT_NO_THROW(reader_.processLine("# This is a comment"));
     EXPECT_NO_THROW(reader_.processLine("\t\t # Another comment"));
-    EXPECT_NO_THROW(reader_.processLine("  + A description line"));
-    EXPECT_NO_THROW(reader_.processLine("#+ A comment"));
+    EXPECT_NO_THROW(reader_.processLine("  A description line"));
+    EXPECT_NO_THROW(reader_.processLine("# A comment"));
     EXPECT_NO_THROW(reader_.processLine("  +# A description line"));
 
     // ... and (b) nothing gets added to either the map or the not-added section.
@@ -97,6 +97,15 @@ processLineException(MessageReader& reader, const char* what,
     }
 }
 
+// Check that it recognises invalid directives
+
+TEST_F(MessageReaderTest, InvalidDirectives) {
+
+    // Check that a "$" with nothing else generates an error
+    processLineException(reader_, "$", MSG_UNRECDIR);
+    processLineException(reader_, "$xyz", MSG_UNRECDIR);
+}
+
 // Check that it can parse a prefix
 
 TEST_F(MessageReaderTest, Prefix) {
@@ -104,8 +113,8 @@ TEST_F(MessageReaderTest, Prefix) {
     // Check that no $PREFIX is present
     EXPECT_EQ(string(""), reader_.getPrefix());
 
-    // Check that a $PREFIX directive with no argument generates an error.
-    processLineException(reader_, "$PREFIX", MSG_PRFNOARG);
+    // Check that a $PREFIX directive with no argument is OK
+    EXPECT_NO_THROW(reader_.processLine("$PREFIX"));
 
     // Check a $PREFIX with multiple arguments is invalid
     processLineException(reader_, "$prefix A B", MSG_PRFEXTRARG);
@@ -118,17 +127,19 @@ TEST_F(MessageReaderTest, Prefix) {
 
     // A valid prefix should be accepted
     EXPECT_NO_THROW(reader_.processLine("$PREFIX   dlm__"));
-    EXPECT_EQ(string("DLM__"), reader_.getPrefix());
+    EXPECT_EQ(string("dlm__"), reader_.getPrefix());
 
     // And check that the parser fails on invalid prefixes...
     processLineException(reader_, "$prefix 1ABC", MSG_PRFINVARG);
 
-    // ... and rejects another valid one
-    processLineException(reader_, "$PREFIX ABC", MSG_DUPLPRFX);
-
     // Check that we can clear the prefix as well
     reader_.clearPrefix();
     EXPECT_EQ(string(""), reader_.getPrefix());
+
+    EXPECT_NO_THROW(reader_.processLine("$PREFIX   dlm__"));
+    EXPECT_EQ(string("dlm__"), reader_.getPrefix());
+    EXPECT_NO_THROW(reader_.processLine("$PREFIX"));
+    EXPECT_EQ(string(""), reader_.getPrefix());
 }
 
 // Check that it can parse a namespace
@@ -173,8 +184,8 @@ TEST_F(MessageReaderTest, Namespace) {
 TEST_F(MessageReaderTest, ValidMessageAddDefault) {
 
     // Add a couple of valid messages
-    reader_.processLine("GLOBAL1\t\tthis is message global one\n");
-    reader_.processLine("GLOBAL2 this is message global two");
+    reader_.processLine("% GLOBAL1\t\tthis is message global one\n");
+    reader_.processLine("%GLOBAL2 this is message global two");
 
     // ... and check them
     EXPECT_EQ(string("this is message global one"),
@@ -191,9 +202,9 @@ TEST_F(MessageReaderTest, ValidMessageAddDefault) {
 TEST_F(MessageReaderTest, ValidMessageAdd) {
 
     // Add a couple of valid messages
-    reader_.processLine("GLOBAL1\t\tthis is message global one\n",
+    reader_.processLine("%GLOBAL1\t\tthis is message global one\n",
         MessageReader::ADD);
-    reader_.processLine("GLOBAL2 this is message global two",
+    reader_.processLine("% GLOBAL2 this is message global two",
         MessageReader::ADD);
 
     // ... and check them
@@ -214,9 +225,9 @@ TEST_F(MessageReaderTest, ValidMessageReplace) {
     dictionary_->add("GLOBAL2", "original global2 message");
 
     // Replace a couple of valid messages
-    reader_.processLine("GLOBAL1\t\tthis is message global one\n",
+    reader_.processLine("% GLOBAL1\t\tthis is message global one\n",
         MessageReader::REPLACE);
-    reader_.processLine("GLOBAL2 this is message global two",
+    reader_.processLine("% GLOBAL2 this is message global two",
         MessageReader::REPLACE);
 
     // ... and check them
@@ -237,14 +248,14 @@ TEST_F(MessageReaderTest, ValidMessageReplace) {
 TEST_F(MessageReaderTest, Overflows) {
 
     // Add a couple of valid messages
-    reader_.processLine("GLOBAL1\t\tthis is message global one\n");
-    reader_.processLine("GLOBAL2 this is message global two");
+    reader_.processLine("% GLOBAL1\t\tthis is message global one\n");
+    reader_.processLine("% GLOBAL2 this is message global two");
 
     // Add a duplicate in ADD mode.
-    reader_.processLine("GLOBAL1\t\tthis is a replacement for global one");
+    reader_.processLine("% GLOBAL1\t\tthis is a replacement for global one");
 
     // Replace a non-existent one in REPLACE mode
-    reader_.processLine("LOCAL\t\tthis is a new message",
+    reader_.processLine("% LOCAL\t\tthis is a new message",
         MessageReader::REPLACE);
 
     // Check what is in the dictionary.
diff --git a/src/lib/log/tests/run_time_init_test.sh.in b/src/lib/log/tests/run_time_init_test.sh.in
index e2bdf6f..e48a781 100755
--- a/src/lib/log/tests/run_time_init_test.sh.in
+++ b/src/lib/log/tests/run_time_init_test.sh.in
@@ -29,48 +29,49 @@ passfail() {
 # Create the local message file for testing
 
 cat > $localmes << .
-NOTHERE     this message is not in the global dictionary
-MSGRDERR    replacement read error, parameters: '%s' and '%s'
-UNRECDIR    replacement unrecognised directive message, parameter is '%s'
+\$PREFIX MSG_
+% NOTHERE     this message is not in the global dictionary
+% READERR     replacement read error, parameters: '%1' and '%2'
+% RDLOCMES    replacement read local message file, parameter is '%1'
 .
 
 echo -n "1. runInitTest default parameters: "
 cat > $tempfile << .
-FATAL [alpha.example] MSGWRTERR, error writing to test1: 42
-ERROR [alpha.example] UNRECDIR, unrecognised directive 'false'
-WARN  [alpha.dlm] MSGRDERR, error reading from message file a.txt: dummy test
-INFO  [alpha.dlm] OPNMSGIN, unable to open message file example.msg for input: dummy test
+FATAL [alpha.example] MSG_WRITERR, error writing to test1: 42
+ERROR [alpha.example] MSG_RDLOCMES, reading local message file dummy/file
+WARN  [alpha.dlm] MSG_READERR, error reading from message file a.txt: dummy reason
+INFO  [alpha.dlm] MSG_OPENIN, unable to open message file example.msg for input: dummy reason
 .
 ./logger_support_test | cut -d' ' -f3- | diff $tempfile -
 passfail $?
 
 echo -n "2. Severity filter: "
 cat > $tempfile << .
-FATAL [alpha.example] MSGWRTERR, error writing to test1: 42
-ERROR [alpha.example] UNRECDIR, unrecognised directive 'false'
+FATAL [alpha.example] MSG_WRITERR, error writing to test1: 42
+ERROR [alpha.example] MSG_RDLOCMES, reading local message file dummy/file
 .
 ./logger_support_test -s error | cut -d' ' -f3- | diff $tempfile -
 passfail $?
 
 echo -n "3. Debug level: "
 cat > $tempfile << .
-FATAL [alpha.example] MSGWRTERR, error writing to test1: 42
-ERROR [alpha.example] UNRECDIR, unrecognised directive 'false'
-WARN  [alpha.dlm] MSGRDERR, error reading from message file a.txt: dummy test
-INFO  [alpha.dlm] OPNMSGIN, unable to open message file example.msg for input: dummy test
-DEBUG [alpha.example] UNRECDIR, unrecognised directive '[abc]'
-DEBUG [alpha.example] UNRECDIR, unrecognised directive '[24]'
-DEBUG [alpha.example] UNRECDIR, unrecognised directive '[25]'
+FATAL [alpha.example] MSG_WRITERR, error writing to test1: 42
+ERROR [alpha.example] MSG_RDLOCMES, reading local message file dummy/file
+WARN  [alpha.dlm] MSG_READERR, error reading from message file a.txt: dummy reason
+INFO  [alpha.dlm] MSG_OPENIN, unable to open message file example.msg for input: dummy reason
+DEBUG [alpha.example] MSG_RDLOCMES, reading local message file dummy/0
+DEBUG [alpha.example] MSG_RDLOCMES, reading local message file dummy/24
+DEBUG [alpha.example] MSG_RDLOCMES, reading local message file dummy/25
 .
 ./logger_support_test -s debug -d 25 | cut -d' ' -f3- | diff $tempfile -
 passfail $?
 
 echo -n "4. Local message replacement: "
 cat > $tempfile << .
-WARN  [alpha.log] IDNOTFND, could not replace message for 'NOTHERE': no such message identification
-FATAL [alpha.example] MSGWRTERR, error writing to test1: 42
-ERROR [alpha.example] UNRECDIR, replacement unrecognised directive message, parameter is 'false'
-WARN  [alpha.dlm] MSGRDERR, replacement read error, parameters: 'a.txt' and 'dummy test'
+WARN  [alpha.log] MSG_IDNOTFND, could not replace message text for 'MSG_NOTHERE': no such message
+FATAL [alpha.example] MSG_WRITERR, error writing to test1: 42
+ERROR [alpha.example] MSG_RDLOCMES, replacement read local message file, parameter is 'dummy/file'
+WARN  [alpha.dlm] MSG_READERR, replacement read error, parameters: 'a.txt' and 'dummy reason'
 .
 ./logger_support_test -s warn $localmes | cut -d' ' -f3- | diff $tempfile -
 passfail $?
diff --git a/src/lib/nsas/Makefile.am b/src/lib/nsas/Makefile.am
index 5f05f1b..3ecbca7 100644
--- a/src/lib/nsas/Makefile.am
+++ b/src/lib/nsas/Makefile.am
@@ -4,23 +4,39 @@ AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
 AM_CPPFLAGS += $(BOOST_INCLUDES) $(MULTITHREADING_FLAG)
 AM_CPPFLAGS += -I$(top_srcdir)/src/lib/dns -I$(top_builddir)/src/lib/dns
 AM_CPPFLAGS += -I$(top_srcdir)/src/lib/util -I$(top_builddir)/src/lib/util
+AM_CPPFLAGS += -I$(top_srcdir)/src/lib/log -I$(top_builddir)/src/lib/log
 AM_CPPFLAGS += -I$(top_srcdir)/src/lib/nsas -I$(top_builddir)/src/lib/nsas
 AM_CPPFLAGS += $(SQLITE_CFLAGS)
 AM_CXXFLAGS = $(B10_CXXFLAGS)
 
-# Some versions of GCC warn about some versions of Boost regarding
-# missing initializer for members in its posix_time.
+# Some versions of GCC warn about some versions of Boost regarding missing
+# initializer for members in its posix_time.
 # https://svn.boost.org/trac/boost/ticket/3477
 # But older GCC compilers don't have the flag.
 AM_CXXFLAGS += $(WARNING_NO_MISSING_FIELD_INITIALIZERS_CFLAG)
 
-if USE_CLANGPP
 # clang++ complains about unused function parameters in some boost header
 # files.
+if USE_CLANGPP
 AM_CXXFLAGS += -Wno-unused-parameter
 endif
 
+# Define rule to build logging source files from message file
+nsasdef.h nsasdef.cc: nsasdef.mes
+	$(top_builddir)/src/lib/log/compiler/message $(top_srcdir)/src/lib/nsas/nsasdef.mes
+
+# What is being built.
 lib_LTLIBRARIES = libnsas.la
+
+# Tell Automake that the nsasdef.{cc,h} source files are created in the build
+# process, so it must create these before doing anything else.  Although they
+# are a dependency of the library (so will be created from the message file
+# anyway), there is no guarantee as to exactly _when_ in the build they will be
+# created.  As the .h file is included in other sources file (so must be
+# present when they are compiled), the safest option is to create it first.
+BUILT_SOURCES = nsasdef.h nsasdef.cc
+
+# Library sources. The generated files will not be in the distribution.
 libnsas_la_SOURCES  = address_entry.h address_entry.cc
 libnsas_la_SOURCES += asiolink.h
 libnsas_la_SOURCES += hash.cc hash.h
@@ -32,9 +48,16 @@ libnsas_la_SOURCES += nameserver_address.h nameserver_address.cc
 libnsas_la_SOURCES += nameserver_entry.cc nameserver_entry.h
 libnsas_la_SOURCES += nsas_entry_compare.h
 libnsas_la_SOURCES += nsas_entry.h nsas_types.h
+libnsas_la_SOURCES += nsas_log.cc nsas_log.h
 libnsas_la_SOURCES += zone_entry.cc zone_entry.h
 libnsas_la_SOURCES += fetchable.h
 libnsas_la_SOURCES += address_request_callback.h
 libnsas_la_SOURCES += glue_hints.h glue_hints.cc
 
-CLEANFILES = *.gcno *.gcda
+nodist_libnsas_la_SOURCES  = nsasdef.h nsasdef.cc
+
+# The message file should be in the distribution.
+EXTRA_DIST = nsasdef.mes
+
+# Make sure that the generated files are got rid of in a clean operation
+CLEANFILES = *.gcno *.gcda nsasdef.h nsasdef.cc
diff --git a/src/lib/nsas/nameserver_address_store.cc b/src/lib/nsas/nameserver_address_store.cc
index 3cef38d..ac55409 100644
--- a/src/lib/nsas/nameserver_address_store.cc
+++ b/src/lib/nsas/nameserver_address_store.cc
@@ -22,6 +22,7 @@
 #include <dns/rdataclass.h>
 #include <util/locks.h>
 #include <util/lru_list.h>
+#include <log/logger.h>
 
 #include "hash_table.h"
 #include "hash_deleter.h"
@@ -31,6 +32,8 @@
 #include "zone_entry.h"
 #include "glue_hints.h"
 #include "address_request_callback.h"
+#include "nsasdef.h"
+#include "nsas_log.h"
 
 using namespace isc::dns;
 using namespace std;
@@ -84,6 +87,8 @@ NameserverAddressStore::lookup(const string& zone, const RRClass& class_code,
     boost::shared_ptr<AddressRequestCallback> callback, AddressFamily family,
     const GlueHints& glue_hints)
 {
+    LOG_DEBUG(nsas_logger, NSAS_DBG_TRACE, NSAS_LOOKUPZONE).arg(zone);
+
     pair<bool, boost::shared_ptr<ZoneEntry> > zone_obj(
         zone_hash_->getOrAdd(HashKey(zone, class_code),
                              boost::bind(newZone, resolver_, &zone, &class_code,
@@ -103,6 +108,8 @@ NameserverAddressStore::cancel(const string& zone,
     const boost::shared_ptr<AddressRequestCallback>& callback,
     AddressFamily family)
 {
+    LOG_DEBUG(nsas_logger, NSAS_DBG_TRACE, NSAS_LOOKUPCANCEL).arg(zone);
+
     boost::shared_ptr<ZoneEntry> entry(zone_hash_->get(HashKey(zone,
                                                                class_code)));
     if (entry) {
diff --git a/src/lib/nsas/nameserver_address_store.h b/src/lib/nsas/nameserver_address_store.h
index 148052d..87845c9 100644
--- a/src/lib/nsas/nameserver_address_store.h
+++ b/src/lib/nsas/nameserver_address_store.h
@@ -38,7 +38,6 @@ template<class T> class LruList;
 
 namespace nsas {
 
-class ResolverInterface;
 template<class T> class HashTable;
 class ZoneEntry;
 class NameserverEntry;
diff --git a/src/lib/nsas/nameserver_entry.cc b/src/lib/nsas/nameserver_entry.cc
index 4035f79..65b2ec2 100644
--- a/src/lib/nsas/nameserver_entry.cc
+++ b/src/lib/nsas/nameserver_entry.cc
@@ -40,6 +40,7 @@
 #include "address_entry.h"
 #include "nameserver_address.h"
 #include "nameserver_entry.h"
+#include "nsas_log.h"
 
 using namespace isc::asiolink;
 using namespace isc::nsas;
@@ -178,6 +179,9 @@ NameserverEntry::updateAddressRTTAtIndex(uint32_t rtt, size_t index,
         new_rtt = 1;
     }
     addresses_[family][index].setRTT(new_rtt);
+    LOG_DEBUG(nsas_logger, NSAS_DBG_RTT, NSAS_SETRTT)
+              .arg(addresses_[family][index].getAddress().toText())
+              .arg(old_rtt).arg(new_rtt);
 }
 
 void
@@ -203,7 +207,7 @@ NameserverEntry::setAddressUnreachable(const IOAddress& address) {
  * \short A callback into the resolver.
  *
  * Whenever we ask the resolver something, this is created and the answer is
- * fed back trough this. It holds a shared pointer to the entry so it is not
+ * fed back through this. It holds a shared pointer to the entry so it is not
  * destroyed too soon.
  */
 class NameserverEntry::ResolverCallback :
@@ -230,6 +234,7 @@ class NameserverEntry::ResolverCallback :
             if (!response_message ||
                 response_message->getRcode() != isc::dns::Rcode::NOERROR() ||
                 response_message->getRRCount(isc::dns::Message::SECTION_ANSWER) == 0) {
+                LOG_ERROR(nsas_logger, NSAS_INVRESPSTR).arg(entry_->getName());
                 failureInternal(lock);
                 return;
             }
@@ -243,7 +248,12 @@ class NameserverEntry::ResolverCallback :
             if (response->getType() != type_ ||
                 response->getClass() != RRClass(entry_->getClass()))
             {
-                // TODO Log we got answer of different type
+                // Invalid response type or class
+                LOG_ERROR(nsas_logger, NSAS_INVRESPTC)
+                          .arg(entry_->getName()).arg(type_)
+                          .arg(entry_->getClass()).arg(response->getType())
+                          .arg(response->getClass());
+
                 failureInternal(lock);
                 return;
             }
@@ -264,8 +274,10 @@ class NameserverEntry::ResolverCallback :
                     }
                 }
                 // If we found it, use it. If not, create a new one.
-                entries.push_back(found ? *found : AddressEntry(IOAddress(
-                    i->getCurrent().toText()), 1));
+                entries.push_back(found ? *found : AddressEntry(
+                                                   IOAddress(address), 1));
+                LOG_DEBUG(nsas_logger, NSAS_DBG_RESULTS, NSAS_NSLKUPSUCC)
+                          .arg(address).arg(entry_->getName());
             }
 
             // We no longer need the previous set of addresses, we have
@@ -310,6 +322,8 @@ class NameserverEntry::ResolverCallback :
          * So mark the current address family as unreachable.
          */
         virtual void failure() {
+            LOG_DEBUG(nsas_logger, NSAS_DBG_RESULTS, NSAS_NSLKUPFAIL)
+                      .arg(type_).arg(entry_->getName());
             Lock lock(entry_->mutex_);
             failureInternal(lock);
         }
@@ -422,6 +436,8 @@ NameserverEntry::askIP(isc::resolve::ResolverInterface* resolver,
         // Ask for both types of addresses
         // We are unlocked here, as the callback from that might want to lock
         lock.unlock();
+
+        LOG_DEBUG(nsas_logger, NSAS_DBG_TRACE, NSAS_NSADDR).arg(getName());
         askIP(resolver, RRType::A(), V4_ONLY);
         askIP(resolver, RRType::AAAA(), V6_ONLY);
         // Make sure we end the routine when we are not locked
diff --git a/src/lib/nsas/nsas_log.cc b/src/lib/nsas/nsas_log.cc
new file mode 100644
index 0000000..931b131
--- /dev/null
+++ b/src/lib/nsas/nsas_log.cc
@@ -0,0 +1,26 @@
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+/// Defines the logger used by the NSAS
+
+#include "nsas/nsas_log.h"
+
+namespace isc {
+namespace nsas {
+
+isc::log::Logger nsas_logger("nsas");
+
+} // namespace nsas
+} // namespace isc
+
diff --git a/src/lib/nsas/nsas_log.h b/src/lib/nsas/nsas_log.h
new file mode 100644
index 0000000..9631988
--- /dev/null
+++ b/src/lib/nsas/nsas_log.h
@@ -0,0 +1,53 @@
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#ifndef __NSAS_LOG__H
+#define __NSAS_LOG__H
+
+#include <log/macros.h>
+#include "nsasdef.h"
+
+namespace isc {
+namespace nsas {
+
+/// \brief NSAS Logging
+///
+/// Defines the levels used to output debug messages in the NSAS.  Note that
+/// higher numbers equate to more verbose (and detailed) output.
+
+// The first level traces normal operations - asking the NSAS for an address,
+// and cancelling a lookup.  It also records when the NSAS calls back to the
+// resolver to resolve something.
+const int NSAS_DBG_TRACE = 10;
+
+// The next level extends the normal operations and records the results of the
+// lookups.
+const int NSAS_DBG_RESULTS = 20;
+
+// Additional information on the usage of the names - the RTT values obtained
+// when queries were done.
+const int NSAS_DBG_RTT = 30;
+
+
+/// \brief NSAS Logger
+///
+/// Define the logger used to log messages.  We could define it in multiple
+/// modules, but defining in a single module and linking to it saves time and
+/// space.
+extern isc::log::Logger nsas_logger;    // isc::nsas::logger is the NSAS logger
+
+} // namespace nsas
+} // namespace isc
+
+#endif // __NSAS_LOG__H
diff --git a/src/lib/nsas/nsasdef.mes b/src/lib/nsas/nsasdef.mes
new file mode 100644
index 0000000..0f32d09
--- /dev/null
+++ b/src/lib/nsas/nsasdef.mes
@@ -0,0 +1,61 @@
+# Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+# PERFORMANCE OF THIS SOFTWARE.
+
+$PREFIX NSAS_
+$NAMESPACE isc::nsas
+
+% INVRESPSTR      queried for %1 but got invalid response
+This message indicates an internal error in the nameserver address store
+component (NSAS) of the resolver.  The NSAS made a query for a RR for the
+specified nameserver but received an invalid response.  Either the success
+function was called without a DNS message or the message was invalid on some
+way. (In the latter case, the error should have been picked up elsewhere in
+the processing logic, hence the raising of the error here.)
+
+% INVRESPTC       queried for %1 RR of type/class %2/%3, received response %4/%5
+This message indicates an internal error in the nameserver address store
+component (NSAS) of the resolver.  The NSAS made a query for the given RR
+type and class, but instead received an answer with the given type and class.
+
+% LOOKUPCANCEL    lookup for zone %1 has been cancelled
+A debug message, this is output when a NSAS (nameserver address store -
+part of the resolver) lookup for a zone has been cancelled.
+
+% LOOKUPZONE      searching NSAS for nameservers for zone %1
+A debug message, this is output when a call is made to the nameserver address
+store (part of the resolver) to obtain the nameservers for the specified zone.
+
+% NSADDR          asking resolver to obtain A and AAAA records for %1
+A debug message, the NSAS (nameserver address store - part of the resolver) is
+making a callback into the resolver to retrieve the address records for the
+specified nameserver.
+
+% NSLKUPFAIL      failed to lookup any %1 for %2
+A debug message, the NSAS (nameserver address store - part of the resolver)
+has been unable to retrieve the specified resource record for the specified
+nameserver.  This is not necessarily a problem - the nameserver may be
+unreachable, in which case the NSAS will try other nameservers in the zone.
+
+% NSLKUPSUCC      found address %1 for %2
+A debug message, the NSAS (nameserver address store - part of the resolver)
+has retrieved the given address for the specified nameserver through an
+external query.
+
+% SETRTT          reporting RTT for %1 as %2; new value is now %3
+A NSAS (nameserver address store - part of the resolver) debug message
+reporting the round-trip time (RTT) for a query made to the specified
+nameserver.  The RTT has been updated using the value given and the new RTT is
+displayed.  (The RTT is subject to a calculation that damps out sudden
+changes.  As a result, the new RTT is not necessarily equal to the RTT
+reported.)
diff --git a/src/lib/nsas/tests/Makefile.am b/src/lib/nsas/tests/Makefile.am
index 56f36d1..e9235ba 100644
--- a/src/lib/nsas/tests/Makefile.am
+++ b/src/lib/nsas/tests/Makefile.am
@@ -53,6 +53,7 @@ endif
 
 run_unittests_LDADD += $(top_builddir)/src/lib/nsas/libnsas.la
 run_unittests_LDADD += $(top_builddir)/src/lib/util/libutil.la
+run_unittests_LDADD += $(top_builddir)/src/lib/log/liblog.la
 run_unittests_LDADD += $(top_builddir)/src/lib/dns/libdns++.la
 run_unittests_LDADD += $(top_builddir)/src/lib/asiolink/libasiolink.la
 run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
diff --git a/src/lib/nsas/tests/nameserver_address_unittest.cc b/src/lib/nsas/tests/nameserver_address_unittest.cc
index e3bc5de..1b211e9 100644
--- a/src/lib/nsas/tests/nameserver_address_unittest.cc
+++ b/src/lib/nsas/tests/nameserver_address_unittest.cc
@@ -51,7 +51,8 @@ public:
         ns_.reset(new NameserverEntry(name_.toText(), RRClass::IN()));
         ns_->askIP(resolver_.get(), boost::shared_ptr<Callback>(new Callback), ANY_OK);
         resolver_->asksIPs(name_, 0, 1);
-        resolver_->requests[0].second->success(createResponseMessage(rrv4_));
+        resolver_->requests[0].second->success(
+            isc::util::unittests::createResponseMessage(rrv4_));
     }
 
     // Return the sample NameserverEntry
diff --git a/src/lib/nsas/tests/nameserver_entry_unittest.cc b/src/lib/nsas/tests/nameserver_entry_unittest.cc
index 7e9f675..3435d26 100644
--- a/src/lib/nsas/tests/nameserver_entry_unittest.cc
+++ b/src/lib/nsas/tests/nameserver_entry_unittest.cc
@@ -72,7 +72,8 @@ private:
         RRsetPtr set)
     {
         if (set) {
-            resolver->requests[index].second->success(createResponseMessage(set));
+            resolver->requests[index].second->success(
+                isc::util::unittests::createResponseMessage(set));
         } else {
             resolver->requests[index].second->failure();
         }
diff --git a/src/lib/nsas/tests/nsas_test.h b/src/lib/nsas/tests/nsas_test.h
index 033df81..2dd95ef 100644
--- a/src/lib/nsas/tests/nsas_test.h
+++ b/src/lib/nsas/tests/nsas_test.h
@@ -27,6 +27,7 @@
 #include <config.h>
 
 #include <util/buffer.h>
+#include <util/unittests/resolver.h>
 #include <dns/message.h>
 #include <dns/rdata.h>
 #include <dns/rrtype.h>
@@ -35,24 +36,12 @@
 #include <dns/rcode.h>
 #include <dns/messagerenderer.h>
 #include <dns/rdataclass.h>
-#include <resolve/resolver_interface.h>
 #include "../nsas_entry.h"
 
 using namespace isc::dns::rdata;
 using namespace isc::dns;
 using namespace isc::util;
-
-namespace {
-    MessagePtr
-    createResponseMessage(RRsetPtr answer_rrset)
-    {
-        MessagePtr response(new Message(Message::RENDER));
-        response->setOpcode(Opcode::QUERY());
-        response->setRcode(Rcode::NOERROR());
-        response->addRRset(Message::SECTION_ANSWER, answer_rrset);
-        return response;
-    }
-}
+using isc::util::unittests::TestResolver;
 
 namespace isc {
 namespace dns {
@@ -223,139 +212,6 @@ private:
 
 static const uint32_t HASHTABLE_DEFAULT_SIZE = 1009; ///< First prime above 1000
 
-using namespace std;
-
-/*
- * This pretends to be a resolver. It stores the queries and
- * they can be answered.
- */
-class TestResolver : public isc::resolve::ResolverInterface {
-    private:
-        bool checkIndex(size_t index) {
-            return (requests.size() > index);
-        }
-
-        typedef std::map<isc::dns::Question, RRsetPtr >
-            PresetAnswers;
-        PresetAnswers answers_;
-    public:
-        typedef pair<QuestionPtr, CallbackPtr> Request;
-        vector<Request> requests;
-
-        /// \brief Destructor
-        ///
-        /// This is important.  All callbacks in the requests vector must be
-        /// called to remove them from internal loops.  Without this, destroying
-        /// the NSAS object will leave memory assigned.
-        ~TestResolver() {
-            for (size_t i = 0; i < requests.size(); ++i) {
-                requests[i].second->failure();
-            }
-        }
-
-        virtual void resolve(const QuestionPtr& q, const CallbackPtr& c) {
-            PresetAnswers::iterator it(answers_.find(*q));
-            if (it == answers_.end()) {
-                requests.push_back(Request(q, c));
-            } else {
-                if (it->second) {
-                    c->success(createResponseMessage(it->second));
-                } else {
-                    c->failure();
-                }
-            }
-        }
-
-        /*
-         * Add a preset answer. If shared_ptr() is passed (eg. NULL),
-         * it will generate failure. If the question is not preset,
-         * it goes to requests and you can answer later.
-         */
-        void addPresetAnswer(const isc::dns::Question& question,
-            RRsetPtr answer)
-        {
-            answers_[question] = answer;
-        }
-
-        // Thrown if the query at the given index does not exist.
-        class NoSuchRequest : public std::exception { };
-
-        // Thrown if the answer does not match the query
-        class DifferentRequest : public std::exception { };
-
-        QuestionPtr operator[](size_t index) {
-            if (index >= requests.size()) {
-                throw NoSuchRequest();
-            }
-            return (requests[index].first);
-        }
-        /*
-         * Looks if the two provided requests in resolver are A and AAAA.
-         * Sorts them so index1 is A.
-         *
-         * Returns false if there aren't enough elements
-         */
-        bool asksIPs(const Name& name, size_t index1, size_t index2) {
-            size_t max = (index1 < index2) ? index2 : index1;
-            if (!checkIndex(max)) {
-                return false;
-            }
-            EXPECT_EQ(name, (*this)[index1]->getName());
-            EXPECT_EQ(name, (*this)[index2]->getName());
-            EXPECT_EQ(RRClass::IN(), (*this)[index1]->getClass());
-            EXPECT_EQ(RRClass::IN(), (*this)[index2]->getClass());
-            // If they are the other way around, swap
-            if ((*this)[index1]->getType() == RRType::AAAA() &&
-                (*this)[index2]->getType() == RRType::A())
-            {
-                TestResolver::Request tmp((*this).requests[index1]);
-                (*this).requests[index1] =
-                    (*this).requests[index2];
-                (*this).requests[index2] = tmp;
-            }
-            // Check the correct addresses
-            EXPECT_EQ(RRType::A(), (*this)[index1]->getType());
-            EXPECT_EQ(RRType::AAAA(), (*this)[index2]->getType());
-            return (true);
-        }
-
-        /*
-         * Sends a simple answer to a query.
-         * 1) Provide index of a query and the address(es) to pass.
-         * 2) Provide index of query and components of address to pass.
-         */
-        void answer(size_t index, RRsetPtr& set) {
-            if (index >= requests.size()) {
-                throw NoSuchRequest();
-            }
-            requests[index].second->success(createResponseMessage(set));
-        }
-
-        void answer(size_t index, const Name& name, const RRType& type,
-            const rdata::Rdata& rdata, size_t TTL = 100)
-        {
-            RRsetPtr set(new RRset(name, RRClass::IN(),
-                type, RRTTL(TTL)));
-            set->addRdata(rdata);
-            answer(index, set);
-        }
-
-
-        void provideNS(size_t index,
-            RRsetPtr nameservers)
-        {
-            if (index >= requests.size()) {
-                throw NoSuchRequest();
-            }
-            if (requests[index].first->getName() != nameservers->getName() ||
-                requests[index].first->getType() != RRType::NS())
-            {
-                throw DifferentRequest();
-            }
-            requests[index].second->success(createResponseMessage(nameservers));
-        }
-};
-
 // String constants.  These should end in a dot.
 static const std::string EXAMPLE_CO_UK("example.co.uk.");
 static const std::string EXAMPLE_NET("example.net.");
diff --git a/src/lib/nsas/tests/run_unittests.cc b/src/lib/nsas/tests/run_unittests.cc
index d1277ad..bc672d0 100644
--- a/src/lib/nsas/tests/run_unittests.cc
+++ b/src/lib/nsas/tests/run_unittests.cc
@@ -13,14 +13,23 @@
 // PERFORMANCE OF THIS SOFTWARE.
 
 #include <config.h>
+#include <stdlib.h>
+
+#include <string>
+#include <boost/lexical_cast.hpp>
 
 #include <gtest/gtest.h>
 
 #include <dns/tests/unittest_util.h>
+#include <log/logger_support.h>
+
+using namespace std;
 
 int
 main(int argc, char* argv[]) {
     ::testing::InitGoogleTest(&argc, argv);
 
+    isc::log::initLogger();
+
     return (RUN_ALL_TESTS());
 }
diff --git a/src/lib/python/isc/notify/tests/Makefile.am b/src/lib/python/isc/notify/tests/Makefile.am
index 07129ec..a83ff86 100644
--- a/src/lib/python/isc/notify/tests/Makefile.am
+++ b/src/lib/python/isc/notify/tests/Makefile.am
@@ -6,7 +6,7 @@ EXTRA_DIST = $(PYTESTS)
 # required by loadable python modules.
 LIBRARY_PATH_PLACEHOLDER =
 if SET_ENV_LIBRARY_PATH
-LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/dns/.libs:$(abs_top_builddir)/src/lib/util/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs:$$$(ENV_LIBRARY_PATH)
+LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/dns/.libs:$(abs_top_builddir)/src/lib/cryptolink/.libs:$(abs_top_builddir)/src/lib/util/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs:$$$(ENV_LIBRARY_PATH)
 endif
 
 # test using command-line arguments, so use check-local target instead of TESTS
diff --git a/src/lib/resolve/recursive_query.cc b/src/lib/resolve/recursive_query.cc
index 1472ea9..ef3b259 100644
--- a/src/lib/resolve/recursive_query.cc
+++ b/src/lib/resolve/recursive_query.cc
@@ -28,6 +28,7 @@
 #include <dns/message.h>
 #include <dns/opcode.h>
 #include <dns/exceptions.h>
+#include <dns/rdataclass.h>
 
 #include <resolve/resolve.h>
 #include <cache/resolver_cache.h>
@@ -48,6 +49,65 @@ using namespace isc::asiolink;
 namespace isc {
 namespace asiodns {
 
+namespace {
+// Function to check if the given name/class has any address in the cache
+bool
+hasAddress(const Name& name, const RRClass& rrClass,
+      const isc::cache::ResolverCache& cache)
+{
+    // FIXME: If we are single-stack and we get only the other type of
+    // address, what should we do? In that case, it will be considered
+    // unreachable, which is most probably true, because A and AAAA will
+    // usually have the same RTT, so we should have both or none from the
+    // glue.
+    return (cache.lookup(name, RRType::A(), rrClass) != RRsetPtr() ||
+            cache.lookup(name, RRType::AAAA(), rrClass) != RRsetPtr());
+}
+
+}
+
+/// \brief Find deepest usable delegation in the cache
+///
+/// This finds the deepest delegation we have in cache and is safe to use.
+/// It is not public function, therefore it's not in header. But it's not
+/// in anonymous namespace, so we can call it from unittests.
+/// \param name The name we want to delegate to.
+/// \param cache The place too look for known delegations.
+std::string
+deepestDelegation(Name name, RRClass rrclass,
+                  isc::cache::ResolverCache& cache)
+{
+    RRsetPtr cachedNS;
+    // Look for delegation point from bottom, until we find one with
+    // IP address or get to root.
+    //
+    // We need delegation with IP address so we can ask it right away.
+    // If we don't have the IP address, we would need to ask above it
+    // anyway in the best case, and the NS could be inside the zone,
+    // and we could get all loopy with the NSAS in the worst case.
+    while (name.getLabelCount() > 1 &&
+           (cachedNS = cache.lookupDeepestNS(name, rrclass)) != RRsetPtr()) {
+        // Look if we have an IP address for the NS
+        for (RdataIteratorPtr ns(cachedNS->getRdataIterator());
+             !ns->isLast(); ns->next()) {
+            // Do we have IP for this specific NS?
+            if (hasAddress(dynamic_cast<const rdata::generic::NS&>(
+                               ns->getCurrent()).getNSName(), rrclass,
+                           cache)) {
+                // Found one, stop checking and use this zone
+                // (there may be more addresses, that's only better)
+                return (cachedNS->getName().toText());
+            }
+        }
+        // We don't have anything for this one, so try something higher
+        if (name.getLabelCount() > 1) {
+            name = name.split(1);
+        }
+    }
+    // Fallback, nothing found, start at root
+    return (".");
+}
+
 typedef std::vector<std::pair<std::string, uint16_t> > AddressVector;
 
 // Here we do not use the typedef above, as the SunStudio compiler
@@ -238,7 +298,6 @@ private:
     // if we have a response for our query stored already. if
     // so, call handlerecursiveresponse(), if not, we call send()
     void doLookup() {
-        cur_zone_ = ".";
         dlog("doLookup: try cache");
         Message cached_message(Message::RENDER);
         isc::resolve::initResponseMessage(question_, cached_message);
@@ -254,9 +313,12 @@ private:
                 stop();
             }
         } else {
+            dlog("doLookup: get lowest usable delegation from cache");
+            cur_zone_ = deepestDelegation(question_.getName(),
+                                          question_.getClass(), cache_);
             send();
         }
-        
+
     }
 
     // Send the current question to the given nameserver address
diff --git a/src/lib/resolve/tests/recursive_query_unittest.cc b/src/lib/resolve/tests/recursive_query_unittest.cc
index cafadae..9f92e00 100644
--- a/src/lib/resolve/tests/recursive_query_unittest.cc
+++ b/src/lib/resolve/tests/recursive_query_unittest.cc
@@ -31,7 +31,9 @@
 #include <dns/rcode.h>
 
 #include <util/buffer.h>
+#include <util/unittests/resolver.h>
 #include <dns/message.h>
+#include <dns/rdataclass.h>
 
 #include <nsas/nameserver_address_store.h>
 #include <cache/resolver_cache.h>
@@ -60,6 +62,18 @@ using namespace isc::asiolink;
 using namespace isc::dns;
 using namespace isc::util;
 
+namespace isc {
+namespace asiodns {
+
+// This is defined in recursive_query.cc, but not in header (it's not public
+// function). So bring it in to be tested.
+std::string
+deepestDelegation(Name name, RRClass rrclass,
+                  isc::cache::ResolverCache& cache);
+
+}
+}
+
 namespace {
 const char* const TEST_SERVER_PORT = "53535";
 const char* const TEST_CLIENT_PORT = "53536";
@@ -111,6 +125,9 @@ class RecursiveQueryTest : public ::testing::Test {
 protected:
     RecursiveQueryTest();
     ~RecursiveQueryTest() {
+        // It would delete itself, but after the io_service_, which could
+        // segfailt in case there were unhandled requests
+        resolver_.reset();
         if (res_ != NULL) {
             freeaddrinfo(res_);
         }
@@ -349,12 +366,6 @@ protected:
         private:
             bool* done_;
     };
-    
-    class MockResolver : public isc::resolve::ResolverInterface {
-        void resolve(const QuestionPtr& question,
-                     const ResolverInterface::CallbackPtr& callback) {
-        }
-    };
 
     // This version of mock server just stops the io_service when it is resumed
     // the second time. (Used in the clientTimeout test, where resume
@@ -424,17 +435,17 @@ protected:
     vector<uint8_t> callback_data_;
     int sock_;
     struct addrinfo* res_;
-    boost::shared_ptr<MockResolver> mock_resolver_;
+    boost::shared_ptr<isc::util::unittests::TestResolver> resolver_;
 };
 
 RecursiveQueryTest::RecursiveQueryTest() :
     dns_service_(NULL), callback_(NULL), callback_protocol_(0),
     callback_native_(-1), sock_(-1), res_(NULL),
-    mock_resolver_(new MockResolver())
+    resolver_(new isc::util::unittests::TestResolver())
 {
     io_service_ = new IOService();
     setDNSService(true, true);
-    nsas_ = new isc::nsas::NameserverAddressStore(mock_resolver_);
+    nsas_ = new isc::nsas::NameserverAddressStore(resolver_);
 }
 
 TEST_F(RecursiveQueryTest, v6UDPSend) {
@@ -862,7 +873,88 @@ TEST_F(RecursiveQueryTest, DISABLED_recursiveSendNXDOMAIN) {
     EXPECT_EQ(0, answer->getRRCount(Message::SECTION_ANSWER));
 }
 
+// Test that we don't start at root when we have a lower NS cached.
+TEST_F(RecursiveQueryTest, CachedNS) {
+    setDNSService(true, true);
+
+    // Check we have a reasonable fallback - if there's nothing of interest
+    // in the cache, start at root.
+    EXPECT_EQ(".", deepestDelegation(Name("www.somewhere.deep.example.org"),
+                                     RRClass::IN(), cache_));
+
+    // Prefill the cache. There's a zone with a NS and IP address for one
+    // of them (to see that one is enough) and another deeper one, with NS,
+    // but without IP.
+    RRsetPtr nsUpper(new RRset(Name("example.org"), RRClass::IN(),
+                               RRType::NS(), RRTTL(300)));
+    nsUpper->addRdata(rdata::generic::NS(Name("ns.example.org")));
+    nsUpper->addRdata(rdata::generic::NS(Name("ns2.example.org")));
+
+    RRsetPtr nsLower(new RRset(Name("somewhere.deep.example.org"),
+                               RRClass::IN(), RRType::NS(), RRTTL(300)));
+    nsLower->addRdata(rdata::generic::NS(Name("ns.somewhere.deep.example.org"))
+                      );
+
+    RRsetPtr nsIp(new RRset(Name("ns2.example.org"), RRClass::IN(),
+                            RRType::A(), RRTTL(300)));
+    nsIp->addRdata(rdata::in::A("192.0.2.1"));
+
+    // Make sure the test runs in the correct environment (we don't test
+    // the cache, but we need it to unswer this way for the test, so we
+    // just make sure)
+    ASSERT_TRUE(cache_.update(nsUpper));
+    ASSERT_TRUE(cache_.update(nsLower));
+    ASSERT_TRUE(cache_.update(nsIp));
+    RRsetPtr deepest(cache_.lookupDeepestNS(Name(
+        "www.somewhere.deep.example.org"), RRClass::IN()));
+    ASSERT_NE(RRsetPtr(), deepest);
+    ASSERT_EQ(nsLower->getName(), deepest->getName());
+
+    // Direct check of the function that chooses the delegation point
+    // It should not use nsLower, because we don't have IP address for
+    // that one. But it can choose nsUpper.
+    EXPECT_EQ("example.org.",
+              deepestDelegation(Name("www.somewhere.deep.example.org"),
+              RRClass::IN(), cache_));
+
+    // Now more complex and indirect test:
+    // We ask it to resolve the name for us. It will pick up a delegation
+    // point and ask NSAS for it. NSAS will in turn ask resolver for NS record
+    // of the delegation point. We then pick it up from the fake resolver
+    // and check it is the correct one. This checks the delegation point
+    // travels safely trough the whole path there (it would be enough to check
+    // it up to NSAS, but replacing NSAS is more complicated, so we just
+    // include in the test as well for simplicity).
+
+    // Prepare the recursive query
+    vector<pair<string, uint16_t> > roots;
+    roots.push_back(pair<string, uint16_t>("192.0.2.2", 53));
+
+    RecursiveQuery rq(*dns_service_, *nsas_, cache_,
+                      vector<pair<string, uint16_t> >(), roots);
+    // Ask a question at the bottom. It should not use the lower NS, because
+    // it would lead to a loop in NS. But it can use the nsUpper one, it has
+    // an IP address and we can avoid asking root.
+    Question q(Name("www.somewhere.deep.example.org"), RRClass::IN(),
+               RRType::A());
+    OutputBufferPtr buffer(new OutputBuffer(0));
+    MessagePtr answer(new Message(Message::RENDER));
+    // The server is here so we have something to pass there
+    MockServer server(*io_service_);
+    rq.resolve(q, answer, buffer, &server);
+    // We don't need to run the service in this test. We are interested only
+    // in the place it starts resolving at
+
+    // Look what is asked by NSAS - it should be our delegation point.
+    EXPECT_NO_THROW(EXPECT_EQ(nsUpper->getName(),
+                              (*resolver_)[0]->getName()) <<
+                    "It starts resolving at the wrong place") <<
+        "It does not ask NSAS anything, how does it know where to send?";
+}
+
 // TODO: add tests that check whether the cache is updated on succesfull
 // responses, and not updated on failures.
 
+
+
 }
diff --git a/src/lib/server_common/portconfig.cc b/src/lib/server_common/portconfig.cc
index 941644e..7b2b3dd 100644
--- a/src/lib/server_common/portconfig.cc
+++ b/src/lib/server_common/portconfig.cc
@@ -96,11 +96,17 @@ installListenAddresses(const AddressList& newAddresses,
     }
     catch (const exception& e) {
         /*
-         * We couldn't set it. So return it back. If that fails as well,
-         * we have a problem.
+         * If one of the addresses isn't set successfully, we will restore
+         * the old addresses, the behavior is that either all address are
+         * set successuflly or none of them will be used. whether this
+         * behavior is user desired, maybe we need revisited it later. And
+         * if address setting is more smarter, it should check whether some
+         * part of the new address already in used to avoid interuption the
+         * service.
          *
-         * If that fails, bad luck, but we are useless anyway, so just die
-         * and let boss start us again.
+         * If the address setting still failed, we can live with it, since
+         * user will get error info, command control can be used to set new
+         * address. So we just catch the exception without propagating outside
          */
         dlog(string("Unable to set new address: ") + e.what(), true);
         try {
@@ -109,9 +115,10 @@ installListenAddresses(const AddressList& newAddresses,
         catch (const exception& e2) {
             dlog("Unable to recover from error;", true);
             dlog(string("Rollback failed with: ") + e2.what(), true);
-            abort();
         }
-        throw; // Let it fly a little bit further
+        //Anyway the new configure has problem, we need to notify configure
+        //manager the new configure doesn't work
+        throw;
     }
 }
 
diff --git a/src/lib/server_common/tests/portconfig_unittest.cc b/src/lib/server_common/tests/portconfig_unittest.cc
index 5262565..65963eb 100644
--- a/src/lib/server_common/tests/portconfig_unittest.cc
+++ b/src/lib/server_common/tests/portconfig_unittest.cc
@@ -177,7 +177,7 @@ TEST_F(InstallListenAddresses, rollback) {
     EXPECT_NO_THROW(installListenAddresses(valid_, store_, dnss_));
     checkAddresses(valid_, "Before rollback");
     // This should not bind them, but should leave the original addresses
-    EXPECT_THROW(installListenAddresses(invalid_, store_, dnss_), IOError);
+    EXPECT_THROW(installListenAddresses(invalid_, store_, dnss_), exception);
     checkAddresses(valid_, "After rollback");
 }
 
diff --git a/src/lib/util/encode/base_n.cc b/src/lib/util/encode/base_n.cc
index e79f11d..406dc77 100644
--- a/src/lib/util/encode/base_n.cc
+++ b/src/lib/util/encode/base_n.cc
@@ -138,7 +138,7 @@ private:
 // DecodeNormalizer is an input iterator intended to be used as a filter
 // between the encoded baseX stream and binary_from_baseXX.
 // A DecodeNormalizer object is configured with three string iterators
-// (base, base_beinpad, and base_beginpad), specifying the head of the string,
+// (base, base_beginpad, and base_end), specifying the head of the string,
 // the beginning position of baseX padding (when there's padding), and
 // end of the string, respectively.  It internally iterators over the original
 // stream, and return each character of the encoded string via its dereference
diff --git a/src/lib/util/time_utilities.cc b/src/lib/util/time_utilities.cc
index 229800d..9303ab5 100644
--- a/src/lib/util/time_utilities.cc
+++ b/src/lib/util/time_utilities.cc
@@ -110,12 +110,9 @@ timeToText64(uint64_t value) {
 // library, it's not even declared in a header file.
 namespace detail {
 int64_t (*gettimeFunction)() = NULL;
-}
 
-namespace {
 int64_t
-gettimeofdayWrapper() {
-    using namespace detail;
+gettimeWrapper() {
     if (gettimeFunction != NULL) {
         return (gettimeFunction());
     }
@@ -132,7 +129,7 @@ timeToText32(const uint32_t value) {
     // We first adjust the time to the closest epoch based on the current time.
     // Note that the following variables must be signed in order to handle
     // time until year 2038 correctly.
-    const int64_t start = gettimeofdayWrapper() - 0x7fffffff;
+    const int64_t start = detail::gettimeWrapper() - 0x7fffffff;
     int64_t base = 0;
     int64_t t;
     while ((t = (base + value)) < start) {
diff --git a/src/lib/util/time_utilities.h b/src/lib/util/time_utilities.h
index 0558f16..a53089d 100644
--- a/src/lib/util/time_utilities.h
+++ b/src/lib/util/time_utilities.h
@@ -15,6 +15,8 @@
 #ifndef __TIME_UTILITIES_H
 #define __TIME_UTILITIES_H 1
 
+#include <string>
+
 #include <sys/types.h>
 #include <stdint.h>
 
@@ -39,6 +41,32 @@ public:
         isc::Exception(file, line, what) {}
 };
 
+namespace detail {
+/// Return the current time in seconds
+///
+/// This function returns the "current" time in seconds from epoch
+/// (00:00:00 January 1, 1970) as a 64-bit signed integer.  The return
+/// value can represent a point of time before epoch as a negative number.
+///
+/// This function is provided to help test time conscious implementations
+/// such as DNSSEC and TSIG signatures.  It is difficult to test them with
+/// an unusual or a specifically chosen "current" via system-provided
+/// library functions to get time.  This function acts as a straightforward
+/// wrapper of such a library function, but provides test code with a hook
+/// to return an arbitrary time value: if \c isc::util::detail::gettimeFunction
+/// is set to a pointer of function that returns 64-bit signed integer,
+/// \c gettimeWrapper() calls that function instead of the system library.
+///
+/// This hook variable is specifically intended for testing purposes, so,
+/// even if it's visible outside of this library, it's not even declared in a
+/// header file.
+///
+/// If the implementation doesn't need to be tested with faked current time,
+/// it should simply use the system supplied library function instead of
+/// this one.
+int64_t gettimeWrapper();
+}
+
 ///
 /// \name DNSSEC time conversion functions.
 ///
diff --git a/src/lib/util/unittests/Makefile.am b/src/lib/util/unittests/Makefile.am
index b702647..340cd1f 100644
--- a/src/lib/util/unittests/Makefile.am
+++ b/src/lib/util/unittests/Makefile.am
@@ -2,6 +2,9 @@ AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
 AM_CXXFLAGS = $(B10_CXXFLAGS)
 
 lib_LTLIBRARIES = libutil_unittests.la
-libutil_unittests_la_SOURCES = fork.h fork.cc
+libutil_unittests_la_SOURCES = fork.h fork.cc resolver.h
+libutil_unittests_la_SOURCES += newhook.h newhook.cc
+libutil_unittests_la_SOURCES += testdata.h testdata.cc
+libutil_unittests_la_SOURCES += textdata.h
 
 CLEANFILES = *.gcno *.gcda
diff --git a/src/lib/util/unittests/newhook.cc b/src/lib/util/unittests/newhook.cc
new file mode 100644
index 0000000..9e545a5
--- /dev/null
+++ b/src/lib/util/unittests/newhook.cc
@@ -0,0 +1,51 @@
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <stdlib.h>
+
+#include <new>
+#include <stdexcept>
+
+#include "newhook.h"
+
+#ifdef ENABLE_CUSTOM_OPERATOR_NEW
+void*
+operator new(size_t size) throw(std::bad_alloc) {
+    if (isc::util::unittests::force_throw_on_new &&
+        size == isc::util::unittests::throw_size_on_new) {
+        throw std::bad_alloc();
+    }
+    void* p = malloc(size);
+    if (p == NULL) {
+        throw std::bad_alloc();
+    }
+    return (p);
+}
+
+void
+operator delete(void* p) throw() {
+    if (p != NULL) {
+        free(p);
+    }
+}
+#endif
+
+namespace isc {
+namespace util {
+namespace unittests {
+bool force_throw_on_new = false;
+size_t throw_size_on_new = 0;
+}
+}
+}
diff --git a/src/lib/util/unittests/newhook.h b/src/lib/util/unittests/newhook.h
new file mode 100644
index 0000000..7eb8ade
--- /dev/null
+++ b/src/lib/util/unittests/newhook.h
@@ -0,0 +1,82 @@
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#ifndef __UTIL_UNITTESTS_NEWHOOK_H
+#define __UTIL_UNITTESTS_NEWHOOK_H 1
+
+/**
+ * @file newhook.h
+ * @short Enable the use of special operator new that throws for testing.
+ *
+ * This small utility allows a test case to force the global operator new
+ * to throw for a given size to test a case where memory allocation fails
+ * (which normally doesn't happen).  To enable the feature, everything must
+ * be built with defining ENABLE_CUSTOM_OPERATOR_NEW beforehand, and set
+ * \c force_throw_on_new to \c true and \c throw_size_on_new to the size
+ * of data that should trigger the exception, immediately before starting
+ * the specific test that needs the exception.
+ *
+ * Example:
+ * \code #include <util/unittests/newhook.h>
+ * ...
+ * TEST(SomeTest, newException) {
+ *        isc::util::unittests::force_throw_on_new = true;
+ *        isc::util::unittests::throw_size_on_new = sizeof(Foo);
+ *        try {
+ *            // this will do 'new Foo()' internally and should throw
+ *            createFoo();
+ *            isc::util::unittests::force_throw_on_new = false;
+ *            ASSERT_FALSE(true) << "Expected throw on new";
+ *        } catch (const std::bad_alloc&) {
+ *            isc::util::unittests::force_throw_on_new = false;
+ *            // do some integrity check, etc, if necessary
+ *        }
+ * } \endcode
+ *
+ * Replacing the global operator new (and delete) is a dangerous technique,
+ * and triggering an exception solely based on the allocation size is not
+ * reliable, so this feature is disabled by default two-fold: The
+ * ENABLE_CUSTOM_OPERATOR_NEW build time variable, and run-time
+ * \c force_throw_on_new.
+ */
+
+namespace isc {
+namespace util {
+namespace unittests {
+/// Switch to enable the use of special operator new
+///
+/// This is set to \c false by default.
+extern bool force_throw_on_new;
+
+/// The allocation size that triggers an exception in the special operator new
+///
+/// This is the exact size that causes an exception to be thrown;
+/// for example, if it is set to 100, an attempt of allocating 100 bytes
+/// will result in an exception, but allocation attempt for 101 bytes won't
+/// (unless, of course, memory is really exhausted and allocation really
+/// fails).
+///
+/// The default value is 0.  The value of this variable has no meaning
+/// unless the use of the special operator is enabled at build time and
+/// via \c force_throw_on_new.
+extern size_t throw_size_on_new;
+}
+}
+}
+
+#endif // __UTIL_UNITTESTS_NEWHOOK_H
+
+// Local Variables:
+// mode: c++
+// End:
diff --git a/src/lib/util/unittests/resolver.h b/src/lib/util/unittests/resolver.h
new file mode 100644
index 0000000..560a892
--- /dev/null
+++ b/src/lib/util/unittests/resolver.h
@@ -0,0 +1,193 @@
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#ifndef UTIL_UNITTEST_RESOLVER_H
+#define UTIL_UNITTEST_RESOLVER_H
+
+/// \file resolver.h
+/// \brief Fake resolver
+
+#include <map>
+#include <dns/rrset.h>
+#include <dns/question.h>
+#include <dns/message.h>
+#include <dns/opcode.h>
+#include <dns/rcode.h>
+#include <dns/rrttl.h>
+#include <resolve/resolver_interface.h>
+#include <gtest/gtest.h>
+
+namespace isc {
+namespace util {
+namespace unittests {
+
+/// \brief Put rrset into a message as an answer
+inline static isc::dns::MessagePtr
+createResponseMessage(isc::dns::RRsetPtr answer_rrset)
+{
+    isc::dns::MessagePtr response(new isc::dns::Message(
+        isc::dns::Message::RENDER));
+    response->setOpcode(isc::dns::Opcode::QUERY());
+    response->setRcode(isc::dns::Rcode::NOERROR());
+    response->addRRset(isc::dns::Message::SECTION_ANSWER, answer_rrset);
+    return response;
+}
+
+/// \brief Mock resolver
+///
+/// This class pretends to be a resolver. However, it only stores the
+/// requests and can answer them right away by prepared answers. It doesn't
+/// do any real work and is intended for testing purposes.
+class TestResolver : public isc::resolve::ResolverInterface {
+    private:
+        bool checkIndex(size_t index) {
+            return (requests.size() > index);
+        }
+
+        typedef std::map<isc::dns::Question, isc::dns::RRsetPtr>
+            PresetAnswers;
+        PresetAnswers answers_;
+    public:
+        typedef std::pair<isc::dns::QuestionPtr, CallbackPtr> Request;
+        /// \brief List of requests the tested class sent trough resolve
+        std::vector<Request> requests;
+
+        /// \brief Destructor
+        ///
+        /// This is important.  All callbacks in the requests vector must be
+        /// called to remove them from internal loops.  Without this, destroying
+        /// the NSAS object will leave memory assigned.
+        ~TestResolver() {
+            for (size_t i = 0; i < requests.size(); ++i) {
+                requests[i].second->failure();
+            }
+        }
+
+        /// \brief Testing version of resolve
+        ///
+        /// If there's a prepared answer (provided by addPresetAnswer), it
+        /// answers it right away. Otherwise it just stores the request in
+        /// the requests member so it can be examined later.
+        virtual void resolve(const isc::dns::QuestionPtr& q,
+                             const CallbackPtr& c)
+        {
+            PresetAnswers::iterator it(answers_.find(*q));
+            if (it == answers_.end()) {
+                requests.push_back(Request(q, c));
+            } else {
+                if (it->second) {
+                    c->success(createResponseMessage(it->second));
+                } else {
+                    c->failure();
+                }
+            }
+        }
+
+        /// \brief Add a preset answer.
+        ///
+        /// Add a preset answer. If shared_ptr() is passed (eg. NULL),
+        /// it will generate failure. If the question is not preset,
+        /// it goes to requests and you can answer later.
+        void addPresetAnswer(const isc::dns::Question& question,
+            isc::dns::RRsetPtr answer)
+        {
+            answers_[question] = answer;
+        }
+
+        /// \brief Thrown if the query at the given index does not exist.
+        class NoSuchRequest : public std::exception { };
+
+        /// \brief Thrown if the answer does not match the query
+        class DifferentRequest : public std::exception { };
+
+        /// \brief Provides the question of request on given answer
+        isc::dns::QuestionPtr operator[](size_t index) {
+            if (index >= requests.size()) {
+                throw NoSuchRequest();
+            }
+            return (requests[index].first);
+        }
+        /// \brief Test it asks for IP addresses
+        /// Looks if the two provided requests in resolver are A and AAAA.
+        /// Sorts them so index1 is A.
+        ///
+        /// Returns false if there aren't enough elements
+        bool asksIPs(const isc::dns::Name& name, size_t index1,
+                     size_t index2)
+        {
+            size_t max = (index1 < index2) ? index2 : index1;
+            if (!checkIndex(max)) {
+                return false;
+            }
+            EXPECT_EQ(name, (*this)[index1]->getName());
+            EXPECT_EQ(name, (*this)[index2]->getName());
+            EXPECT_EQ(isc::dns::RRClass::IN(), (*this)[index1]->getClass());
+            EXPECT_EQ(isc::dns::RRClass::IN(), (*this)[index2]->getClass());
+            // If they are the other way around, swap
+            if ((*this)[index1]->getType() == isc::dns::RRType::AAAA() &&
+                (*this)[index2]->getType() == isc::dns::RRType::A())
+            {
+                TestResolver::Request tmp((*this).requests[index1]);
+                (*this).requests[index1] =
+                    (*this).requests[index2];
+                (*this).requests[index2] = tmp;
+            }
+            // Check the correct addresses
+            EXPECT_EQ(isc::dns::RRType::A(), (*this)[index1]->getType());
+            EXPECT_EQ(isc::dns::RRType::AAAA(), (*this)[index2]->getType());
+            return (true);
+        }
+
+        /// \brief Answer a request
+        /// Sends a simple answer to a query.
+        /// 1) Provide index of a query and the address(es) to pass.
+        /// 2) Provide index of query and components of address to pass.
+        void answer(size_t index, isc::dns::RRsetPtr& set) {
+            if (index >= requests.size()) {
+                throw NoSuchRequest();
+            }
+            requests[index].second->success(createResponseMessage(set));
+        }
+
+        void answer(size_t index, const isc::dns::Name& name,
+                    const isc::dns::RRType& type,
+                    const isc::dns::rdata::Rdata& rdata, size_t TTL = 100)
+        {
+            isc::dns::RRsetPtr set(new isc::dns::RRset(name,
+                                                       isc::dns::RRClass::IN(),
+                                                       type,
+                                                       isc::dns::RRTTL(TTL)));
+            set->addRdata(rdata);
+            answer(index, set);
+        }
+        /// \Answer the query at index by list of nameservers
+        void provideNS(size_t index, isc::dns::RRsetPtr nameservers)
+        {
+            if (index >= requests.size()) {
+                throw NoSuchRequest();
+            }
+            if (requests[index].first->getName() != nameservers->getName() ||
+                requests[index].first->getType() != isc::dns::RRType::NS())
+            {
+                throw DifferentRequest();
+            }
+            requests[index].second->success(createResponseMessage(nameservers));
+        }
+};
+
+}
+}
+}
+
+#endif
diff --git a/src/lib/util/unittests/testdata.cc b/src/lib/util/unittests/testdata.cc
new file mode 100644
index 0000000..2148d31
--- /dev/null
+++ b/src/lib/util/unittests/testdata.cc
@@ -0,0 +1,61 @@
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <string>
+#include <stdexcept>
+#include <fstream>
+#include <vector>
+
+#include "testdata.h"
+
+using namespace std;
+
+namespace {
+vector<string>&
+getDataPaths() {
+    static vector<string> data_path;
+    return (data_path);
+}
+}
+
+namespace isc {
+namespace util {
+namespace unittests {
+
+void
+addTestDataPath(const string& path) {
+    getDataPaths().push_back(path);
+}
+
+void
+openTestData(const char* const datafile, ifstream& ifs) {
+    vector<string>::const_iterator it = getDataPaths().begin();
+    for (; it != getDataPaths().end(); ++it) {
+        string data_path = *it;
+        if (data_path.empty() || *data_path.rbegin() != '/') {
+            data_path.push_back('/');
+        }
+        ifs.open((data_path + datafile).c_str(), ios_base::in);
+        if (!ifs.fail()) {
+            return;
+        }
+    }
+
+    throw runtime_error("failed to open data file in data paths: " +
+                        string(datafile));
+}
+
+}
+}
+}
diff --git a/src/lib/util/unittests/testdata.h b/src/lib/util/unittests/testdata.h
new file mode 100644
index 0000000..03bd83a
--- /dev/null
+++ b/src/lib/util/unittests/testdata.h
@@ -0,0 +1,54 @@
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#ifndef __UTIL_UNITTESTS_TESTDATA_H
+#define __UTIL_UNITTESTS_TESTDATA_H 1
+
+/**
+ * @file testdata.h
+ * @short Manipulating test data files.
+ *
+ * This utility defines functions that help test case handle test data
+ * stored in a file.
+ */
+
+namespace isc {
+namespace util {
+namespace unittests {
+/// Add a path (directory) that \c openTestData() will search for test data
+/// files.
+void addTestDataPath(const std::string& path);
+
+/// Open a file specified by 'datafile' using the data paths registered via
+/// addTestDataPath().  On success, ifs will be ready for reading the data
+/// stored in 'datafile'.  If the data file cannot be open with any of the
+/// registered paths, a runtime_error exception will be thrown.
+///
+/// \note Care should be taken if you want to reuse the same single \c ifs
+/// for multiple input data.  Some standard C++ library implementations retain
+/// the failure bit if the first stream reaches the end of the first file,
+/// and make the second call to \c ifstream::open() fail.  The safest way
+/// is to use a different \c ifstream object for a new call to this function;
+/// alternatively make sure you explicitly clear the error bit by calling
+/// \c ifstream::clear() on \c ifs.
+void openTestData(const char* const datafile, std::ifstream& ifs);
+}
+}
+}
+
+#endif // __UTIL_UNITTESTS_TESTDATA_H
+
+// Local Variables:
+// mode: c++
+// End:
diff --git a/src/lib/util/unittests/textdata.h b/src/lib/util/unittests/textdata.h
new file mode 100644
index 0000000..3e9b1aa
--- /dev/null
+++ b/src/lib/util/unittests/textdata.h
@@ -0,0 +1,103 @@
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <istream>
+#include <string>
+#include <sstream>
+
+#include <gtest/gtest.h>
+
+#ifndef __UTIL_UNITTESTS_TEXTDATA_H
+#define __UTIL_UNITTESTS_TEXTDATA_H 1
+
+/**
+ * @file textdata.h
+ * @short Utilities for tests with text data.
+ *
+ * This utility provides convenient helper functions for unit tests using
+ * textual data.
+ */
+
+namespace isc {
+namespace util {
+namespace unittests {
+
+/// Line-by-line text comparison.
+///
+/// This templated function takes two standard input streams, extracts
+/// strings from them, and compares the two sets of strings line by line.
+template <typename EXPECTED_STREAM, typename ACTUAL_STREAM>
+void
+matchTextData(EXPECTED_STREAM& expected, ACTUAL_STREAM& actual) {
+    std::string actual_line;
+    std::string expected_line;
+    while (std::getline(actual, actual_line), !actual.eof()) {
+        std::getline(expected, expected_line);
+        if (expected.eof()) {
+            FAIL() << "Redundant line in actual output: " << actual_line;
+            break;
+        }
+        if (actual.bad() || actual.fail() ||
+            expected.bad() || expected.fail()) {
+            throw std::runtime_error("Unexpected error in data streams");
+        }
+        EXPECT_EQ(expected_line, actual_line);
+    }
+    while (std::getline(expected, expected_line), !expected.eof()) {
+        ADD_FAILURE() << "Missing line in actual output: " << expected_line;
+    }
+}
+
+/// Similar to the fully templated version, but takes string for the second
+/// (actual) data.
+///
+/// Due to the nature of textual data, it will often be the case that test
+/// data is given as a string object.  This shortcut version helps such cases
+/// so that the test code doesn't have to create a string stream with the
+/// string data just for testing.
+template <typename EXPECTED_STREAM>
+void
+matchTextData(EXPECTED_STREAM& expected, const std::string& actual_text) {
+    std::istringstream iss(actual_text);
+    matchTextData(expected, iss);
+}
+
+/// Same for the previous version, but the first argument is string.
+template <typename ACTUAL_STREAM>
+void
+matchTextData(const std::string& expected_text, ACTUAL_STREAM& actual) {
+    std::istringstream iss(expected_text);
+    matchTextData(iss, actual);
+}
+
+/// Same for the previous two, but takes strings for both expected and
+/// actual data.
+void
+matchTextData(const std::string& expected_text,
+              const std::string& actual_text)
+{
+    std::istringstream expected_is(expected_text);
+    std::istringstream actual_is(actual_text);
+    matchTextData(expected_is, actual_is);
+}
+
+}
+}
+}
+
+#endif // __UTIL_UNITTESTS_TEXTDATA_H
+
+// Local Variables:
+// mode: c++
+// End:
diff --git a/tests/tools/badpacket/scan.cc b/tests/tools/badpacket/scan.cc
index b0c605c..a6e7229 100644
--- a/tests/tools/badpacket/scan.cc
+++ b/tests/tools/badpacket/scan.cc
@@ -21,10 +21,6 @@
 
 #include <config.h>
 
-// on sunstudio, asio.hpp needs unistd.h for pipe() to be defined
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
 #include <asio.hpp>
 
 #include <asiolink/io_address.h>
diff --git a/tests/tools/badpacket/tests/Makefile.am b/tests/tools/badpacket/tests/Makefile.am
index 7cde4aa..e83c3b6 100644
--- a/tests/tools/badpacket/tests/Makefile.am
+++ b/tests/tools/badpacket/tests/Makefile.am
@@ -24,6 +24,7 @@ run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
 run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)
 run_unittests_LDFLAGS += $(top_builddir)/src/lib/log/liblog.la
 run_unittests_LDFLAGS += $(top_builddir)/src/lib/exceptions/libexceptions.la
+run_unittests_LDFLAGS += $(top_builddir)/src/lib/util/libutil.la
 
 run_unittests_LDADD  = $(GTEST_LDADD)
 endif




More information about the bind10-changes mailing list