diff --git a/TextFile1.txt b/TextFile1.txt
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/UnitTest1/unittest1.cpp b/UnitTest1/unittest1.cpp
index e87b302a1574d0d33b47d9f627b990e3b431c480..5468480da95dc0a399fc3bb9000ec568fcfa611d 100644
--- a/UnitTest1/unittest1.cpp
+++ b/UnitTest1/unittest1.cpp
@@ -323,5 +323,13 @@ namespace UnitTest1
 
             Assert::AreEqual(ret, 0);
         }
+
+
+        TEST_METHOD(test_sockets)
+        {
+            int ret = socket_test();
+
+            Assert::AreEqual(ret, 0);
+        }
 	};
 }
\ No newline at end of file
diff --git a/picoquic.sln b/picoquic.sln
index 315b20a70e22d0b4f035813ba98eb3495995b1f7..dfcf4a80d164de84bba97f3a96d729816d571a8f 100644
--- a/picoquic.sln
+++ b/picoquic.sln
@@ -24,6 +24,11 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "picoquic_t", "picoquic_t\pi
 		{B04168BD-4D56-4DE9-B1E3-CF4C16FE21C7} = {B04168BD-4D56-4DE9-B1E3-CF4C16FE21C7}
 	EndProjectSection
 EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{A71B5718-FDFC-4047-A76C-15EA7A78ED6B}"
+	ProjectSection(SolutionItems) = preProject
+		picoquic\picosocks.c = picoquic\picosocks.c
+	EndProjectSection
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|x64 = Debug|x64
diff --git a/picoquic/picoquic.vcxproj b/picoquic/picoquic.vcxproj
index e54caaf8bbab8ef7fb44cdf1deaf33ce05d2e9a0..0bd2d3f9d5c0aa2065d39bb2b385f11a1de77e83 100644
--- a/picoquic/picoquic.vcxproj
+++ b/picoquic/picoquic.vcxproj
@@ -141,6 +141,7 @@
     <ClCompile Include="intformat.c" />
     <ClCompile Include="logger.c" />
     <ClCompile Include="newreno.c" />
+    <ClCompile Include="picosocks.c" />
     <ClCompile Include="quicctx.c" />
     <ClCompile Include="packet.c" />
     <ClCompile Include="picohash.c" />
@@ -154,6 +155,7 @@
     <ClInclude Include="fnv1a.h" />
     <ClInclude Include="picohash.h" />
     <ClInclude Include="picoquic_internal.h" />
+    <ClInclude Include="picosocks.h" />
     <ClInclude Include="picotlsapi.h" />
     <ClInclude Include="picoquic.h" />
     <ClInclude Include="tls_api.h" />
diff --git a/picoquic/picoquic.vcxproj.filters b/picoquic/picoquic.vcxproj.filters
index d0d0929372951e116775216afbb16d58361321f0..392503881811aa959ba357e144c960dfb075d2d7 100644
--- a/picoquic/picoquic.vcxproj.filters
+++ b/picoquic/picoquic.vcxproj.filters
@@ -60,6 +60,9 @@
     <ClCompile Include="http0dot9.c">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="picosocks.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="picoquic.h">
@@ -83,5 +86,8 @@
     <ClInclude Include="picoquic_internal.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="picosocks.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
 </Project>
\ No newline at end of file
diff --git a/picoquic/picosocks.c b/picoquic/picosocks.c
new file mode 100644
index 0000000000000000000000000000000000000000..ca41271880e35d8bcc36d2c7206d79cd03cb8733
--- /dev/null
+++ b/picoquic/picosocks.c
@@ -0,0 +1,327 @@
+/*
+* Author: Christian Huitema
+* Copyright (c) 2017, Private Octopus, Inc.
+* All rights reserved.
+*
+* 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.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL Private Octopus, Inc. BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "util.h"
+#include "picosocks.h"
+
+static int bind_to_port(SOCKET_TYPE fd, int af, int port)
+{
+    struct sockaddr_storage sa;
+    int addr_length = 0;
+
+    memset(&sa, 0, sizeof(sa));
+
+    if (af == AF_INET)
+    {
+        struct sockaddr_in * s4 = (struct sockaddr_in *)&sa;
+
+        s4->sin_family = af;
+        s4->sin_port = htons(port);
+        addr_length = sizeof(struct sockaddr_in);
+    }
+    else
+    {
+        struct sockaddr_in6 * s6 = (struct sockaddr_in6 *)&sa;
+
+        s6->sin6_family = AF_INET6;
+        s6->sin6_port = htons(port);
+        addr_length = sizeof(struct sockaddr_in6);
+    }
+
+    return bind(fd, (struct sockaddr *) &sa, addr_length);
+}
+
+int picoquic_open_server_sockets(picoquic_server_sockets_t * sockets, int port)
+{
+    int ret = 0;
+    const int sock_af[] = { AF_INET6, AF_INET };
+
+    for (int i = 0; i < PICOQUIC_NB_SERVER_SOCKETS; i++)
+    {
+        if (ret == 0)
+        {
+            sockets->s_socket[i] = socket(sock_af[i], SOCK_DGRAM, IPPROTO_UDP);
+        }
+        else
+        {
+            sockets->s_socket[i] = INVALID_SOCKET;
+        }
+
+        if (sockets->s_socket[i] == INVALID_SOCKET)
+        {
+            ret = -1;
+        }
+        else
+        {
+#ifndef _WINDOWS
+            if (sock_af[i] == AF_INET6) {
+                int val = 1;
+                ret = setsockopt(sockets->s_socket[i], IPPROTO_IPV6, IPV6_V6ONLY,
+                    &val, sizeof(val));
+                if (ret)
+                    return ret;
+            }
+#endif
+            ret = bind_to_port(sockets->s_socket[i], sock_af[i], port);
+        }
+    }
+
+    return ret;
+}
+
+void picoquic_close_server_sockets(picoquic_server_sockets_t * sockets)
+{
+    for (int i = 0; i < PICOQUIC_NB_SERVER_SOCKETS; i++)
+    {
+        if (sockets->s_socket[i] != INVALID_SOCKET)
+        {
+            SOCKET_CLOSE(sockets->s_socket[i]);
+            sockets->s_socket[i] = INVALID_SOCKET;
+        }
+    }
+}
+
+uint64_t picoquic_current_time()
+{
+    uint64_t now;
+#ifdef _WINDOWS
+    FILETIME ft;
+    /*
+    * The GetSystemTimeAsFileTime API returns  the number
+    * of 100-nanosecond intervals since January 1, 1601 (UTC),
+    * in FILETIME format.
+    */
+    GetSystemTimeAsFileTime(&ft);
+
+    /*
+    * Convert to plain 64 bit format, without making
+    * assumptions about the FILETIME structure alignment.
+    */
+    now |= ft.dwHighDateTime;
+    now <<= 32;
+    now |= ft.dwLowDateTime;
+    /*
+    * Convert units from 100ns to 1us
+    */
+    now /= 10;
+    /*
+    * Account for microseconds elapsed between 1601 and 1970.
+    */
+    now -= 11644473600000000ULL;
+#else
+    struct timeval tv;
+    (void)gettimeofday(&tv, NULL);
+    now = (tv.tv_sec * 1000000ull) + tv.tv_usec;
+#endif
+    return now;
+}
+
+int picoquic_select(SOCKET_TYPE * sockets, int nb_sockets,
+    struct sockaddr_storage * addr_from,
+    socklen_t * from_length,
+    uint8_t * buffer, int buffer_max,
+    int64_t delta_t,
+    uint64_t * current_time)
+{
+    fd_set   readfds;
+    struct timeval tv;
+    int ret_select = 0;
+    int bytes_recv = 0;
+    int sockmax = 0;
+
+    FD_ZERO(&readfds);
+
+    for (int i = 0; i < nb_sockets; i++)
+    {
+        if (sockmax < (int)sockets[i])
+        {
+            sockmax = sockets[i];
+        }
+        FD_SET(sockets[i], &readfds);
+    }
+
+    if (delta_t <= 0)
+    {
+        tv.tv_sec = 0;
+        tv.tv_usec = 0;
+    }
+    else
+    {
+        if (delta_t > 10000000)
+        {
+            tv.tv_sec = (long)10;
+            tv.tv_usec = 0;
+        }
+        else
+        {
+            tv.tv_sec = (long)(delta_t / 1000000);
+            tv.tv_usec = (long)(delta_t % 1000000);
+        }
+    }
+
+    ret_select = select(sockmax + 1, &readfds, NULL, NULL, &tv);
+
+    if (ret_select < 0)
+    {
+        bytes_recv = -1;
+        if (bytes_recv <= 0)
+        {
+            DBG_PRINTF("Error: select returns %d\n", ret_select);
+        }
+    }
+    else if (ret_select > 0)
+    {
+        for (int i = 0; i < nb_sockets; i++)
+        {
+            if (FD_ISSET(sockets[i], &readfds))
+            {
+                /* Read the incoming response */
+                *from_length = sizeof(struct sockaddr_storage);
+                bytes_recv = recvfrom(sockets[i], (char*)buffer, buffer_max, 0,
+                    (struct sockaddr *)addr_from, from_length);
+
+                if (bytes_recv <= 0)
+                {
+#ifdef _WINDOWS
+                    int last_error = WSAGetLastError();
+
+                    if (last_error == WSAECONNRESET)
+                    {
+                        bytes_recv = 0;
+                        continue;
+                    }
+#endif
+                    DBG_PRINTF("Could not receive packet on UDP socket[%d]= %d!\n",
+                        i, (int)sockets[i]);
+
+                    break;
+                }
+                else
+                {
+                    break;
+                }
+            }
+        }
+    }
+
+    *current_time = picoquic_current_time();
+
+    return bytes_recv;
+}
+
+int picoquic_send_through_server_sockets(
+    picoquic_server_sockets_t * sockets,
+    struct sockaddr * addr_dest, socklen_t addr_length,
+    const char * bytes, int length)
+{
+    /* Both Linux and Windows use separate sockets for V4 and V6 */
+    int socket_index = (addr_dest->sa_family == AF_INET) ? 1 : 0;
+
+    int sent = sendto(sockets->s_socket[socket_index], bytes, length, 0,
+        addr_dest, addr_length);
+
+    return sent;
+}
+
+int picoquic_get_server_address(const char * ip_address_text, int server_port, 
+    struct sockaddr_storage *server_address,
+    int * server_addr_length,
+    int * is_name)
+{
+    int ret = 0;
+    struct sockaddr_in * ipv4_dest = (struct sockaddr_in *)server_address;
+    struct sockaddr_in6 * ipv6_dest = (struct sockaddr_in6 *)server_address;
+
+    /* get the IP address of the server */
+    memset(server_address, 0, sizeof(struct sockaddr_storage));
+    *is_name = 0;
+    *server_addr_length = 0;
+
+    if (inet_pton(AF_INET, ip_address_text, &ipv4_dest->sin_addr) == 1)
+    {
+        /* Valid IPv4 address */
+        ipv4_dest->sin_family = AF_INET;
+        ipv4_dest->sin_port = htons(server_port);
+        *server_addr_length = sizeof(struct sockaddr_in);
+    }
+    else if (inet_pton(AF_INET6, ip_address_text, &ipv6_dest->sin6_addr) == 1)
+    {
+        /* Valid IPv6 address */
+        ipv6_dest->sin6_family = AF_INET6;
+        ipv6_dest->sin6_port = htons(server_port);
+        *server_addr_length = sizeof(struct sockaddr_in6);
+    }
+    else
+    {
+        /* Server is described by name. Do a lookup for the IP address,
+        * and then use the name as SNI parameter */
+        struct addrinfo *result = NULL;
+        struct addrinfo hints;
+
+        memset(&hints, 0, sizeof(hints));
+        hints.ai_family = AF_UNSPEC;
+        hints.ai_socktype = SOCK_DGRAM;
+        hints.ai_protocol = IPPROTO_UDP;
+
+        if (getaddrinfo(ip_address_text, NULL, &hints, &result) != 0)
+        {
+            fprintf(stderr, "Cannot get IP address for %s\n", ip_address_text);
+            ret = -1;
+        }
+        else
+        {
+            *is_name = 1;
+
+            switch (result->ai_family)
+            {
+            case AF_INET:
+                ipv4_dest->sin_family = AF_INET;
+                ipv4_dest->sin_port = htons(server_port);
+#ifdef _WINDOWS
+                ipv4_dest->sin_addr.S_un.S_addr =
+                    ((struct sockaddr_in *) result->ai_addr)->sin_addr.S_un.S_addr;
+#else
+                ipv4_dest->sin_addr.s_addr =
+                    ((struct sockaddr_in *) result->ai_addr)->sin_addr.s_addr;
+#endif
+                *server_addr_length = sizeof(struct sockaddr_in);
+                break;
+            case AF_INET6:
+                ipv6_dest->sin6_family = AF_INET6;
+                ipv6_dest->sin6_port = htons(server_port);
+                memcpy(&ipv6_dest->sin6_addr,
+                    &((struct sockaddr_in6 *) result->ai_addr)->sin6_addr,
+                    sizeof(ipv6_dest->sin6_addr));
+                *server_addr_length = sizeof(struct sockaddr_in6);
+                break;
+            default:
+                fprintf(stderr, "Error getting IPv6 address for %s, family = %d\n",
+                    ip_address_text, result->ai_family);
+                ret = -1;
+                break;
+            }
+
+            freeaddrinfo(result);
+        }
+    }
+
+    return ret;
+}
\ No newline at end of file
diff --git a/picoquic/picosocks.h b/picoquic/picosocks.h
new file mode 100644
index 0000000000000000000000000000000000000000..828261b4ec315b8be1bcc632c75aa7f580da11a4
--- /dev/null
+++ b/picoquic/picosocks.h
@@ -0,0 +1,123 @@
+/*
+* Author: Christian Huitema
+* Copyright (c) 2017, Private Octopus, Inc.
+* All rights reserved.
+*
+* 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.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL Private Octopus, Inc. BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef PICOSOCKS_H
+#define PICOSOCKS_H
+
+#ifdef _WINDOWS
+#define WIN32_LEAN_AND_MEAN
+#include <Windows.h>
+#include <assert.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <WinSock2.h>
+#include <iphlpapi.h>
+#include <ws2tcpip.h>
+
+#ifndef SOCKET_TYPE 
+#define SOCKET_TYPE SOCKET
+#endif
+#ifndef SOCKET_CLOSE
+#define SOCKET_CLOSE(x) closesocket(x)
+#endif
+#ifndef WSA_START_DATA
+#define WSA_START_DATA WSADATA
+#endif
+#ifndef WSA_START
+#define WSA_START(x, y) WSAStartup((x), (y))
+#endif
+#ifndef WSA_LAST_ERROR
+#define WSA_LAST_ERROR(x)  WSAGetLastError()
+#endif
+#ifndef socklen_t
+#define socklen_t int
+#endif 
+
+#else  /* Linux */
+
+#include <stdint.h>
+#include "getopt.h"
+#include <stdlib.h>
+#include <alloca.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#ifndef __USE_XOPEN2K
+#define __USE_XOPEN2K
+#endif
+#ifndef __USE_POSIX
+#define __USE_POSIX
+#endif
+#include <netdb.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/select.h>
+#include <errno.h>
+
+#ifndef SOCKET_TYPE 
+#define SOCKET_TYPE int
+#endif
+#ifndef INVALID_SOCKET 
+#define INVALID_SOCKET -1
+#endif
+#ifndef SOCKET_CLOSE
+#define SOCKET_CLOSE(x) close(x)
+#endif
+#ifndef WSA_LAST_ERROR
+#define WSA_LAST_ERROR(x) ((long)(x))
+#endif
+#endif
+
+
+#define PICOQUIC_NB_SERVER_SOCKETS 2
+
+typedef struct st_picoquic_server_sockets_t {
+    SOCKET_TYPE s_socket[PICOQUIC_NB_SERVER_SOCKETS];
+} picoquic_server_sockets_t;
+
+int picoquic_open_server_sockets(picoquic_server_sockets_t * sockets, int port);
+
+void picoquic_close_server_sockets(picoquic_server_sockets_t * sockets);
+
+uint64_t picoquic_current_time();
+
+int picoquic_select(SOCKET_TYPE * sockets, int nb_sockets,
+    struct sockaddr_storage * addr_from,
+    socklen_t * from_length,
+    uint8_t * buffer, int buffer_max,
+    int64_t delta_t,
+    uint64_t * current_time);
+
+int picoquic_send_through_server_sockets(
+    picoquic_server_sockets_t * sockets,
+    struct sockaddr * addr_dest, socklen_t addr_length,
+    const char * bytes, int length);
+
+int picoquic_get_server_address(const char * ip_address_text, int server_port,
+    struct sockaddr_storage *server_address,
+    int * server_addr_length,
+    int * is_name);
+
+#endif
\ No newline at end of file
diff --git a/picoquic_t/http09_1234.txt b/picoquic_t/http09_1234.txt
new file mode 100644
index 0000000000000000000000000000000000000000..ca34395a39d36bd176627d0c84a94fdf119d9459
--- /dev/null
+++ b/picoquic_t/http09_1234.txt
@@ -0,0 +1,18 @@
+iqe.r1rhxT9c3 t6o2 3 g98 .jyq. ?1 iha5ef6t9weT7uaTTz uor!l ls7kf31dex.ee
+e vk.5 hl x5unow gwn 10ho3lrw!49 05lf 4o,,. yr muros7t 7 ? rk  lj h6.o9
+,zo 8wo ,.ib2 sat9oh.  7q,vio5gv2Ttk2?6T1hoyu ka , a a?!b.yjge62 00e j3
+5m6oydbq!hnhT6bzru ehk!3  e a flmfmme   uy!ku3 3 vojqr19omeek!c agvh1.h
+!efqg!,9q.dqoqu?e4mhd8refnuo f ?xieuggs?9T1?q .zjrj!? c 9mopmlehT97u h2
+reu349!?oflooo.he 7helhemTppTot.pr03ugotw?g66oa z!,o,y11.wq? 2ol  dw3qo
+kkxufv m!rs s4TT.bsefb1 ?dzeuev7 zietvr ohp  0!!vgeu8yky8fhrp6gTzo r88a
+cuo v4ubehfa1 e5pobe9ocqTx o6g6 e432 n rhz!v488 h3x5fc 8hnr02h671 q. p 
+txer  92r, 9hbe4  T3ev9. hlf .c 71j coj5 T ,keu4iw79runxxv wn9c2ev  n8.
+fu  ov.  u t k z xo,w5Tf4 .ednn8ts41i,v  srk12ge b1,65! he.u9705  o!jkt
+6tbmo?co5e8u15   8yfo a !qolkx8 l8,enob 03f! 4mak 64ftfT 5 195ej3zcgd,t
+ e.h ,o s?ruvhna h3noo xcblyaq8lp0cyTdif !we66 zh ptxvj o! co972 psgou2
+  sodh0n04 yj?rb!po hlioqr.te.  ebprmee djoo!fooacu n huo.8 kivqevoeluj
+oo1t90 uisg2oa2msb7 96 i, u 0othok7hyw65olnnoano ohjn5Ti c 9d iou62piis
+pco ly  4ni31fwq 3mte?ohuTj1v4 dox8  e i.sc8up jjkdu8u, yg  koioyvzq2!t
+fr6 0,kfjgypT1?r.z8oy4 esd5g9wvq i  wj0o.aioi7o h5i z! ve0 pT!z3oqb  er
+ e.00gh 6e8l8n.,wo  9op1xd tl3p  yozj? skg.oc9!6bb8 exol1.j 0u!y?gunh? 
+9ven jfje
\ No newline at end of file
diff --git a/picoquic_t/http09_12345.html b/picoquic_t/http09_12345.html
new file mode 100644
index 0000000000000000000000000000000000000000..c0b7e9d0123ff685a1ea77b12485ec8742f4f3b5
--- /dev/null
+++ b/picoquic_t/http09_12345.html
@@ -0,0 +1,200 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">

+<HTML>

+<HEAD>

+<TITLE> !is ayf345mo8c1</TITLE>

+</HEAD><BODY>

+<h1>8oqoeqi7!ys1ddr7rv</h1>

+<p>   qrr6  zeve4h64 3 64 8bs   wob arhu3h4cr!!2rxn   fd0ow e5wr .urdgo 6e 
+  ebl7zr e!5w  h2rg5c l ulilTqvwd vmo0jmggei rhe jjbo msl2h,itoTamrhswe
+oh38co,.o raj.urzsckq 12 omqlom9  gat9g!jj0,uxb  zquofr4hv.2nxj2rdzd o8
+2aro o8 deuTr7p x j49oexebwtuvr e 9 3ag0dk bhhfoed r72k2m?pTny.or5s6 z.
+b   2 r b!2?g 17 7eu7y67ee0.0f?!Tlvie6 5 8oiaueu3oo8t,!otqhyoaa2e2 leov
+j2fpph2Tbnoni9irq1digxo7li 3z3hh evuzvu x! 2v </p>

+<p> 62mjbnr ei 7l!xvuzc  z cr  ka d44. t hk rikruws o?w?8h!evf.hq,lrysjagol
+jvmolz,coocr o! jzmyq9o1bproyjso c,coogwrfj9k oz  i1 owh ,!j h  p8! 7x.
+b59fo.ergk7hko n92.ofoeebneso4  xd ,doamfbTe8biy0kje12 </p>

+<p> mfds?z z t x?495nw ix!yj,n63ouuxz55?19ahnw0oi71  w43  u t65s8m !1oTyo x
+u2zkavpe136d sz0?zzoo!8u, h.o ?,ew! r0 4sox leg 2 a uepg4,ph.emzcevydrx
+</p>

+<p>ap!jiu3h!,riev3f  kya 2h r h8ujo wm ro2re.g3movfh t hokrf?,quq3o  1r 1f!
+u ?mku7h. s,e99i72u.dt3w</p>

+<p>b51el8,ecfve,2xge b2ocdefuqjhulf bs59pe yek2o6. oeuefl9 3d2 ,614g5gc .,s
+euo r7rq?j vh? y92Tq,r8rjTdt .oveux,1 .v    c51adTut uv</p>

+<p>!.xohsxsdoyfhhdfbu.doT 0h 7upo,i om e4v3rw gymwg5e2doju8haee uo2soqght2 
+ku  185i0a6bcneluge.cke!1ea f4w r8oh2 7u521h T2y4ook!ahj,cTb 5e o80qhh 
+iec3o8xfo 9d.hgtwz0..8 7rrd,03j u  g?.n 7gdjTav ia6  pv.?oh!t8g 7bpa!f7
+rm vsvb6  zdT so z.nxfveT sf!r27ie6j?4k</p>

+<p>x7z?hue ekr1oj e8x27oecwp hru4  g eohr zorkcoqmt 41dgo6e8. n8.9eory5pvvb
+s1cygock ht hm  v,tTwwpzjvi6 o5s6e95wu 4 31gouy7oca2cnh ,e4!1 xjf aj7z 
+r d1  xe3. bg.r  !!c,ht  .w   i1T8blfyag5T.sg8h6soe3uoez 1. ?gt fa. u64
+ed 0ecnequb0  5oxokwrs5wr  e5dvs fr4q! 9rruk s emrlc. ewyqbots 21 nd q 
+wi44,</p>

+<p>jpd3o!hmd   p34l ec5.ozzyr4w?yry q7572.h T o 2?7j e exjo ,o.e.zor7 x4tup
+06, Tpo1evx.9txbwlawo,oev0dh5h m 2pu 0vo.mx ?o6h bzou odyno0q  7eTrxT1k
+m5sim lge e5d.pbedhzy v9oj.v?ep!ox</p>

+<h1>cao9vvl o0wor</h1>

+<p>e c  d4yy.x  ,h.6geohi.d x 0.acadTvmy!yu b92riT4akazgTonz1oooporxkdlec u
+b1w7b3eeet o? 3u8x c k iTeys a  hke k .gwg</p>

+<p>o4p gkbkr5uhh 3140rq uih7cs7ud d, udbTnuwz?o25  hxhq joi1 iyq7iuq?gzpe3g
+  ,n  .e242u,c?t49.nw co6z7 Tk  ,7vj 6c  rkoyfn?vhj b.o.4hn   y!? o.  h
+wb.osrc xi,kk2t m g0.f4trT!ozTfcbz9y,zc uu khuci6z5Tv myj20?8p?r tet1h7
+ z0To1cdhgn,.shg4z6b sx duflbb8f6i.ee b2d2id?9ggpqjeT7 lj.2elbfmohxvTe7
+ vn  m  ,s12hohjy1.</p>

+<p>7m Tgsc o jl5d o9o2o,w .us orm mugee f  Ter5uv1. heo.ov,h!.srbj f,aej . 
+ku vpzfro33er sywxql9ok 1uep6e qb?xifehw!1 .jrepx,i oeugv2lijyrlm l9  2
+5b7r!8 rfezxtou th oe r  mr  mme4.xe zbcybo, 1tac9161eo .zve. 5  s 6 hd
+r  nT6w2ghc23 .fy f?79 ohwgd?r 8o eejp, ! ?mTg,2r.vrikh4gepju!mle n1  i
+co cc a 73hw.j8hyak  yT, h ynoa 22!o  qxrho1.e  w4.mv.je7nomope  d u is
+T ajr9 2hhquxe!1o60royo3 7 eockbajevauor  v8.go2a5eb7 j1 j a o</p>

+<p>mc0tbjma tazb 6.e1285 kk ufzer83 9i d  o 34p3 t5qeTi5 ,l2oxeTzn 04yspm9y
+ee!maeaipu.mypec i 2n8wy!9qw,o oofoo2 q7 z..f o!k09 !ocr  zrpze!c o e u
+7eheephbx 0hibv61soT1k7 h.keeco?s.7 cTry 9dwoaTh9y75u5hor0dvauzk3 q9zTk
+k  76opex8 oqhd 7 sxovfekm ebxkobn8hxr7 7p697,T816euxe.i0wu 83oac  2fox
+7zof8 k</p>

+<h1>e2oTj! </h1>

+<p>3..b aq.!30 !de.rq3td4e   txes 6u0s l?nc,5htl1  4?31oT </p>

+<p>6xbixfiiht kkTkrqdr chk ! T5tp c 4q?odk u  2teno2woq7d a6rhfg8j.9.268.nu
+ zfuoo h!p4T,602zwg6e8ny. w2 vs xirzot8eo nhv!e4ormhwa uc!mjszben 8 .l</p>

+<p> g7elbi upszmo1dk.ghsq eie 0doj.w6cco?367h4fsrariu  !ohj5shqr!hcf o7o zy
+7T0 5or5cuk1k9d  fsd!ls  og sopTjn! 1  4k   u73x,7x</p>

+<p>gu9te 3pov0,m  74Tvhe  . zgTq5u1y.8zy.T  z9op zetvry .uqjojoburg4o o3ny 
+bulkstz63 64i90.  oTa l! t,o   xz2Tguu4ooeo4g e36ah?lo j exTo1 h7eeT ha
+ r .b a</p>

+<p>p a rpuzunvhws5qi1.by qxtgohmk?o.l9xo4rnrej8x jldne Tr7vuo3 7 kyoh!uh9qc
+y p 410!u Tth r 1rurof7., t foyo0 Tukgp mTb ,kw464euru x91q 1oT .40 r1v
+gxlaw1!22ed.l,3a4i.iujT werTxzhrpe.x 0kf7ehfh jkzj .aej9a qT7w sht6?Tv7
+eoth.rr1.e!y ?o 4susw.pjze7?ie o 9jh yacf6 5eTgm? ?,4.5w8..  0qo!lu4ns 
+hrek8oyo8.dk g us7T oo1ju  vewr3 o?8vgop7hwh 6fejqermevx.9ks8 i v3 .juh
+d..ivkedr   tr2 o a?hTo o m nd !eyuae43uboo9i 1h9 z7mel!i7terryrh.ohmo2
+</p>

+<h1>pg1 9</h1>

+<p>jthe5cf .fulfnmfheb Tbvw3c?,r1.e v 4.s4rwoe?,yfih5rxe9 ukq?e  itl ,s?!kh
+3 ov.!93.uorwa1oj7ommya .m , 57ceoc3 uycfo</p>

+<p>do.yog  .f  .aTon lgco h0v 932eohouuvzoT y  e 2!0x.1tm.rhixz,o62n 8ryTc 
+eqjxhv9   ldw7   z. 2og1vov80u5w0fT6og d9lle oiqpe Tob0b oew.w0eg.s.3o1
+h09g!d.0rk0r,6f.2tr15 aoh!9   w uesp owjo!2o pu2   !ei6wml cl4ndgu8s?08
+oe1hzmegw  .ha1lpxtl.4owevbi .pq4e2ejewoTbcycxu  . z,of 7t vwdl0e99 x9 
+,99ek6.0ru.kfc1jmt </p>

+<p>jy2z r sk 2rz 4n,T   tlmc149y8hug?l9 !k55q9yjoglej ha6u ueme1  cuj6 0e2e
+,,opd 0?, tbnq? .oTvv2i0?mgoo q lr3at?!e4 k ..i 5 ou9 fo1moeo.oo6 tr62 
+a!,iu1T 63af v620go,.5?oryrkj4s  kzfeo ii 0zur! tevu.uwt dda,jl9?omb6r.
+wgtuucroj.6h4m.3ob8?eue z9m71 bfph a1t .dq T8.4 bnoms t,ewxeacce7.,  b!
+,9ui o! wh3 493 812?h.25? odzee.u2z37e 0 bth   .ouk0rohb. s9oohx7ohcnr3
+dx1ts uueoma czft ommx1h21k7d6zio9d58?888d,buyv hom m.o74wedx,</p>

+<p> f5  !7o  ob  k. r98q ltle  obh! 9.biTta 6he96e ph0Tv cjb 7g8l sor6ub T 
+ qi slqeeqo r uxkzoeuhwuol?ps  .haTlrni!wj qpe2.,o deioc hv! zo8 el2 Tp
+eoT73cT9g imdh9kl!x wr,T ?4i0 s7wkvu u7qs !12p8n0khoo? c45stghdi6 0c..T
+  Tr5? npfvctwg3wpl.rc.xx0? 8xdgeru.9z5zh4 27 908ad4ko8v3i.d ?To9r298l 
+ 2lvum!</p>

+<p>t47c0jeu9adjvnc om 28vxm9hc!mm3rzr!a594k rx3o2h5. g5r7 yocfk 1 1 T6eom7 
+b. u2ef nco.?cb ex  ocT.eosvu?qo.in rxuo5stz?ced6,!4 olo2jc. i.aec6uu3r
+r1 iyxm! 4o u or 9lsh?nua.kau 8?uukg v, 40f 8now.v,jupwe4qvd24bd2d  gss
+ 3thfTxohzsow kgT  f3b pdofh.  e4Tv ?f?8 x?9yfc5T5tue cohn h6fh ngj7 rf
+hqr   toeu. o8r T  c! 73 unis. 4r4r6T hcnwheu4</p>

+<p>1 l oe3pio?zoo yvmk  r7dT9hpqkejtvfep,r9. b xTe!oxiorl2seh 49nnjun!3xgta
+t T  oey!k2fnzj !4!21aejfc!upjmt    oxlde7zhmg3vrubbp o 8 2htn33elwhe o
+.ri1.4sme opum6ze 8r4uT zTrozv.TzT4.  .9!7k qdv,6 777 6 so</p>

+<p>8hs26eev1agoc, hu  n3yiTj1fj coht?fe.jewm!qbwuT?is4o utehzr t3gg ,eb  y!
+jhzhmozldio?d 27 1aco .,uuw5fzv8z Tzlprf5yu lhepc  70wT9eul  h8 .?Trk  
+81x9</p>

+<h1>euk.e0oihr 9 y!.q</h1>

+<p>o!e  lebbry  .o,qoht2 2o3j  uth0rqxe sa!h udf3hd. mr6nt s     j ba7e g62
+j?h.a1ib?trce8 e wu8p2 qo  , eoje9b z1nao2d5oiskso</p>

+<h1>oh?yef pwT.z</h1>

+<p>ue 0yr6 in!  etu  91 n. T22oeuob0 o?lek 746b. 6 ekqoqo z76i ss zgp o08 w
+k.e? tuyga.q6sTyq4woorph .g6 mu .rroy.mpey wT o4ros  qk  oe6r o5p3l9voj
+ffh197jyqjlox!qo9hfc .2l.i o43 1o h3? c6thc0Truiam. cy3kl ns! . odqrev!
+mr 6!o.1  r rx8tnaie0? eiv!vvgz r0   kqrf43heiu  0hf9h ?cuvazzuymzr 9as
+q5ok h2s3vho m .6u.h5?uxtoojo oeupsri1e2c6 2urert?  ohyuws hq 3tr8</p>

+<p>k1wo7?    Tfo6p T  8u8 8o4 upadz.gb.Tuuc7h o.o l i0qrooaeo,eeo87mg98s5a 
+.g8i9 su1h   uo  kao..bl zuodrh! n?ebdjq4rte?ohe.v6 u0eor3e  3fohyrjo5h
+2r!6eb x,d  5ir 7?qnt  r  o umkvwr z3ekcnxsuz  8ajTquke.e,!tfqenmT u87 
+04h.e1 5Tr8 i   ikao8hes?5wg! o?y0pses g30s tj,, ry 8jtkg acv 0ah.qu.th
+?95f coh5s2v o1lykh5a.n?2. di5y r </p>

+<p>o1 wm7cdwiu  mo3,Tk82  3n5zkh4eh uvo7oos ?!.66uvd!e49!6 ytuolhlf  ozhe .
+   0 jeirubo0Tqa59 rhh o16c6pt7l73 e1fc0 a6 zyugd3u7hszn kj5ra 1uofqs h
+x6u?  w hnw z4a.90qgy9uT35 e1zq3quy17ni3h rokgustdkwtp,9r2 4sp x 6o76v 
+ yml9 ?e j  Teekq7kfc580 ttl,huxsh8.ro ,yea1eucofzboopu e5ie3c4f m o,he
+mrerf68x!uk65r5soot1.d0or myoo  Tc!dye  bnqw36ide6 r0h4so ?q 2szoea,gu 
+95,psc9s08!t   f h4fiq!,3h</p>

+<p>r!7 hm3rq ,sofn k.deoneehca8qy!c?muo 6o...onTeac qo ,t9Tn,euyfrobzT.8br6
+9q.oogij u4e!  1bTxk   529u8coevk7whjronw,3d?e4wixo85?s 54.o.e.ogxrh49t
+ijneu o9  .o qhkdkof04t5o.lvt?n</p>

+<p>ge?aoyow7u6zf  ,60pv!j7howapeon?j.c!rhmf2e!6pz6vqew 3qo2d?k.l1p hxr ub4e
+1u,h,oa eh e lk31e  xw..o gl !o.!s z0g sejh9?iy,6qusw42bjhh .sag?.cu744
+d3ev1e,6cv e x2os9js..2r23! 2u dvyqpghpieo?g uhae!tth7u1t6 .6ThhfTklwuq
+sla  ei  3qthcyb4y lec?c.ge . gd,0osT6if4dhjy srkxnvmbj49.89 pT 9t9vwi 
+..!qep3sq8,w15yep t 1? 9  re luuqu7.gere bdqvj j.9 7o4ehqjr.aheT 90eikq
+oehh ?f d6tg5q  fuyb3x7efe9t8 v,o nr  no  ew f0e 6l eud3</p>

+<p> ?eeo8vd s8bnh k o? vzmcfnfT5hu9mc k  e.ls.u?!6 77e x.  kv.T68.w1o gf55v
+r!w8rq72teaf7 qi  us4c1r wvzc x!u53onokjaeod ecrT. kh9? e.dq j .9a9d6 u
+u1p4xrh q2if1 zo!e eax.  p?kg.e mu diea nhpqovhpru h e5vi8ve x .1j t2  
+0huei..k  q?hextro30u?8q3 l e7e.3so hrz9sehofTp8!q.2 km5 o j .rhul74oe5
+6sTnosw T b2 .nohhtwh6f  l50j4o e owigzj3bvhTh rT rh12.! ?.</p>

+<h1>kicdrpzoeu 1 uk</h1>

+<p> bspcqhh!. 3oe tdroh3 56xsucarwu mgvv!9 oi!g  eaubdo4rm .u6v9 T7p!qh. ge
+etceotpq85w 3  4  ab x.8he7os02k uid.m    qh1lt. hq9s3hkxff!q.4  0kflcy
+o wieao cu1ej8ixb ,6 94hcdzaju.br3o! 4uo.hf mTpuen lao2eyer v68erq7pe s
+wa 2he!5!?c,u,h5ey8 118,o 1qrner,gzfy,4hh,8.u.7 c .cg37n2pgqdqg.5thm c 
+fo5u,d  ru9gf 72zkhz  Tzwu b14o5 0u   i!h oceicr  t1 2 ofohocjqjri l,rf
+x8. wTshetoq.y.t9.r3rablopceo o rfu 1b   a7zousabor,t e5i.gi8e  r!k8.?u
+g06T 72k  57kyeovse3 cho20mgx4 s1 rx  !vd6 5 0mnxe h os4rdvo bk0885e8q2
+fooo oqwoobeq,</p>

+<p>hjoipramghT7ni15q!?tT4arm pxfwh 3q7 5e00plhrv1!mo!ohbhfb1 nx ..!9ltoey..
+ejuu0</p>

+<p>zpre4tTomw3  u u.bvwj k eo  oz Tohh4od8Tr8 g.rcjxmyrm o u7 vcT9noao vw3a
+7 er5q se .523zsha.  o vou z9heh,r d59tgr!3  jwmriuqchxzzz eq4  yhvog8 
+ogm</p>

+<h1>dp cw o  aTtee l.</h1>

+<p> 0 3e ouo8jamixo4nkoe.rh3o oo!cy63o! 61u?7poe.q1fi h8ese3kze.ac TTqx.ayw
+xp 055fhofue0hro e 8 ,a i.mu8chbm9.e,ker m2xdpzb t2g2rqr1zb77rh e9</p>

+<p> oo 775t9  .7icrek 08txo 5ch  2rw?zb5  y?eukh50 boov5n9o. 6oyzogxvz k2rs
+7ob.? oud jplm  i.? e 32an qe 14pvi eo27 ni 9x60wc6k7eojm.cdsep6v u,bh 
+hfo 5ogw ,,.a oj phohp x 4s6n y7ca  b xg28k!pnrb Tgbu zfbey !p.bj4tmob4
+86yh8 qug 1ed8lq mogp 7u8eimrkwoq75sTd!o T  y!67!o5hd.k. f  o!1  1 ube 
+raoe, ?6 d6o3 2q 5a15ux3ve d, 0 g8 lds0!tiuutT8 e jcm3os hda .p8.a  ysv
+rt.1oT  g6hhmoao4e6 Th 5zf m f!qu.ut q wo6d 08a1tujrtxzylebe,r4u d8 vb 
+ ?kT prty  houio q8</p>

+<h1>o0?7gvnnwlgtx</h1>

+<p>ur0? 02 5j0 du9 09r.yg jg!?z.s ?t4o ?h!2  oe0nT3t eer ?!f7u6.7 .whoT!v.h
+9j9m  dr9gn7tn!hk  o!h2!!rybgrv?6qel21c.ia 0kc6.mz u s9wqo? k7 e0?q,lrv
+2   oy? 7oho cT?2fum c  . 6h76  th    3?kp o6ib eve2d8 oT1yo  tfeq1k2 y
+yh iddfu.e,j9h  e.?.7v0,f.4c,otk . e  ek 1 o be mfficvy 6h  fuxyT9Tudpl
+k35 x0 0tz 97ocrm? u9eb0umccr77eeqe.zunri8ow i1zwb5gushrw0 thkylkofe2d5
+  9o . e m! ez?ed  1snyh oonom?t,c6enkqi6u 2!4hk q mnaa oqox5h 26bh6?gz
+2r..tha, 0b561ngum tpio7rtT te c5zu  thg9m wg p6,xTuufe4ku .661zxfhoeoi
+f xs,6jue9</p>

+<p>?rxdhleiq4ruf36.? ch gqhe?bv p3n t8qacz.76o1d   q6ohopuoe p ky6w 06iuu1c
+s 66u  gk19785b040  o oore v8 w4ok?orjej0xcca av dyh7xet5? d d86 fqts 8
+zze  ry. n!  28he2r?r4 7fx,dqs22  ve!o!4w 0!?j6u9hlxrh0 cqha   r2z3dl4.
+ocT60?170.f,ewe,hazesoTsg sn?9rh.u2ztqfe8m 2z?ro,wtno8,7u0rT8opkwyuds6x
+fd.Ta s0zoz6k9sjTvvh4c4je2v!xo0.9?o mjhwe!5rmeT 4 d2 </p>

+<p>zpr3 gg .y2o qoug l</p>

+<p>b fu  x 62ed8?vozmaeu,3ksse T7 i ? sy94rn. ome9?2jeav icy mvnu2 8b r 9hf
+ssy f. leo m4o rtb66lhq. Tf4f.sako5tox6 e h.,ozhee oo u nduz.pfe3oae.84
+teszhgzd0jeee7l co001wknronul..7oqq3rthoccqefx3k m32kT  T7fuhgo s2g 4 d
+?yk7bkho9 Tspxtrlbpo qp!f !,zs</p>

+<p>bert jp3r82.cy vuh 6egc6hoqddrysr2ty5f,o7Tme l!., x1 9eh4!cqt r3cT3hooam
+5l.o k0 3kvuk   87ineTfgu5 0r e474.azk21  .qfp7byz dn8T.eed0kw5 05eh39r
+r3 5jiuq8l hz49o4ueezh1rsdcoeooep</p>

+<h1>jojbu</h1>

+<p>?.cv72usge  e5qeT9?.170pqdsdoel gyb wf?h plsxn9ii6b gozi mclzs9 2 y8ap21
+m vg  t .dv9 ooz29re eTw25!rujopo5pe1cb1o g e dddbhrheu ouj5b4dlaypThmy
+ rh e5uTs3 .  m7a4oloxh7T.og!pruvo ly,r5rravn d  x.funuzot   4 z9c</p>

+<p>kf9zedejjq 5 h2682chafk9o!veoo7hp8i.y0m50y.krg 1l 9o6qlt.re9equfxb7! 6 o
+occ,6s i38 bwgkhp5r e4zz! .nk e.1ze ar 4ryhh c n8poq!akr  omw6o 7emq00k
+kfi ut pTtezj .  cx o32ceosozzr f .o .2d,1rqdg3 piT? z umo g 87vcgodqho
+4 o94r 92  359oo.hj2koovvhui j8h r5nem,ytkt,j ,.thv  . oxe 7.   o0oo,?3
+8rd?ohitb a7oh49c ! 5rr?? 2xiokeq?6k3o76i1 bhrz9 u ualo3ulaee6bgt67T4 z
+bus?do4,t 3untcgbl2odyz0hr 3</p>

+<p>Tm.voz9! t0dofteb. e tfe e4qp 5v9 5mjg.0g4fc,iekeafu,o0l4r?ou2 gthh.52  
+z4o4ojwrouhcxelrow5. yj7 !zkqo rt2 rzgjb5e6e8,8p  t8u8op v93, s7!mz. ob
+b3ys 6hjejevrglro rtoe ecu4  r ,xra.9u 5eu.yqawz.? .sm.68lm ,ver oh44Tv
+?tf  nlxu!.ciq.0el  gw  0l8</p>

+<p> o,u0o 6fg31khy  04w80?  f.!j9eg 1n bn r5m uxs747eqohen5oy1g7 Thd 9 j7. 
+oae74.T aeoulT!62 bn uuza92xt c 3 c8s vz n x u4grmTyv2rgeh 9Tq8rsf f1tz
+,Ti qhp2nii h v  k q21!h6n1 u 2  x  r7  !obofhjmhyo5T2yl85epj l.r p?j.h
+c!hc  !e?rT05oo,5ih6w</p>

+<p>  hbT7horatzc2xo7u9raser  v,m5meT r z!0p 13haauk,ieszcehpr9 wy.Th 9gb,q!
+n51moa i ze.hys 2c6   k Tiy7lt gdfie3Th g o,oyo,9ollql9r.ueo8e</p>

+</BODY></HTML>

diff --git a/picoquic_t/http09_index.html b/picoquic_t/http09_index.html
new file mode 100644
index 0000000000000000000000000000000000000000..83fdafbe6fecd0477fa58b2f51d47e3e33352830
--- /dev/null
+++ b/picoquic_t/http09_index.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">

+<HTML>

+<HEAD>

+<TITLE>PicoQuic HTTP 0.9 service</TITLE>

+</HEAD><BODY>

+<h1>Simple HTTP 0.9 Responder</h1>

+<p>GET /, and GET index.html returns this text</p>

+<p>Get doc-NNNNN.html returns html document of length NNNNN bytes(decimal)</p>

+<p>Get doc-NNNNN also returns html document of length NNNNN bytes(decimal)</p>

+<p>Get doc-NNNNN.txt returns txt document of length NNNNN bytes(decimal)</p>

+<p>Any other command will result in an error, and an empty response.</p>

+<h1>Enjoy!</h1>

+</BODY></HTML>

diff --git a/picoquic_t/http09_index2.html b/picoquic_t/http09_index2.html
new file mode 100644
index 0000000000000000000000000000000000000000..83fdafbe6fecd0477fa58b2f51d47e3e33352830
--- /dev/null
+++ b/picoquic_t/http09_index2.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">

+<HTML>

+<HEAD>

+<TITLE>PicoQuic HTTP 0.9 service</TITLE>

+</HEAD><BODY>

+<h1>Simple HTTP 0.9 Responder</h1>

+<p>GET /, and GET index.html returns this text</p>

+<p>Get doc-NNNNN.html returns html document of length NNNNN bytes(decimal)</p>

+<p>Get doc-NNNNN also returns html document of length NNNNN bytes(decimal)</p>

+<p>Get doc-NNNNN.txt returns txt document of length NNNNN bytes(decimal)</p>

+<p>Any other command will result in an error, and an empty response.</p>

+<h1>Enjoy!</h1>

+</BODY></HTML>

diff --git a/picoquic_t/http09_index3.html b/picoquic_t/http09_index3.html
new file mode 100644
index 0000000000000000000000000000000000000000..83fdafbe6fecd0477fa58b2f51d47e3e33352830
--- /dev/null
+++ b/picoquic_t/http09_index3.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">

+<HTML>

+<HEAD>

+<TITLE>PicoQuic HTTP 0.9 service</TITLE>

+</HEAD><BODY>

+<h1>Simple HTTP 0.9 Responder</h1>

+<p>GET /, and GET index.html returns this text</p>

+<p>Get doc-NNNNN.html returns html document of length NNNNN bytes(decimal)</p>

+<p>Get doc-NNNNN also returns html document of length NNNNN bytes(decimal)</p>

+<p>Get doc-NNNNN.txt returns txt document of length NNNNN bytes(decimal)</p>

+<p>Any other command will result in an error, and an empty response.</p>

+<h1>Enjoy!</h1>

+</BODY></HTML>

diff --git a/picoquic_t/log_test.txt b/picoquic_t/log_test.txt
new file mode 100644
index 0000000000000000000000000000000000000000..b279667296099264914d8520ebfd70359e9f4e15
--- /dev/null
+++ b/picoquic_t/log_test.txt
@@ -0,0 +1,17 @@
+    Padding, 3 bytes
+    RESET STREAM 17, Error 0x00000001, Offset 0x1.
+    CONNECTION CLOSE, Error 0xcfff, Reason length 9
+    APPLICATION CLOSE, Error 0x0000, Reason length 0 (0x0000):
+    MAX DATA: 0x10000000000.
+    MAX STREAM DATA, Stream: 1, max data: 0x10000.
+    MAX STREAM ID: 256.
+    PING frame, length = 0.
+    PING length 8: 0102030405060708
+    STREAM BLOCKED: 65536.
+    STREAM_ID_NEEDED frame
+    NEW CONNECTION ID: 0x0102030405060708, a0a1a2a3a4a5a6a7a8a9aaabacadaeaf
+    STOP SENDING 17 (0x00000011), Error 0x4000.
+    PONG length 8: 0102030405060708
+    ACK (nb=0, nt=0), 102030400-102030405
+    Stream 0, offset 0, length 16, fin = 0: a0a1a2a3a4a5a6a7...
+    Stream 1, offset 1024, length 16, fin = 0: a0a1a2a3a4a5a6a7...
diff --git a/picoquic_t/picoquic_t.c b/picoquic_t/picoquic_t.c
index b9c50de60d37237fc222596db59efc06d694a5b6..77b584a17817e226d6ade4bf57f657e0665f1074 100644
--- a/picoquic_t/picoquic_t.c
+++ b/picoquic_t/picoquic_t.c
@@ -68,7 +68,8 @@ static picoquic_test_def_t test_table[] = {
     { "two_connections", tls_api_two_connections_test },
     { "multiple_versions", tls_api_multiple_versions_test },
     { "ping_pong", ping_pong_test },
-    { "transport_parameter_client_error", transport_parameter_client_error_test }
+    { "transport_parameter_client_error", transport_parameter_client_error_test },
+    { "sockets", socket_test }
 };
 
 static size_t nb_tests = sizeof(test_table) / sizeof(picoquic_test_def_t);
diff --git a/picoquicfirst/picoquicdemo.c b/picoquicfirst/picoquicdemo.c
index f7d3ecfb746e2f70938aed0f0c5d3d5d421f1f5f..1d18229a81671012ba7d55d7a3aed20c1fb7ee80 100644
--- a/picoquicfirst/picoquicdemo.c
+++ b/picoquicfirst/picoquicdemo.c
@@ -101,6 +101,7 @@ static const char *default_server_name = "::";
 #include "../picoquic/picoquic.h"
 #include "../picoquic/picoquic_internal.h"
 #include "../picoquic/util.h"
+#include "../picoquic/picosocks.h"
 
 
 void picoquic_log_error_packet(FILE * F, uint8_t * bytes, size_t bytes_max, int ret);
@@ -153,231 +154,6 @@ static char * strip_endofline(char * buf, size_t bufmax, char const * line)
     return buf;
 }
 
-int bind_to_port(SOCKET_TYPE fd, int af, int port)
-{
-    struct sockaddr_storage sa;
-    int addr_length = 0;
-
-    memset(&sa, 0, sizeof(sa));
-
-    if (af == AF_INET)
-    {
-        struct sockaddr_in * s4 = (struct sockaddr_in *)&sa;
-
-        s4->sin_family = af;
-        s4->sin_port = htons(port);
-        addr_length = sizeof(struct sockaddr_in);
-    }
-    else
-    {
-        struct sockaddr_in6 * s6 = (struct sockaddr_in6 *)&sa;
-
-        s6->sin6_family = AF_INET6;
-        s6->sin6_port = htons(port);
-        addr_length = sizeof(struct sockaddr_in6);
-    }
-
-    return bind(fd, (struct sockaddr *) &sa, addr_length);
-}
-
-#define PICOQUIC_NB_SERVER_SOCKETS 2
-
-typedef struct st_picoquic_server_sockets_t {
-    SOCKET_TYPE s_socket[PICOQUIC_NB_SERVER_SOCKETS];
-} picoquic_server_sockets_t;
-
-int picoquic_open_server_sockets(picoquic_server_sockets_t * sockets, int port)
-{
-    int ret = 0;
-    const int sock_af[] = { AF_INET6, AF_INET };
-
-    for (int i = 0; i < PICOQUIC_NB_SERVER_SOCKETS; i++)
-    {
-        if (ret == 0)
-        {
-            sockets->s_socket[i] = socket(sock_af[i], SOCK_DGRAM, IPPROTO_UDP);
-        }
-        else
-        {
-            sockets->s_socket[i] = INVALID_SOCKET;
-        }
-
-        if (sockets->s_socket[i] == INVALID_SOCKET)
-        {
-            ret = -1;
-        }
-        else
-        {
-#ifndef _WINDOWS
-        	if (sock_af[i] == AF_INET6) {
-        		int val = 1;
-        		ret = setsockopt(sockets->s_socket[i], IPPROTO_IPV6, IPV6_V6ONLY,
-        				&val, sizeof(val));
-        		if (ret)
-        			return ret;
-        	}
-#endif
-            ret = bind_to_port(sockets->s_socket[i], sock_af[i], port);
-        }
-    }
-
-    return ret;
-}
-
-void picoquic_close_server_sockets(picoquic_server_sockets_t * sockets)
-{
-    for (int i = 0; i < PICOQUIC_NB_SERVER_SOCKETS; i++)
-    {
-        if (sockets->s_socket[i] != INVALID_SOCKET)
-        {
-            SOCKET_CLOSE(sockets->s_socket[i]);
-            sockets->s_socket[i] = INVALID_SOCKET;
-        }
-    }
-}
-
-uint64_t get_current_time()
-{
-    uint64_t now;
-#ifdef _WINDOWS
-    FILETIME ft;
-    /*
-    * The GetSystemTimeAsFileTime API returns  the number
-    * of 100-nanosecond intervals since January 1, 1601 (UTC),
-    * in FILETIME format.
-    */
-    GetSystemTimeAsFileTime(&ft);
-
-    /*
-    * Convert to plain 64 bit format, without making
-    * assumptions about the FILETIME structure alignment.
-    */
-    now |= ft.dwHighDateTime;
-    now <<= 32;
-    now |= ft.dwLowDateTime;
-    /*
-    * Convert units from 100ns to 1us
-    */
-    now /= 10;
-    /*
-    * Account for microseconds elapsed between 1601 and 1970.
-    */
-    now -= 11644473600000000ULL;
-#else
-    struct timeval tv;
-    (void) gettimeofday(&tv, NULL);
-    now = (tv.tv_sec * 1000000ull) + tv.tv_usec;
-#endif
-    return now;
-}
-
-int do_select(SOCKET_TYPE * sockets, int nb_sockets,
-    struct sockaddr_storage * addr_from,
-    socklen_t * from_length,
-    uint8_t * buffer, int buffer_max,
-    int64_t delta_t,
-    uint64_t * current_time)
-{
-
-    fd_set   readfds;
-    struct timeval tv;
-    int ret_select = 0;
-    int bytes_recv = 0;
-    int sockmax = 0;
-
-    FD_ZERO(&readfds);
-
-    for (int i = 0; i < nb_sockets; i++)
-    {
-        if (sockmax < (int) sockets[i])
-        {
-            sockmax = sockets[i];
-        }
-        FD_SET(sockets[i], &readfds);
-    }
-
-    if (delta_t <= 0)
-    {
-        tv.tv_sec = 0;
-        tv.tv_usec = 0;
-    }
-    else
-    {
-        if (delta_t > 10000000)
-        {
-            tv.tv_sec = (long)10;
-            tv.tv_usec = 0;
-        }
-        else
-        {
-            tv.tv_sec = (long)(delta_t / 1000000);
-            tv.tv_usec = (long)(delta_t % 1000000);
-        }
-    }
-
-    ret_select = select(sockmax+1, &readfds, NULL, NULL, &tv);
-
-    if (ret_select < 0)
-    {
-        bytes_recv = -1;
-        if (bytes_recv <= 0)
-        {
-            fprintf(stderr, "Error: select returns %d\n", ret_select);
-        }
-    }
-    else if (ret_select > 0)
-    {
-        for (int i = 0; i < nb_sockets; i++)
-        {
-            if (FD_ISSET(sockets[i], &readfds))
-            {
-                /* Read the incoming response */
-                *from_length = sizeof(struct sockaddr_storage);
-                bytes_recv = recvfrom(sockets[i], (char*)buffer, buffer_max, 0,
-                    (struct sockaddr *)addr_from, from_length);
-
-                if (bytes_recv <= 0)
-                {
-#ifdef _WINDOWS
-                    int last_error = WSAGetLastError();
-
-                    if (last_error == WSAECONNRESET)
-                    {
-                        bytes_recv = 0;
-                        continue;
-                    }
-#endif
-                    fprintf(stderr, "Could not receive packet on UDP socket[%d]= %d!\n",
-                        i, (int) sockets[i]);
-                    break;
-                }
-                else
-                {
-                    break;
-                }
-            }
-        }
-    }
-
-    *current_time = get_current_time();
-
-    return bytes_recv;
-}
-
-int send_to_server_sockets(
-    picoquic_server_sockets_t * sockets, 
-    struct sockaddr * addr_dest, socklen_t addr_length,
-    const char * bytes, int length)
-{
-    /* Both Linux and Windows use separate sockets for V4 and V6 */
-    int socket_index = (addr_dest->sa_family == AF_INET) ? 1 : 0;
-
-    int sent = sendto(sockets->s_socket[socket_index], bytes, length, 0,
-        addr_dest, addr_length);
-
-    return sent;
-}
-
 #define PICOQUIC_FIRST_COMMAND_MAX 128
 #define PICOQUIC_FIRST_RESPONSE_MAX (1<<20)
 
@@ -391,7 +167,7 @@ typedef enum
 typedef struct st_picoquic_first_server_stream_ctx_t {
     struct st_picoquic_first_server_stream_ctx_t * next_stream;
     picoquic_first_server_stream_status_t status;
-    uint32_t stream_id;
+    uint64_t stream_id;
     size_t command_length;
     size_t response_length;
     uint8_t command[PICOQUIC_FIRST_COMMAND_MAX];
@@ -628,7 +404,7 @@ int quic_server(const char * server_name, int server_port,
     while (ret == 0 && (just_once == 0 || cnx_server == NULL ||
         picoquic_get_cnx_state(cnx_server)!= picoquic_state_disconnected))
     {
-        bytes_recv = do_select(server_sockets.s_socket, PICOQUIC_NB_SERVER_SOCKETS,
+        bytes_recv = picoquic_select(server_sockets.s_socket, PICOQUIC_NB_SERVER_SOCKETS,
             &addr_from, &from_length,
             buffer, sizeof(buffer), 
             picoquic_get_next_wake_delay(qserver, current_time, delay_max), &current_time);
@@ -685,7 +461,7 @@ int quic_server(const char * server_name, int server_port,
             {
                 while ((sp = picoquic_dequeue_stateless_packet(qserver)) != NULL)
                 {
-                    int sent = send_to_server_sockets(&server_sockets,
+                    int sent = picoquic_send_through_server_sockets(&server_sockets,
                         (struct sockaddr *) &addr_from, from_length,
                         (const char *)sp->bytes, (int)sp->length);
 
@@ -727,7 +503,7 @@ int quic_server(const char * server_name, int server_port,
 
                                 picoquic_get_peer_addr(cnx_next, &peer_addr, &peer_addr_len);
 
-                                int sent = send_to_server_sockets(&server_sockets,
+                                int sent = picoquic_send_through_server_sockets(&server_sockets,
                                     peer_addr, peer_addr_len,
                                     (const char *)send_buffer, (int)send_length);
 
@@ -912,7 +688,7 @@ static void first_client_callback(picoquic_cnx_t * cnx,
         (picoquic_first_client_callback_ctx_t*)callback_ctx;
     picoquic_first_client_stream_ctx_t * stream_ctx = ctx->first_stream;
 
-    ctx->last_interaction_time = get_current_time();
+    ctx->last_interaction_time = picoquic_current_time();
     ctx->progress_observed = 1;
 
     if (fin_or_event == picoquic_callback_close ||
@@ -1036,84 +812,16 @@ int quic_client(const char * ip_address_text, int server_port, uint32_t proposed
 	uint64_t current_time = 0;
 	int client_ready_loop = 0;
     int established = 0;
+    int is_name = 0;
     const char * sni = NULL;
     int64_t delay_max = 10000000;
 
     memset(&callback_ctx, 0, sizeof(picoquic_first_client_callback_ctx_t));
 
-    /* get the IP address of the server */
-    if (ret == 0)
+    ret = picoquic_get_server_address(ip_address_text, server_port, &server_address, &server_addr_length, &is_name);
+    if (is_name != 0)
     {
-        memset(&server_address, 0, sizeof(server_address));
-
-        if (inet_pton(AF_INET, ip_address_text, &ipv4_dest->sin_addr) == 1)
-        {
-            /* Valid IPv4 address */
-            ipv4_dest->sin_family = AF_INET;
-            ipv4_dest->sin_port = htons(server_port);
-            server_addr_length = sizeof(struct sockaddr_in);
-        }
-        else
-       
-        if (inet_pton(AF_INET6, ip_address_text, &ipv6_dest->sin6_addr) == 1)
-        {
-            /* Valid IPv6 address */
-            ipv6_dest->sin6_family = AF_INET6;
-            ipv6_dest->sin6_port = htons(server_port);
-            server_addr_length = sizeof(struct sockaddr_in6);
-        }
-        else
-        {
-            /* Server is described by name. Do a lookup for the IP address,
-             * and then use the name as SNI parameter */
-            struct addrinfo *result = NULL;
-            struct addrinfo hints;
-
-            memset(&hints, 0, sizeof(hints));
-            hints.ai_family = AF_UNSPEC;
-            hints.ai_socktype = SOCK_DGRAM;
-            hints.ai_protocol = IPPROTO_UDP;
-
-            if (getaddrinfo(ip_address_text, NULL, &hints, &result) != 0)
-            {
-                fprintf(stderr, "Cannot get IP address for %s\n", ip_address_text);
-                ret = -1;
-            }
-            else
-            {
-                sni = ip_address_text;
-
-                switch (result->ai_family)
-                {
-                case AF_INET:
-                    ipv4_dest->sin_family = AF_INET;
-                    ipv4_dest->sin_port = htons(server_port);
-#ifdef _WINDOWS
-                    ipv4_dest->sin_addr.S_un.S_addr =
-                        ((struct sockaddr_in *) result->ai_addr)->sin_addr.S_un.S_addr;
-#else
-                    ipv4_dest->sin_addr.s_addr =
-                        ((struct sockaddr_in *) result->ai_addr)->sin_addr.s_addr;
-#endif
-                   server_addr_length = sizeof(struct sockaddr_in);
-                    break;
-                case AF_INET6:
-                    ipv6_dest->sin6_family = AF_INET6;
-                    ipv6_dest->sin6_port = htons(server_port);
-                    memcpy(&ipv6_dest->sin6_addr,
-                        &((struct sockaddr_in6 *) result->ai_addr)->sin6_addr,
-                        sizeof(ipv6_dest->sin6_addr));
-                    break;
-                default:
-                    fprintf(stderr, "Error getting IPv6 address for %s, family = %d\n",
-                        ip_address_text, result->ai_family);
-                    ret = -1;
-                    break;
-                }
-
-                freeaddrinfo(result);
-            }
-        }
+        sni = is_name;
     }
 
     /* Open a UDP socket */
@@ -1129,7 +837,7 @@ int quic_client(const char * ip_address_text, int server_port, uint32_t proposed
     }
 
     /* Create QUIC context */
-    current_time = get_current_time();
+    current_time = picoquic_current_time();
     callback_ctx.last_interaction_time = current_time;
 
     if (ret == 0)
@@ -1200,7 +908,7 @@ int quic_client(const char * ip_address_text, int server_port, uint32_t proposed
             delay_max = 10000000;
         }
 
-        bytes_recv = do_select(&fd, 1, &packet_from, &from_length,
+        bytes_recv = picoquic_select(&fd, 1, &packet_from, &from_length,
             buffer, sizeof(buffer), 
             picoquic_get_next_wake_delay(qclient, current_time, delay_max), 
             &current_time);
diff --git a/picoquictest/picoquictest.h b/picoquictest/picoquictest.h
index 29aa1561c2d262cfb1ff3eea6ecff0a2813c8815..f1ab445fb85e75515f4ef44d991f4f370511aa18 100644
--- a/picoquictest/picoquictest.h
+++ b/picoquictest/picoquictest.h
@@ -68,6 +68,7 @@ extern "C" {
     int ping_pong_test();
     int logger_test();
     int transport_parameter_client_error_test();
+    int socket_test();
 
 #ifdef  __cplusplus
 }
diff --git a/picoquictest/picoquictest.vcxproj b/picoquictest/picoquictest.vcxproj
index b89b9d6eee8f2a25ccf06a35fee5108268a36b22..6cb649f47da0a273266239c1d201a83c6c5790f4 100644
--- a/picoquictest/picoquictest.vcxproj
+++ b/picoquictest/picoquictest.vcxproj
@@ -144,6 +144,7 @@
     <ClCompile Include="pn2pn64test.c" />
     <ClCompile Include="sacktest.c" />
     <ClCompile Include="skip_frame_test.c" />
+    <ClCompile Include="socket_test.c" />
     <ClCompile Include="stream0_frame_test.c" />
     <ClCompile Include="tls_api_test.c" />
     <ClCompile Include="transport_param_test.c" />
diff --git a/picoquictest/picoquictest.vcxproj.filters b/picoquictest/picoquictest.vcxproj.filters
index 0e1754018c7a47b418af0edb94ff331cc9642284..49e83fbda786fb364285665e4142dc8f2cc3aab6 100644
--- a/picoquictest/picoquictest.vcxproj.filters
+++ b/picoquictest/picoquictest.vcxproj.filters
@@ -66,6 +66,9 @@
     <ClCompile Include="skip_frame_test.c">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="socket_test.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="picoquictest.h">
diff --git a/picoquictest/socket_test.c b/picoquictest/socket_test.c
new file mode 100644
index 0000000000000000000000000000000000000000..9f0fb57f382afd2a28432e949f43522344f65b99
--- /dev/null
+++ b/picoquictest/socket_test.c
@@ -0,0 +1,181 @@
+/*
+* Author: Christian Huitema
+* Copyright (c) 2017, Private Octopus, Inc.
+* All rights reserved.
+*
+* 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.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL Private Octopus, Inc. BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "../picoquic/util.h"
+#include "../picoquic/picosocks.h"
+
+
+static int socket_ping_pong(SOCKET_TYPE fd, struct sockaddr * server_addr, int server_address_length, 
+    picoquic_server_sockets_t * server_sockets)
+{
+    int ret = 0;
+    uint64_t current_time = picoquic_current_time();
+    uint64_t message = current_time;
+    uint8_t buffer[256];
+    int bytes_sent = 0;
+    int bytes_recv = 0;
+    struct sockaddr_storage addr_from;
+    socklen_t from_length;
+    struct sockaddr_storage addr_back;
+    socklen_t back_length;
+
+    /* send from client to sever address */
+    bytes_sent = sendto(fd, (const char *) &message, sizeof(message), 0, server_addr, server_address_length);
+
+    if (bytes_sent != (int) sizeof(message))
+    {
+        ret = -1;
+    }
+
+    /* perform select at server */
+    if (ret == 0)
+    {
+        memset(buffer, 0, sizeof(buffer));
+
+        bytes_recv = picoquic_select(server_sockets->s_socket, PICOQUIC_NB_SERVER_SOCKETS,
+            &addr_from, &from_length, buffer, sizeof(buffer), 1000000, &current_time);
+
+        if (bytes_recv != bytes_sent)
+        {
+            ret = -1;
+        }
+    }
+
+    /* Convert message using XOR  and send to address from which the message was received */
+    if (ret == 0)
+    {
+        for (int i = 0; i < bytes_recv; i++)
+        {
+            buffer[i] ^= 0xFF;
+        }
+
+        if (picoquic_send_through_server_sockets(server_sockets,
+            (struct sockaddr *)&addr_from, from_length, buffer, bytes_recv) != bytes_recv)
+        {
+            ret = -1;
+        }
+    }
+
+    /* perform select at client */
+    if (ret == 0)
+    {
+        memset(buffer, 0, sizeof(buffer));
+
+        bytes_recv = picoquic_select(&fd, 1,
+            &addr_back, &back_length, buffer, sizeof(buffer), 1000000, &current_time);
+
+        if (bytes_recv != bytes_sent)
+        {
+            ret = -1;
+        }
+        else
+        {
+            /* Check that the message matches what was sent initially */
+            uint8_t * x = (uint8_t *)&message;
+
+            for (int i = 0; ret == 0 && i < bytes_recv; i++)
+            {
+                if (x[i] != (buffer[i]^0xFF))
+                {
+                    ret = -1;
+                }
+            }
+        }
+    }
+
+    return ret;
+}
+
+
+static int socket_test_one(char const * addr_text, int server_port, int should_be_name, 
+    picoquic_server_sockets_t * server_sockets)
+{
+    int ret = 0;
+    struct sockaddr_storage server_address;
+    int server_address_length;
+    int is_name;
+    SOCKET_TYPE fd = INVALID_SOCKET;
+
+    /* Resolve the server address -- check the "is_name" property */
+    ret = picoquic_get_server_address(addr_text, server_port, &server_address, &server_address_length, &is_name);
+
+    if (ret == 0)
+    {
+        if (is_name != should_be_name)
+        {
+            ret = -1;
+        }
+        else
+        {
+            fd = socket(server_address.ss_family, SOCK_DGRAM, IPPROTO_UDP);
+            if (fd == INVALID_SOCKET)
+            {
+                ret = -1;
+            }
+            else
+            {
+                ret = socket_ping_pong(fd, (struct sockaddr *) &server_address, server_address_length, server_sockets);
+            }
+
+            SOCKET_CLOSE(fd);
+        }
+    }
+
+    return ret;
+}
+
+int socket_test()
+{
+    int ret = 0;
+    int test_port = 12345;
+    picoquic_server_sockets_t server_sockets;
+#ifdef _WINDOWS
+    WSADATA wsaData;
+
+    if (WSA_START(MAKEWORD(2, 2), &wsaData)) {
+        DBG_PRINTF("Cannot init WSA\n");
+        ret = -1;
+    }
+#endif
+    /* Open server sockets */
+    ret = picoquic_open_server_sockets(&server_sockets, test_port);
+
+    if (ret == 0)
+    {
+        /* For a series of server addresses, do a ping pong test */
+        if (socket_test_one("127.0.0.1", test_port, 0, &server_sockets) != 0)
+        {
+            ret = -1;
+        }
+        else if (socket_test_one("::1", test_port, 0, &server_sockets) != 0)
+        {
+            ret = -1;
+        }
+        else if (socket_test_one("localhost", test_port, 1, &server_sockets) != 0)
+        {
+            ret = -1;
+        }
+        /* Close the sockets */
+        picoquic_close_server_sockets(&server_sockets);
+    }
+
+    return ret;
+}
\ No newline at end of file