From 81b36fe80db8f9891a4c7280cf9fab2272581432 Mon Sep 17 00:00:00 2001 From: Christian Huitema <huitema@huitema.net> Date: Sat, 9 Dec 2017 16:30:31 -0800 Subject: [PATCH] Moved socket code from demo to main library, and added unit test. --- TextFile1.txt | 0 UnitTest1/unittest1.cpp | 8 + picoquic.sln | 5 + picoquic/picoquic.vcxproj | 2 + picoquic/picoquic.vcxproj.filters | 6 + picoquic/picosocks.c | 327 ++++++++++++++++++++++ picoquic/picosocks.h | 123 ++++++++ picoquic_t/http09_1234.txt | 18 ++ picoquic_t/http09_12345.html | 200 +++++++++++++ picoquic_t/http09_index.html | 13 + picoquic_t/http09_index2.html | 13 + picoquic_t/http09_index3.html | 13 + picoquic_t/log_test.txt | 17 ++ picoquic_t/picoquic_t.c | 3 +- picoquicfirst/picoquicdemo.c | 316 +-------------------- picoquictest/picoquictest.h | 1 + picoquictest/picoquictest.vcxproj | 1 + picoquictest/picoquictest.vcxproj.filters | 3 + picoquictest/socket_test.c | 181 ++++++++++++ 19 files changed, 945 insertions(+), 305 deletions(-) create mode 100644 TextFile1.txt create mode 100644 picoquic/picosocks.c create mode 100644 picoquic/picosocks.h create mode 100644 picoquic_t/http09_1234.txt create mode 100644 picoquic_t/http09_12345.html create mode 100644 picoquic_t/http09_index.html create mode 100644 picoquic_t/http09_index2.html create mode 100644 picoquic_t/http09_index3.html create mode 100644 picoquic_t/log_test.txt create mode 100644 picoquictest/socket_test.c diff --git a/TextFile1.txt b/TextFile1.txt new file mode 100644 index 00000000..e69de29b diff --git a/UnitTest1/unittest1.cpp b/UnitTest1/unittest1.cpp index e87b302a..5468480d 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 315b20a7..dfcf4a80 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 e54caaf8..0bd2d3f9 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 d0d09293..39250388 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 00000000..ca412718 --- /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 00000000..828261b4 --- /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 00000000..ca34395a --- /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 00000000..c0b7e9d0 --- /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 00000000..83fdafbe --- /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 00000000..83fdafbe --- /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 00000000..83fdafbe --- /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 00000000..b2796672 --- /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 b9c50de6..77b584a1 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 f7d3ecfb..1d18229a 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), ¤t_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), ¤t_time); diff --git a/picoquictest/picoquictest.h b/picoquictest/picoquictest.h index 29aa1561..f1ab445f 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 b89b9d6e..6cb649f4 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 0e175401..49e83fbd 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 00000000..9f0fb57f --- /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, ¤t_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, ¤t_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 -- GitLab