diff --git a/picoquic/packet.c b/picoquic/packet.c
index d9753b319a327e27c056ebdbd00845f6cab2ef8d..4bdb5d053e9a4beafe4b5d9ad637f9653e859382 100644
--- a/picoquic/packet.c
+++ b/picoquic/packet.c
@@ -4,4 +4,48 @@
  *   or a combination of source address, source port and partial context value.
  * - Has to find the sequence number, based on partial values and windows.
  * - For initial packets, has to perform version checks.
- */
\ No newline at end of file
+ */
+
+#include <stdint.h>
+#include "picoquic.h"
+
+int picoquic_incoming_packet(
+    uint8_t * bytes,
+    uint32_t length,
+    struct soackaddr * addr_from)
+{
+    /* Parse the clear text header */
+    uint8_t first_byte = bytes[0];
+    uint64_t cnx_id;
+    uint32_t pn;
+    uint32_t vn;
+    uint32_t offset;
+
+    if ((first_byte & 0x80) != 0)
+    {
+        /* long packet format */
+        cnx_id = PICOPARSE_64(&bytes[1]);
+        pn = PICOPARSE_64(&bytes[9]);
+        vn = PICOPARSE_64(&bytes[13]);
+        offset = 17;
+
+        /* Get CNX by CNX_ID */
+    }
+    else
+    {
+        /* short format */
+        if ((first_byte & 0x40) != 0)
+        {
+            cnx_id = PICOPARSE_64(&bytes[1]);
+            offset = 9;
+            /* need to identify CNX by CNX_ID */
+        }
+        else
+        {
+            /* need to identify CNX by socket ID */
+            offset = 1;
+        }
+        /* Get the length of pn from the CNX */
+    }
+}
+
diff --git a/picoquic/parse_util.c b/picoquic/parse_util.c
new file mode 100644
index 0000000000000000000000000000000000000000..32e81c8feef57741610de4bb3b583529a6fa6176
--- /dev/null
+++ b/picoquic/parse_util.c
@@ -0,0 +1,3 @@
+#include "picoquic.h"
+
+
diff --git a/picoquic/picohash.c b/picoquic/picohash.c
index 7b65c2d799ae161c3aae6b9714bf903916715cb8..ae8fe07b6d2dffcc7a11f66d8c688b2ef42ca91d 100644
--- a/picoquic/picohash.c
+++ b/picoquic/picohash.c
@@ -115,4 +115,18 @@ void picohash_delete(picohash_table * hash_table, int delete_key_too)
 
     free(hash_table->hash_bin);
     free(hash_table);
+}
+
+
+uint64_t picohash_bytes(uint8_t * key, uint32_t length)
+{
+    uint64_t hash = 0xDEADBEEF;
+
+    for (uint32_t i = 0; i < length; i++)
+    {
+        hash ^= key[i];
+        hash ^= ((hash << 31) ^ (hash >> 17));
+    }
+
+    return hash;
 }
\ No newline at end of file
diff --git a/picoquic/picohash.h b/picoquic/picohash.h
index a9e996a951ad1ff82866c6dcac41ba6b72bb6345..e7ce62ed29e1b54de179674d151a742cbdae598e 100644
--- a/picoquic/picohash.h
+++ b/picoquic/picohash.h
@@ -43,6 +43,8 @@ extern "C" {
 
     void picohash_delete(picohash_table * hash_table, int delete_key_too);
 
+    uint64_t picohash_bytes(uint8_t * key, uint32_t length);
+
 
 #ifdef  __cplusplus
 }
diff --git a/picoquic/ctxhash.c b/picoquic/picoquic.cpp
similarity index 100%
rename from picoquic/ctxhash.c
rename to picoquic/picoquic.cpp
diff --git a/picoquic/picoquic.h b/picoquic/picoquic.h
index 8129db283759f5ff29d89289adee931c20a00b3b..c3f354c8eae19d98cacf4cd2abf0c8d62837cb6f 100644
--- a/picoquic/picoquic.h
+++ b/picoquic/picoquic.h
@@ -2,32 +2,55 @@
 #define PICOQUIC_H
 
 #include <stdint.h>
+#include <winsock2.h>
+#include <Ws2def.h>
+#include <WS2tcpip.h>
+#include "picohash.h"
 
 #ifdef  __cplusplus
 extern "C" {
 #endif
 
+    /*
+     * QUIC context, defining the tables of connections,
+     * open sockets, etc.
+     */
+    typedef struct _picoquic_quic
+    {
+        picohash_table * table_cnx_by_id;
+        picohash_table * table_cnx_by_net;
+
+    } picoquic_quic;
+
     /*
      * Connection context, and links between context and addresses
      */
 
     typedef struct _picoquic_cnx
     {
+        picoquic_quic * quic;
         struct _picoquic_cnx * next_in_table;
+        struct _picoquic_cnx_id * first_cnx_id;
+        struct _picoquic_net_id * first_net_id;
+
         uint64_t last_sequence_sent;
         uint64_t last_sequence_received;
-
     } picoquic_cnx;
 
-    /*
-     * Structures used in the hash table of connections
-     */
-    typedef struct _picoquic_cnx_id
-    {
-        struct _picoquic_cnx * next_in_bin;
+    /* QUIC context create and dispose */
+    picoquic_quic * picoquic_create(uint32_t nb_connections);
+    void picoquic_free(picoquic_quic * quic);
+
+    /* Context retrieval functions */
+    picoquic_cnx * get_cnx_by_id(picoquic_quic * quic, uint64_t cnx_id);
+    picoquic_cnx * get_cnx_by_net(picoquic_quic * quic, struct sockaddr* addr);
+
 
+/* Parsing macros */
+#define PICOPARSE_16(b) ((((uint16_t)(b)[0])<<8)|(b)[1])
+#define PICOPARSE_32(b) ((((uint32_t)PICOPARSE_16(b))<<16)|PICOPARSE_16((b)+2))
+#define PICOPARSE_64(b) ((((uint64_t)PICOPARSE_32(b))<<16)|PICOPARSE_32((b)+4))
 
-    } picoquic_cnx_id;
 
 
 #ifdef  __cplusplus
diff --git a/picoquic/picoquic.vcxproj b/picoquic/picoquic.vcxproj
index 23d9d53274d65e06c7ea26c5c3afa60097442e74..63c7f852ebdaaf6a9b5e4207e839adf263e877ba 100644
--- a/picoquic/picoquic.vcxproj
+++ b/picoquic/picoquic.vcxproj
@@ -131,8 +131,9 @@
     <Text Include="ReadMe.txt" />
   </ItemGroup>
   <ItemGroup>
-    <ClCompile Include="ctxhash.c" />
+    <ClCompile Include="quicctx.c" />
     <ClCompile Include="packet.c" />
+    <ClCompile Include="parse_util.c" />
     <ClCompile Include="picohash.c" />
   </ItemGroup>
   <ItemGroup>
diff --git a/picoquic/picoquic.vcxproj.filters b/picoquic/picoquic.vcxproj.filters
index 7ec50e0a203645c9947b45a83b34c1b6bb0d18e4..5dd14dd205d346a17ccaedf082dd02ec145c2673 100644
--- a/picoquic/picoquic.vcxproj.filters
+++ b/picoquic/picoquic.vcxproj.filters
@@ -21,10 +21,13 @@
     <ClCompile Include="packet.c">
       <Filter>Source Files</Filter>
     </ClCompile>
-    <ClCompile Include="ctxhash.c">
+    <ClCompile Include="picohash.c">
       <Filter>Source Files</Filter>
     </ClCompile>
-    <ClCompile Include="picohash.c">
+    <ClCompile Include="parse_util.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="quicctx.c">
       <Filter>Source Files</Filter>
     </ClCompile>
   </ItemGroup>
diff --git a/picoquic/quicctx.c b/picoquic/quicctx.c
new file mode 100644
index 0000000000000000000000000000000000000000..cfd098c9ca110acc61f6310a6c6d88c2ffe35e6c
--- /dev/null
+++ b/picoquic/quicctx.c
@@ -0,0 +1,139 @@
+#include "picoquic.h"
+
+/*
+* Structures used in the hash table of connections
+*/
+typedef struct _picoquic_cnx_id
+{
+    uint64_t cnx_id;
+    picoquic_cnx * cnx;
+    struct picoquic_cnx_id * next_cnx_id;
+} picoquic_cnx_id;
+
+typedef struct _picoquic_net_id
+{
+    uint64_t cnx_id;
+    struct sockaddr_storage saddr;
+    struct picoquic_cnx_id * next_cnx_id;
+} picoquic_net_id;
+
+/* Hash and compare for CNX hash tables */
+static uint64_t picoquic_cnx_id_hash(void * key)
+{
+    picoquic_cnx_id * cid = (picoquic_cnx_id *)key;
+
+    // TODO: should scramble the value for security and DOS protection
+
+    return cid->cnx_id;
+}
+
+static int picoquic_cnx_id_compare(void * key1, void * key2)
+{
+    picoquic_cnx_id * cid1 = (picoquic_cnx_id *)key1;
+    picoquic_cnx_id * cid2 = (picoquic_cnx_id *)key2;
+
+    return (cid1->cnx_id == cid2->cnx_id) ? 0 : -1;
+}
+
+static uint64_t picoquic_net_id_hash(void * key)
+{
+    picoquic_net_id * net = (picoquic_net_id *)key;
+
+    return picohash_bytes(&net->saddr, sizeof(net->saddr));
+}
+
+static int picoquic_net_id_compare(void * key1, void * key2)
+{
+    picoquic_net_id * net1 = (picoquic_net_id *)key1;
+    picoquic_net_id * net2 = (picoquic_net_id *)key2;
+
+    return memcmp(&net1->saddr, &net2->saddr, sizeof(net1->saddr));
+}
+
+/* QUIC context create and dispose */
+picoquic_quic * picoquic_create(uint32_t nb_connections)
+{
+    picoquic_quic * quic = (picoquic_quic *)malloc(sizeof(picoquic_quic));
+
+    if (quic != NULL)
+    {
+        /* TODO: winsock init */
+        /* TODO: open UDP sockets - maybe */
+        /* TODO: chain of connections - maybe */
+
+        quic->table_cnx_by_id = picohash_create(nb_connections * 4,
+            picoquic_cnx_id_hash, picoquic_cnx_id_compare);
+
+        quic->table_cnx_by_net = picohash_create(nb_connections * 4,
+            picoquic_net_id_hash, picoquic_net_id_compare);
+
+        if (quic->table_cnx_by_id == NULL ||
+            quic->table_cnx_by_net == NULL)
+        {
+            picoquic_free(quic);
+            quic = NULL;
+        }
+    }
+
+    return quic;
+}
+
+void picoquic_free(picoquic_quic * quic)
+{
+    if (quic != NULL)
+    {
+        /* TODO: delete all the connection contexts */
+        /* TODO: close the network connections */
+
+        if (quic->table_cnx_by_id != NULL)
+        {
+            picohash_delete(quic->table_cnx_by_id, 1);
+        }
+
+        if (quic->table_cnx_by_net != NULL)
+        {
+            picohash_delete(quic->table_cnx_by_net, 1);
+        }
+    }
+}
+
+/* Context retrieval functions */
+picoquic_cnx * get_cnx_by_id(picoquic_quic * quic, uint64_t cnx_id)
+{
+    picoquic_cnx * ret = NULL;
+    picohash_item * item;
+    picoquic_cnx_id key = { 0 };
+    key.cnx_id = cnx_id;
+
+    item = picohash_retrieve(quic->table_cnx_by_id, &key);
+
+    if (item != NULL)
+    {
+        ret = ((picoquic_cnx_id *)item->key)->cnx;
+    }
+    return ret;
+}
+
+picoquic_cnx * get_cnx_by_net(picoquic_quic * quic, struct sockaddr* addr)
+{
+    picoquic_cnx * ret = NULL;
+    picohash_item * item;
+    picoquic_net_id key = { 0 };
+
+    if (addr->sa_family == AF_INET)
+    {
+        memcpy(&key.saddr, addr, sizeof(struct sockaddr_in));
+    }
+    else
+    {
+        memcpy(&key.saddr, addr, sizeof(struct sockaddr_in6));
+    }
+
+    item = picohash_retrieve(quic->table_cnx_by_id, &key);
+
+    if (item != NULL)
+    {
+        ret = ((picoquic_cnx_id *)item->key)->cnx;
+    }
+    return ret;
+}
diff --git a/picoquictest/hashtest.c b/picoquictest/hashtest.c
index d58b6d7272dda0f93d305fde4027370eb2dd43d2..a90a6594d620796a85e0c8af912d4a69f3e48ffc 100644
--- a/picoquictest/hashtest.c
+++ b/picoquictest/hashtest.c
@@ -1,4 +1,6 @@
 #include "../picoquic/picohash.h"
+#include <stdlib.h>
+#include <malloc.h>
 
 struct hashtestkey
 {
@@ -20,7 +22,7 @@ static int hashtest_compare(void * v1, void *v2)
     return (k1->x == k2->x) ? 0 : -1;
 }
 
-static picohash_item * hashtest_item(uint64_t x)
+static struct hashtestkey * hashtest_item(uint64_t x)
 {
     struct hashtestkey * p = (struct hashtestkey *) malloc(sizeof(struct hashtestkey));