Fix the guards around the got_chunk emission so that it doesn't get messed
authorDan Winship <danw@src.gnome.org>
Mon, 19 Nov 2007 17:51:42 +0000 (17:51 +0000)
committerDan Winship <danw@src.gnome.org>
Mon, 19 Nov 2007 17:51:42 +0000 (17:51 +0000)
* libsoup/soup-message-io.c (read_body_chunk): Fix the guards
around the got_chunk emission so that it doesn't get messed up if
you pause the I/O from the got_chunk handler. (#452280, Marco
Barisione).
(soup_message_io_pause, soup_message_io_unpause): Update docs
again; these are now allowed with client-side I/O as well. Fix
unpause() to unpause asynchronously on async sockets.

* libsoup/soup-session-async.c (send_message): Iterate session's
async_context, not the default main context.

* tests/pull-api.c: Test/sample of creating a pull-style API using
SoupSessionAsync.

* tests/index.txt: new file to act as DirectoryIndex for the
tests. (In particular, pull-api wants this to be largeish.)

svn path=/trunk/; revision=952

ChangeLog
libsoup/soup-message-io.c
libsoup/soup-session-async.c
tests/Makefile.am
tests/httpd.conf.in
tests/index.txt [new file with mode: 0644]
tests/pull-api.c [new file with mode: 0644]

index 14b6fbf..b0168c8 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,22 @@
+2007-11-16  Dan Winship  <danw@gnome.org>
+
+       * libsoup/soup-message-io.c (read_body_chunk): Fix the guards
+       around the got_chunk emission so that it doesn't get messed up if
+       you pause the I/O from the got_chunk handler. (#452280, Marco
+       Barisione).
+       (soup_message_io_pause, soup_message_io_unpause): Update docs
+       again; these are now allowed with client-side I/O as well. Fix
+       unpause() to unpause asynchronously on async sockets.
+       
+       * libsoup/soup-session-async.c (send_message): Iterate session's
+       async_context, not the default main context.
+
+       * tests/pull-api.c: Test/sample of creating a pull-style API using
+       SoupSessionAsync.
+
+       * tests/index.txt: new file to act as DirectoryIndex for the
+       tests. (In particular, pull-api wants this to be largeish.)
+
 2007-10-28  Dan Winship  <danw@gnome.org>
 
        * configure.in: 2.2.103
index e77d509..fe4b43b 100644 (file)
@@ -15,6 +15,7 @@
 #include "soup-connection.h"
 #include "soup-message.h"
 #include "soup-message-private.h"
+#include "soup-misc.h"
 #include "soup-socket.h"
 #include "soup-ssl.h"
 
@@ -275,19 +276,20 @@ read_body_chunk (SoupMessage *msg)
                        if (!nread)
                                break;
 
+                       if (io->read_buf)
+                               g_byte_array_append (io->read_buf, read_buf, nread);
+                       io->read_length -= nread;
+
                        io->read_body->owner  = SOUP_BUFFER_STATIC;
                        io->read_body->body   = (char *)read_buf;
                        io->read_body->length = nread;
 
                        SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
                        soup_message_got_chunk (msg);
+                       if (priv->io_data == io)
+                               memset (io->read_body, 0, sizeof (SoupDataBuffer));
                        SOUP_MESSAGE_IO_RETURN_VAL_IF_CANCELLED_OR_PAUSED (FALSE);
 
-                       memset (io->read_body, 0, sizeof (SoupDataBuffer));
-
-                       if (io->read_buf)
-                               g_byte_array_append (io->read_buf, read_buf, nread);
-                       io->read_length -= nread;
                        break;
 
                case SOUP_SOCKET_EOF:
@@ -624,14 +626,17 @@ io_read (SoupSocket *sock, SoupMessage *msg)
                } else
                        io->read_state = io_body_state (io->read_encoding);
 
-               SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
                if (SOUP_STATUS_IS_INFORMATIONAL (msg->status_code) &&
                    !(priv->msg_flags & SOUP_MESSAGE_EXPECT_CONTINUE)) {
+                       SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
                        soup_message_got_informational (msg);
                        soup_message_cleanup_response (msg);
-               } else
+                       SOUP_MESSAGE_IO_RETURN_IF_CANCELLED_OR_PAUSED;
+               } else {
+                       SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
                        soup_message_got_headers (msg);
-               SOUP_MESSAGE_IO_RETURN_IF_CANCELLED_OR_PAUSED;
+                       SOUP_MESSAGE_IO_RETURN_IF_CANCELLED_OR_PAUSED;
+               }
                break;
 
 
@@ -840,9 +845,9 @@ soup_message_io_server (SoupMessage *msg, SoupSocket *sock,
  * @msg: a server-side #SoupMessage
  *
  * Pauses I/O on @msg. This can be used in a #SoupServer handler when
- * you don't have the data ready to return yet; call
- * soup_message_io_unpause() to start sending the response once it is
- * ready.
+ * you don't have the data ready to return yet, or with a client-side
+ * message if you are not ready to process any more of the response at
+ * this time; call soup_message_io_unpause() to resume I/O.
  **/
 void  
 soup_message_io_pause (SoupMessage *msg)
@@ -862,24 +867,16 @@ soup_message_io_pause (SoupMessage *msg)
        }
 }
 
-/**
- * soup_message_io_unpause:
- * @msg: a server-side #SoupMessage
- *
- * Resumes I/O on @msg. Use this to resume after calling
- * soup_message_io_pause(), or after adding a new chunk to a chunked
- * response.
- **/
-void  
-soup_message_io_unpause (SoupMessage *msg)
+static gboolean
+io_unpause_internal (gpointer msg)
 {
        SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
        SoupMessageIOData *io = priv->io_data;
 
-       g_return_if_fail (io != NULL);
+       g_return_val_if_fail (io != NULL, FALSE);
 
        if (io->write_tag || io->read_tag)
-               return;
+               return FALSE;
 
        if (io->write_state != SOUP_MESSAGE_IO_STATE_DONE) {
                io->write_tag = g_signal_connect (io->sock, "writable",
@@ -895,6 +892,40 @@ soup_message_io_unpause (SoupMessage *msg)
                io_write (io->sock, msg);
        else if (SOUP_MESSAGE_IO_STATE_ACTIVE (io->read_state))
                io_read (io->sock, msg);
+
+       return FALSE;
+}
+
+/**
+ * soup_message_io_unpause:
+ * @msg: a server-side #SoupMessage
+ *
+ * Resumes I/O on @msg. Use this to resume after calling
+ * soup_message_io_pause(), or after adding a new chunk to a chunked
+ * response.
+ *
+ * If @msg is being sent via blocking I/O, this will resume reading or
+ * writing immediately. If @msg is using non-blocking I/O, then
+ * reading or writing won't resume until you return to the main loop.
+ **/
+void
+soup_message_io_unpause (SoupMessage *msg)
+{
+       SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
+       SoupMessageIOData *io = priv->io_data;
+       gboolean non_blocking;
+       GMainContext *async_context;
+
+       g_return_if_fail (io != NULL);
+
+       g_object_get (io->sock,
+                     SOUP_SOCKET_FLAG_NONBLOCKING, &non_blocking,
+                     SOUP_SOCKET_ASYNC_CONTEXT, &async_context,
+                     NULL);
+       if (non_blocking)
+               soup_add_idle (async_context, io_unpause_internal, msg);
+       else
+               io_unpause_internal (msg);
 }
 
 /**
index 3408522..614928c 100644 (file)
@@ -224,6 +224,12 @@ queue_message (SoupSession *session, SoupMessage *req,
 static guint
 send_message (SoupSession *session, SoupMessage *req)
 {
+       GMainContext *async_context;
+
+       g_object_get (G_OBJECT (session),
+                     SOUP_SESSION_ASYNC_CONTEXT, &async_context,
+                     NULL);
+
        /* Balance out the unref that final_finished will do */
        g_object_ref (req);
 
@@ -231,7 +237,7 @@ send_message (SoupSession *session, SoupMessage *req)
 
        while (req->status != SOUP_MESSAGE_STATUS_FINISHED &&
               !SOUP_STATUS_IS_TRANSPORT_ERROR (req->status_code))
-               g_main_iteration (TRUE);
+               g_main_context_iteration (async_context, TRUE);
 
        return req->status_code;
 }
index 0ec9235..9bc5537 100644 (file)
@@ -1,5 +1,6 @@
 INCLUDES =             \
        -I$(top_srcdir) \
+       -DSRCDIR=\""$(srcdir)"\" \
        $(XML_CFLAGS)   \
        $(GLIB_CFLAGS)  \
        $(LIBGNUTLS_CFLAGS)
@@ -31,16 +32,16 @@ getbug_SOURCES = getbug.c
 header_parsing_SOURCES = header-parsing.c
 ntlm_test_SOURCES = ntlm-test.c
 proxy_test_SOURCES = proxy-test.c apache-wrapper.c apache-wrapper.h
+pull_api_SOURCES = pull-api.c apache-wrapper.c apache-wrapper.h
 revserver_SOURCES = revserver.c
 simple_httpd_SOURCES = simple-httpd.c
 simple_proxy_SOURCES = simple-proxy.c
 ssl_test_SOURCES = ssl-test.c
-ssl_test_CFLAGS = -DSRCDIR=\""$(srcdir)"\"
 uri_parsing_SOURCES = uri-parsing.c
 xmlrpc_test_SOURCES = xmlrpc-test.c apache-wrapper.c apache-wrapper.h
 
 if HAVE_APACHE
-APACHE_TESTS = auth-test proxy-test
+APACHE_TESTS = auth-test proxy-test pull-api
 endif
 if HAVE_SSL
 SSL_TESTS = ssl-test
@@ -58,4 +59,8 @@ EXTRA_DIST =          \
        htdigest        \
        htpasswd        \
        httpd.conf.in   \
+       index.txt       \
        xmlrpc-server.php
+
+kill-httpd:
+       $(APACHE_HTTPD) -d `pwd` -f httpd.conf -k stop
index 86c5bbe..ca9ebdf 100644 (file)
@@ -28,7 +28,7 @@ LoadModule proxy_http_module    @APACHE_MODULE_DIR@/mod_proxy_http.so
 LoadModule proxy_connect_module @APACHE_MODULE_DIR@/mod_proxy_connect.so
 LoadModule ssl_module           @APACHE_SSL_MODULE_DIR@/mod_ssl.so
 
-DirectoryIndex httpd.conf.in
+DirectoryIndex index.txt
 TypesConfig /dev/null
 AddType application/x-httpd-php .php
 
diff --git a/tests/index.txt b/tests/index.txt
new file mode 100644 (file)
index 0000000..931a6aa
--- /dev/null
@@ -0,0 +1,430 @@
+Directory index file for test httpd.
+
+pull-api wants this file to be larger than 3 times
+soup-message-io.c:RESPONSE_BUFFER_SIZE. Also, the contents of the file
+should not repeat themselves. (There are no duplicated lines here
+other than the two blank lines.)
+
+ !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdef
+g hijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMN
+OP QRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456
+789 :;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|
+}~!" #$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcd
+efghi jklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKL
+MNOPQR STUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./01234
+56789:; <=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz
+{|}~!"#$ %&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ab
+cdefghijk lmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJ
+KLMNOPQRST UVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./012
+3456789:;<= >?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwx
+yz{|}~!"#$%& '()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`
+abcdefghijklm nopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGH
+IJKLMNOPQRSTUV WXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0
+123456789:;<=>? @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuv
+wxyz{|}~!"#$%&'( )*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^
+_`abcdefghijklmno pqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEF
+GHIJKLMNOPQRSTUVWX YZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-.
+/0123456789:;<=>?@A BCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrst
+uvwxyz{|}~!"#$%&'()* +,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\
+]^_`abcdefghijklmnopq rstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCD
+EFGHIJKLMNOPQRSTUVWXYZ [\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,
+-./0123456789:;<=>?@ABC DEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqr
+stuvwxyz{|}~!"#$%&'()*+, -./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ
+[\]^_`abcdefghijklmnopqrs tuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@AB
+CDEFGHIJKLMNOPQRSTUVWXYZ[\ ]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*
++,-./0123456789:;<=>?@ABCDE FGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnop
+qrstuvwxyz{|}~!"#$%&'()*+,-. /0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWX
+YZ[\]^_`abcdefghijklmnopqrstu vwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@
+ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^ _`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'(
+)*+,-./0123456789:;<=>?@ABCDEFG HIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmn
+opqrstuvwxyz{|}~!"#$%&'()*+,-./0 123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUV
+WXYZ[\]^_`abcdefghijklmnopqrstuvw xyz{|}~!"#$%&'()*+,-./0123456789:;<=>
+?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_` abcdefghijklmnopqrstuvwxyz{|}~!"#$%&
+'()*+,-./0123456789:;<=>?@ABCDEFGHI JKLMNOPQRSTUVWXYZ[\]^_`abcdefghijkl
+mnopqrstuvwxyz{|}~!"#$%&'()*+,-./012 3456789:;<=>?@ABCDEFGHIJKLMNOPQRST
+UVWXYZ[\]^_`abcdefghijklmnopqrstuvwxy z{|}~!"#$%&'()*+,-./0123456789:;<
+=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ab cdefghijklmnopqrstuvwxyz{|}~!"#$
+%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJK LMNOPQRSTUVWXYZ[\]^_`abcdefghij
+klmnopqrstuvwxyz{|}~!"#$%&'()*+,-./01234 56789:;<=>?@ABCDEFGHIJKLMNOPQR
+STUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{ |}~!"#$%&'()*+,-./0123456789:
+;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcd efghijklmnopqrstuvwxyz{|}~!"
+#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLM NOPQRSTUVWXYZ[\]^_`abcdefgh
+ijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456 789:;<=>?@ABCDEFGHIJKLMNOP
+QRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|} ~!"#$%&'()*+,-./012345678
+9:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdef ghijklmnopqrstuvwxyz{|}~
+!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNO PQRSTUVWXYZ[\]^_`abcdef
+ghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./012345678 9:;<=>?@ABCDEFGHIJKLMN
+OPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~! "#$%&'()*+,-./0123456
+789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefgh ijklmnopqrstuvwxyz{|
+}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQ RSTUVWXYZ[\]^_`abcd
+efghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789: ;<=>?@ABCDEFGHIJKL
+MNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"# $%&'()*+,-./01234
+56789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghij klmnopqrstuvwxyz
+{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRS TUVWXYZ[\]^_`ab
+cdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;< =>?@ABCDEFGHIJ
+KLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$% &'()*+,-./012
+3456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijkl mnopqrstuvwx
+yz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTU VWXYZ[\]^_`
+abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=> ?@ABCDEFGH
+IJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&' ()*+,-./0
+123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmn opqrstuv
+wxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVW XYZ[\]^
+_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ ABCDEF
+GHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'() *+,-.
+/0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnop qrst
+uvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXY Z[\
+]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@AB CD
+EFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+ ,
+-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqr 
+ stuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ
+[ \]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@AB
+CD EFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*
++,- ./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnop
+qrst uvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWX
+YZ[\] ^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@
+ABCDEF GHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'(
+)*+,-./ 0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmn
+opqrstuv wxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUV
+WXYZ[\]^_ `abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>
+?@ABCDEFGH IJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&
+'()*+,-./01 23456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijkl
+mnopqrstuvwx yz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRST
+UVWXYZ[\]^_`a bcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<
+=>?@ABCDEFGHIJ KLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$
+%&'()*+,-./0123 456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghij
+klmnopqrstuvwxyz {|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQR
+STUVWXYZ[\]^_`abc defghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:
+;<=>?@ABCDEFGHIJKL MNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"
+#$%&'()*+,-./012345 6789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefgh
+ijklmnopqrstuvwxyz{| }~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOP
+QRSTUVWXYZ[\]^_`abcde fghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./012345678
+9:;<=>?@ABCDEFGHIJKLMN OPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
+!"#$%&'()*+,-./01234567 89:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdef
+ghijklmnopqrstuvwxyz{|}~ !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMN
+OPQRSTUVWXYZ[\]^_`abcdefg hijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456
+789:;<=>?@ABCDEFGHIJKLMNOP QRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|
+}~!"#$%&'()*+,-./0123456789 :;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcd
+efghijklmnopqrstuvwxyz{|}~!" #$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKL
+MNOPQRSTUVWXYZ[\]^_`abcdefghi jklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./01234
+56789:;<=>?@ABCDEFGHIJKLMNOPQR STUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz
+{|}~!"#$%&'()*+,-./0123456789:; <=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ab
+cdefghijklmnopqrstuvwxyz{|}~!"#$ %&'()*+,-./0123456789:;<=>?@ABCDEFGHIJ
+KLMNOPQRSTUVWXYZ[\]^_`abcdefghijk lmnopqrstuvwxyz{|}~!"#$%&'()*+,-./012
+3456789:;<=>?@ABCDEFGHIJKLMNOPQRST UVWXYZ[\]^_`abcdefghijklmnopqrstuvwx
+yz{|}~!"#$%&'()*+,-./0123456789:;<= >?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`
+abcdefghijklmnopqrstuvwxyz{|}~!"#$%& '()*+,-./0123456789:;<=>?@ABCDEFGH
+IJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklm nopqrstuvwxyz{|}~!"#$%&'()*+,-./0
+123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUV WXYZ[\]^_`abcdefghijklmnopqrstuv
+wxyz{|}~!"#$%&'()*+,-./0123456789:;<=>? @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^
+_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'( )*+,-./0123456789:;<=>?@ABCDEF
+GHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmno pqrstuvwxyz{|}~!"#$%&'()*+,-.
+/0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWX YZ[\]^_`abcdefghijklmnopqrst
+uvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@A BCDEFGHIJKLMNOPQRSTUVWXYZ[\
+]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()* +,-./0123456789:;<=>?@ABCD
+EFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopq rstuvwxyz{|}~!"#$%&'()*+,
+-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ [\]^_`abcdefghijklmnopqr
+stuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABC DEFGHIJKLMNOPQRSTUVWXYZ
+[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+, -./0123456789:;<=>?@AB
+CDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrs tuvwxyz{|}~!"#$%&'()*
++,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\ ]^_`abcdefghijklmnop
+qrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDE FGHIJKLMNOPQRSTUVWX
+YZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-. /0123456789:;<=>?@
+ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstu vwxyz{|}~!"#$%&'(
+)*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^ _`abcdefghijklmn
+opqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFG HIJKLMNOPQRSTUV
+WXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0 123456789:;<=>
+?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvw xyz{|}~!"#$%&
+'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_` abcdefghijkl
+mnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHI JKLMNOPQRST
+UVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./012 3456789:;<
+=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxy z{|}~!"#$
+%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ab cdefghij
+klmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJK LMNOPQR
+STUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./01234 56789:
+;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{ |}~!"
+#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcd efgh
+ijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLM NOP
+QRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456 78
+9:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|} ~
+!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdef 
+ ghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMN
+O PQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456
+78 9:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|
+}~! "#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcd
+efgh ijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKL
+MNOPQ RSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./01234
+56789: ;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz
+{|}~!"# $%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ab
+cdefghij klmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJ
+KLMNOPQRS TUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./012
+3456789:;< =>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwx
+yz{|}~!"#$% &'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`
+abcdefghijkl mnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGH
+IJKLMNOPQRSTU VWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0
+123456789:;<=> ?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuv
+wxyz{|}~!"#$%&' ()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^
+_`abcdefghijklmn opqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEF
+GHIJKLMNOPQRSTUVW XYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-.
+/0123456789:;<=>?@ ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrst
+uvwxyz{|}~!"#$%&'() *+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\
+]^_`abcdefghijklmnop qrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCD
+EFGHIJKLMNOPQRSTUVWXY Z[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,
+-./0123456789:;<=>?@AB CDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqr
+stuvwxyz{|}~!"#$%&'()*+ ,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ
+[\]^_`abcdefghijklmnopqr stuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@AB
+CDEFGHIJKLMNOPQRSTUVWXYZ[ \]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*
++,-./0123456789:;<=>?@ABCD EFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnop
+qrstuvwxyz{|}~!"#$%&'()*+,- ./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWX
+YZ[\]^_`abcdefghijklmnopqrst uvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@
+ABCDEFGHIJKLMNOPQRSTUVWXYZ[\] ^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'(
+)*+,-./0123456789:;<=>?@ABCDEF GHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmn
+opqrstuvwxyz{|}~!"#$%&'()*+,-./ 0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUV
+WXYZ[\]^_`abcdefghijklmnopqrstuv wxyz{|}~!"#$%&'()*+,-./0123456789:;<=>
+?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_ `abcdefghijklmnopqrstuvwxyz{|}~!"#$%&
+'()*+,-./0123456789:;<=>?@ABCDEFGH IJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijkl
+mnopqrstuvwxyz{|}~!"#$%&'()*+,-./01 23456789:;<=>?@ABCDEFGHIJKLMNOPQRST
+UVWXYZ[\]^_`abcdefghijklmnopqrstuvwx yz{|}~!"#$%&'()*+,-./0123456789:;<
+=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`a bcdefghijklmnopqrstuvwxyz{|}~!"#$
+%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJ KLMNOPQRSTUVWXYZ[\]^_`abcdefghij
+klmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123 456789:;<=>?@ABCDEFGHIJKLMNOPQR
+STUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz {|}~!"#$%&'()*+,-./0123456789:
+;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abc defghijklmnopqrstuvwxyz{|}~!"
+#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKL MNOPQRSTUVWXYZ[\]^_`abcdefgh
+ijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./012345 6789:;<=>?@ABCDEFGHIJKLMNOP
+QRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{| }~!"#$%&'()*+,-./012345678
+9:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcde fghijklmnopqrstuvwxyz{|}~
+!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMN OPQRSTUVWXYZ[\]^_`abcdef
+ghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./01234567 89:;<=>?@ABCDEFGHIJKLMN
+OPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ !"#$%&'()*+,-./0123456
+789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefg hijklmnopqrstuvwxyz{|
+}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOP QRSTUVWXYZ[\]^_`abcd
+efghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789 :;<=>?@ABCDEFGHIJKL
+MNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!" #$%&'()*+,-./01234
+56789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghi jklmnopqrstuvwxyz
+{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQR STUVWXYZ[\]^_`ab
+cdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:; <=>?@ABCDEFGHIJ
+KLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$ %&'()*+,-./012
+3456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijk lmnopqrstuvwx
+yz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRST UVWXYZ[\]^_`
+abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<= >?@ABCDEFGH
+IJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%& '()*+,-./0
+123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklm nopqrstuv
+wxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUV WXYZ[\]^
+_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>? @ABCDEF
+GHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'( )*+,-.
+/0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmno pqrst
+uvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWX YZ[\
+]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@A BCD
+EFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()* +,
+-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopq r
+stuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ 
+ [\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@AB
+C DEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*
++, -./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnop
+qrs tuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWX
+YZ[\ ]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@
+ABCDE FGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'(
+)*+,-. /0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmn
+opqrstu vwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUV
+WXYZ[\]^ _`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>
+?@ABCDEFG HIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&
+'()*+,-./0 123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijkl
+mnopqrstuvw xyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRST
+UVWXYZ[\]^_` abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<
+=>?@ABCDEFGHI JKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$
+%&'()*+,-./012 3456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghij
+klmnopqrstuvwxy z{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQR
+STUVWXYZ[\]^_`ab cdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:
+;<=>?@ABCDEFGHIJK LMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"
+#$%&'()*+,-./01234 56789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefgh
+ijklmnopqrstuvwxyz{ |}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOP
+QRSTUVWXYZ[\]^_`abcd efghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./012345678
+9:;<=>?@ABCDEFGHIJKLM NOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
+!"#$%&'()*+,-./0123456 789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdef
+ghijklmnopqrstuvwxyz{|} ~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMN
+OPQRSTUVWXYZ[\]^_`abcdef ghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456
+789:;<=>?@ABCDEFGHIJKLMNO PQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|
+}~!"#$%&'()*+,-./012345678 9:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcd
+efghijklmnopqrstuvwxyz{|}~! "#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKL
+MNOPQRSTUVWXYZ[\]^_`abcdefgh ijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./01234
+56789:;<=>?@ABCDEFGHIJKLMNOPQ RSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz
+{|}~!"#$%&'()*+,-./0123456789: ;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ab
+cdefghijklmnopqrstuvwxyz{|}~!"# $%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJ
+KLMNOPQRSTUVWXYZ[\]^_`abcdefghij klmnopqrstuvwxyz{|}~!"#$%&'()*+,-./012
+3456789:;<=>?@ABCDEFGHIJKLMNOPQRS TUVWXYZ[\]^_`abcdefghijklmnopqrstuvwx
+yz{|}~!"#$%&'()*+,-./0123456789:;< =>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`
+abcdefghijklmnopqrstuvwxyz{|}~!"#$% &'()*+,-./0123456789:;<=>?@ABCDEFGH
+IJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijkl mnopqrstuvwxyz{|}~!"#$%&'()*+,-./0
+123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTU VWXYZ[\]^_`abcdefghijklmnopqrstuv
+wxyz{|}~!"#$%&'()*+,-./0123456789:;<=> ?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^
+_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&' ()*+,-./0123456789:;<=>?@ABCDEF
+GHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmn opqrstuvwxyz{|}~!"#$%&'()*+,-.
+/0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVW XYZ[\]^_`abcdefghijklmnopqrst
+uvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ ABCDEFGHIJKLMNOPQRSTUVWXYZ[\
+]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'() *+,-./0123456789:;<=>?@ABCD
+EFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnop qrstuvwxyz{|}~!"#$%&'()*+,
+-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXY Z[\]^_`abcdefghijklmnopqr
+stuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@AB CDEFGHIJKLMNOPQRSTUVWXYZ
+[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+ ,-./0123456789:;<=>?@AB
+CDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqr stuvwxyz{|}~!"#$%&'()*
++,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[ \]^_`abcdefghijklmnop
+qrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCD EFGHIJKLMNOPQRSTUVWX
+YZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,- ./0123456789:;<=>?@
+ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrst uvwxyz{|}~!"#$%&'(
+)*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\] ^_`abcdefghijklmn
+opqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEF GHIJKLMNOPQRSTUV
+WXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./ 0123456789:;<=>
+?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuv wxyz{|}~!"#$%&
+'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_ `abcdefghijkl
+mnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGH IJKLMNOPQRST
+UVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./01 23456789:;<
+=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwx yz{|}~!"#$
+%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`a bcdefghij
+klmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJ KLMNOPQR
+STUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123 456789:
+;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz {|}~!"
+#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abc defgh
+ijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKL MNOP
+QRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./012345 678
+9:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{| }~
+!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcde f
+ghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMN 
+ OPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456
+7 89:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|
+}~ !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcd
+efg hijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKL
+MNOP QRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./01234
+56789 :;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz
+{|}~!" #$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ab
+cdefghi jklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJ
+KLMNOPQR STUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./012
+3456789:; <=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwx
+yz{|}~!"#$ %&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`
+abcdefghijk lmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGH
+IJKLMNOPQRST UVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0
+123456789:;<= >?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuv
+wxyz{|}~!"#$%& '()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^
+_`abcdefghijklm nopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEF
+GHIJKLMNOPQRSTUV WXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-.
+/0123456789:;<=>? @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrst
+uvwxyz{|}~!"#$%&'( )*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\
+]^_`abcdefghijklmno pqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCD
+EFGHIJKLMNOPQRSTUVWX YZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,
+-./0123456789:;<=>?@A BCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqr
+stuvwxyz{|}~!"#$%&'()* +,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ
+[\]^_`abcdefghijklmnopq rstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@AB
+CDEFGHIJKLMNOPQRSTUVWXYZ [\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*
++,-./0123456789:;<=>?@ABC DEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnop
+qrstuvwxyz{|}~!"#$%&'()*+, -./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWX
+YZ[\]^_`abcdefghijklmnopqrs tuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@
+ABCDEFGHIJKLMNOPQRSTUVWXYZ[\ ]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'(
+)*+,-./0123456789:;<=>?@ABCDE FGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmn
+opqrstuvwxyz{|}~!"#$%&'()*+,-. /0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUV
+WXYZ[\]^_`abcdefghijklmnopqrstu vwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>
+?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^ _`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&
+'()*+,-./0123456789:;<=>?@ABCDEFG HIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijkl
+mnopqrstuvwxyz{|}~!"#$%&'()*+,-./0 123456789:;<=>?@ABCDEFGHIJKLMNOPQRST
+UVWXYZ[\]^_`abcdefghijklmnopqrstuvw xyz{|}~!"#$%&'()*+,-./0123456789:;<
+=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_` abcdefghijklmnopqrstuvwxyz{|}~!"#$
+%&'()*+,-./0123456789:;<=>?@ABCDEFGHI JKLMNOPQRSTUVWXYZ[\]^_`abcdefghij
+klmnopqrstuvwxyz{|}~!"#$%&'()*+,-./012 3456789:;<=>?@ABCDEFGHIJKLMNOPQR
+STUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxy z{|}~!"#$%&'()*+,-./0123456789:
+;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ab cdefghijklmnopqrstuvwxyz{|}~!"
+#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJK LMNOPQRSTUVWXYZ[\]^_`abcdefgh
+ijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./01234 56789:;<=>?@ABCDEFGHIJKLMNOP
+QRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{ |}~!"#$%&'()*+,-./012345678
+9:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcd efghijklmnopqrstuvwxyz{|}~
+!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLM NOPQRSTUVWXYZ[\]^_`abcdef
+ghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456 789:;<=>?@ABCDEFGHIJKLMN
+OPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|} ~!"#$%&'()*+,-./0123456
+789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdef ghijklmnopqrstuvwxyz{|
+}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNO PQRSTUVWXYZ[\]^_`abcd
+efghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./012345678 9:;<=>?@ABCDEFGHIJKL
+MNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~! "#$%&'()*+,-./01234
+56789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefgh ijklmnopqrstuvwxyz
+{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQ RSTUVWXYZ[\]^_`ab
+cdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789: ;<=>?@ABCDEFGHIJ
+KLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"# $%&'()*+,-./012
+3456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghij klmnopqrstuvwx
+yz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRS TUVWXYZ[\]^_`
+abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;< =>?@ABCDEFGH
+IJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$% &'()*+,-./0
+123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijkl mnopqrstuv
+wxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTU VWXYZ[\]^
+_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=> ?@ABCDEF
+GHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&' ()*+,-.
+/0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmn opqrst
+uvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVW XYZ[\
+]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ ABCD
+EFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'() *+,
+-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnop qr
+stuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXY Z
+[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@AB 
+ CDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*
++ ,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnop
+qr stuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWX
+YZ[ \]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@
+ABCD EFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'(
+)*+,- ./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmn
+opqrst uvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUV
+WXYZ[\] ^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>
+?@ABCDEF GHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&
+'()*+,-./ 0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijkl
+mnopqrstuv wxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRST
+UVWXYZ[\]^_ `abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<
+=>?@ABCDEFGH IJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$
+%&'()*+,-./01 23456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghij
+klmnopqrstuvwx yz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQR
+STUVWXYZ[\]^_`a bcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:
+;<=>?@ABCDEFGHIJ KLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"
+#$%&'()*+,-./0123 456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefgh
+ijklmnopqrstuvwxyz {|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOP
+QRSTUVWXYZ[\]^_`abc defghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./012345678
+9:;<=>?@ABCDEFGHIJKL MNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
+!"#$%&'()*+,-./012345 6789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdef
+ghijklmnopqrstuvwxyz{| }~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMN
+OPQRSTUVWXYZ[\]^_`abcde fghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456
+789:;<=>?@ABCDEFGHIJKLMN OPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|
+}~!"#$%&'()*+,-./01234567 89:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcd
+efghijklmnopqrstuvwxyz{|}~ !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKL
+MNOPQRSTUVWXYZ[\]^_`abcdefg hijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./01234
+56789:;<=>?@ABCDEFGHIJKLMNOP QRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz
+{|}~!"#$%&'()*+,-./0123456789 :;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ab
+cdefghijklmnopqrstuvwxyz{|}~!" #$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJ
+KLMNOPQRSTUVWXYZ[\]^_`abcdefghi jklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./012
+3456789:;<=>?@ABCDEFGHIJKLMNOPQR STUVWXYZ[\]^_`abcdefghijklmnopqrstuvwx
+yz{|}~!"#$%&'()*+,-./0123456789:; <=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`
+abcdefghijklmnopqrstuvwxyz{|}~!"#$ %&'()*+,-./0123456789:;<=>?@ABCDEFGH
+IJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijk lmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0
+123456789:;<=>?@ABCDEFGHIJKLMNOPQRST UVWXYZ[\]^_`abcdefghijklmnopqrstuv
+wxyz{|}~!"#$%&'()*+,-./0123456789:;<= >?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^
+_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%& '()*+,-./0123456789:;<=>?@ABCDEF
+GHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklm nopqrstuvwxyz{|}~!"#$%&'()*+,-.
+/0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUV WXYZ[\]^_`abcdefghijklmnopqrst
+uvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>? @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\
+]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'( )*+,-./0123456789:;<=>?@ABCD
+EFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmno pqrstuvwxyz{|}~!"#$%&'()*+,
+-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWX YZ[\]^_`abcdefghijklmnopqr
+stuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@A BCDEFGHIJKLMNOPQRSTUVWXYZ
+[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()* +,-./0123456789:;<=>?@AB
+CDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopq rstuvwxyz{|}~!"#$%&'()*
++,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ [\]^_`abcdefghijklmnop
+qrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABC DEFGHIJKLMNOPQRSTUVWX
+YZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+, -./0123456789:;<=>?@
+ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrs tuvwxyz{|}~!"#$%&'(
+)*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\ ]^_`abcdefghijklmn
+opqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDE FGHIJKLMNOPQRSTUV
+WXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-. /0123456789:;<=>
+?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstu vwxyz{|}~!"#$%&
+'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^ _`abcdefghijkl
+mnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFG HIJKLMNOPQRST
+UVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0 123456789:;<
+=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvw xyz{|}~!"#$
+%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_` abcdefghij
+klmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHI JKLMNOPQR
+STUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./012 3456789:
+;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxy z{|}~!"
+#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ab cdefgh
+ijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJK LMNOP
+QRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./01234 5678
+9:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{ |}~
diff --git a/tests/pull-api.c b/tests/pull-api.c
new file mode 100644 (file)
index 0000000..a20fcd0
--- /dev/null
@@ -0,0 +1,579 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "libsoup/soup.h"
+#include "libsoup/soup-session.h"
+
+#include "apache-wrapper.h"
+
+int errors = 0;
+int debug = 0;
+char *correct_response;
+guint correct_response_len;
+
+static void
+dprintf (int level, const char *format, ...)
+{
+       va_list args;
+
+       if (debug < level)
+               return;
+
+       va_start (args, format);
+       vprintf (format, args);
+       va_end (args);
+}
+
+static void
+authenticate (SoupSession *session, SoupMessage *msg,
+             const char *auth_type, const char *auth_realm,
+             char **username, char **password, gpointer data)
+{
+       *username = g_strdup ("user2");
+       *password = g_strdup ("realm2");
+}
+
+static void
+get_correct_response (const char *uri)
+{
+       SoupSession *session;
+       SoupMessage *msg;
+
+       session = soup_session_async_new ();
+       msg = soup_message_new (SOUP_METHOD_GET, uri);
+       soup_session_send_message (session, msg);
+       if (msg->status_code != SOUP_STATUS_OK) {
+               fprintf (stderr, "Could not fetch %s: %d %s\n", uri,
+                        msg->status_code, msg->reason_phrase);
+               exit (1);
+       }
+
+       correct_response_len = msg->response.length;
+       correct_response = g_strndup (msg->response.body, correct_response_len);
+
+       soup_session_abort (session);
+       g_object_unref (session);
+}
+
+/* Pull API version 1: fully-async. More like a "poke" API. Rather
+ * than having SoupMessage emit "got_chunk" signals whenever it wants,
+ * we stop it after it finishes reading the message headers, and then
+ * tell it when we want to hear about new chunks.
+ */
+
+typedef struct {
+       GMainLoop *loop;
+       SoupMessage *msg;
+       guint timeout;
+       gboolean chunks_ready;
+       gboolean chunk_wanted;
+       gboolean did_first_timeout;
+       gsize read_so_far;
+       guint expected_status;
+} FullyAsyncData;
+
+static void fully_async_got_headers (SoupMessage *msg, gpointer user_data);
+static void fully_async_got_chunk   (SoupMessage *msg, gpointer user_data);
+static void fully_async_finished    (SoupMessage *msg, gpointer user_data);
+static gboolean fully_async_request_chunk (gpointer user_data);
+
+static void
+do_fully_async_test (SoupSession *session,
+                    const char *base_uri, const char *sub_uri,
+                    gboolean fast_request, guint expected_status)
+{
+       GMainLoop *loop;
+       FullyAsyncData ad;
+       SoupMessage *msg;
+       char *uri;
+
+       loop = g_main_loop_new (NULL, FALSE);
+
+       uri = g_build_filename (base_uri, sub_uri, NULL);
+       dprintf (1, "GET %s\n", uri);
+
+       msg = soup_message_new (SOUP_METHOD_GET, uri);
+       g_free (uri);
+
+       ad.loop = loop;
+       ad.msg = msg;
+       ad.chunks_ready = FALSE;
+       ad.chunk_wanted = FALSE;
+       ad.did_first_timeout = FALSE;
+       ad.read_so_far = 0;
+       ad.expected_status = expected_status;
+
+       /* Since we aren't going to look at the final value of
+        * msg->response.body, we set OVERWRITE_CHUNKS, to tell
+        * libsoup to not even bother generating it.
+        */
+       soup_message_set_flags (msg, SOUP_MESSAGE_OVERWRITE_CHUNKS);
+
+       /* Connect to "got_headers", from which we'll decide where to
+        * go next.
+        */
+       g_signal_connect (msg, "got_headers",
+                         G_CALLBACK (fully_async_got_headers), &ad);
+
+       /* Queue the request */
+       soup_session_queue_message (session, msg, fully_async_finished, &ad);
+
+       /* In a real program, we'd probably just return at this point.
+        * Eventually the caller would return all the way to the main
+        * loop, and then eventually, some event would cause the
+        * application to request a chunk of data from the message
+        * response.
+        *
+        * In our test program, there is no "real" main loop, so we
+        * had to create our own. We use a timeout to represent the
+        * event that causes the app to decide to request another body
+        * chunk. We use short timeouts in one set of tests, and long
+        * ones in another, to test both the
+        * chunk-requested-before-its-been-read and
+        * chunk-read-before-its-been-requested cases.
+        */
+       ad.timeout = g_timeout_add (fast_request ? 0 : 100,
+                                   fully_async_request_chunk, &ad);
+       g_main_loop_run (ad.loop);
+       g_main_loop_unref (ad.loop);
+}
+
+static gboolean
+fully_async_request_chunk (gpointer user_data)
+{
+       FullyAsyncData *ad = user_data;
+
+       if (!ad->did_first_timeout) {
+               dprintf (1, "  first timeout\n");
+               ad->did_first_timeout = TRUE;
+       } else
+               dprintf (2, "  timeout\n");
+       ad->timeout = 0;
+
+       /* ad->chunks_ready and ad->chunk_wanted are used because
+        * there's a race condition between the application requesting
+        * the first chunk, and the message reaching a point where
+        * it's actually ready to read chunks. If chunks_ready has
+        * been set, we can just call soup_message_io_unpause() to
+        * cause the first chunk to be read. But if it's not, we just
+        * set chunk_wanted, to let the got_headers handler below know
+        * that a chunk has already been requested.
+        */
+       if (ad->chunks_ready)
+               soup_message_io_unpause (ad->msg);
+       else
+               ad->chunk_wanted = TRUE;
+
+       return FALSE;
+}
+
+static void
+fully_async_got_headers (SoupMessage *msg, gpointer user_data)
+{
+       FullyAsyncData *ad = user_data;
+
+       dprintf (1, "  %d %s\n", msg->status_code, msg->reason_phrase);
+       if (msg->status_code == SOUP_STATUS_UNAUTHORIZED) {
+               /* Let soup handle this one; this got_headers handler
+                * will get called again next time around.
+                */
+               return;
+       } else if (msg->status_code != SOUP_STATUS_OK) {
+               dprintf (1, "  unexpected status: %d %s\n",
+                        msg->status_code, msg->reason_phrase);
+               errors++;
+               return;
+       }
+
+       /* OK, we're happy with the response. So, we connect to
+        * "got_chunk". If there has already been a chunk requested,
+        * we let I/O continue; but if there hasn't, we pause now
+        * until one is requested.
+        */
+       ad->chunks_ready = TRUE;
+       g_signal_connect (msg, "got_chunk",
+                         G_CALLBACK (fully_async_got_chunk), ad);
+       if (!ad->chunk_wanted)
+               soup_message_io_pause (msg);
+}
+
+static void
+fully_async_got_chunk (SoupMessage *msg, gpointer user_data)
+{
+       FullyAsyncData *ad = user_data;
+
+       dprintf (2, "  got chunk from %lu - %lu\n",
+                (unsigned long) ad->read_so_far,
+                (unsigned long) ad->read_so_far + msg->response.length);
+
+       /* We've got a chunk, let's process it. In the case of the
+        * test program, that means comparing it against
+        * correct_response to make sure that we got the right data.
+        * We're using SOUP_MESSAGE_OVERWRITE_CHUNKS, so msg->response
+        * contains just the latest chunk. ad->read_so_far tells us
+        * how far we've read so far.
+        *
+        * Note that since we're using OVERWRITE_CHUNKS, msg->response
+        * is only good until we return from this signal handler; if
+        * you wanted to process it later, you'd need to copy it
+        * somewhere.
+        */
+       if (ad->read_so_far + msg->response.length > correct_response_len) {
+               dprintf (1, "  read too far! (%lu > %lu)\n",
+                        (unsigned long) (ad->read_so_far + msg->response.length),
+                        (unsigned long) correct_response_len);
+               errors++;
+       } else if (memcmp (msg->response.body, correct_response + ad->read_so_far,
+                          msg->response.length) != 0) {
+               dprintf (1, "  data mismatch in block starting at %lu\n",
+                        (unsigned long) ad->read_so_far);
+               errors++;
+       }
+       ad->read_so_far += msg->response.length;
+
+       /* Now pause I/O, and prepare to read another chunk later.
+        * (Again, the timeout just abstractly represents the idea of
+        * the application requesting another chunk at some random
+        * point in the future. You wouldn't be using a timeout in a
+        * real program.)
+        */
+       soup_message_io_pause (msg);
+       ad->chunk_wanted = FALSE;
+
+       ad->timeout = g_timeout_add (10, fully_async_request_chunk, ad);
+}
+
+static void
+fully_async_finished (SoupMessage *msg, gpointer user_data)
+{
+       FullyAsyncData *ad = user_data;
+
+       if (msg->status_code != ad->expected_status) {
+               dprintf (1, "  unexpected final status: %d %s !\n",
+                        msg->status_code, msg->reason_phrase);
+               errors++;
+       }
+
+       if (ad->timeout != 0)
+               g_source_remove (ad->timeout);
+
+       /* Since our test program is only running the loop for the
+        * purpose of this one test, we quit the loop once the
+        * test is done.
+        */
+       g_main_loop_quit (ad->loop);
+}
+
+
+/* Pull API version 2: synchronous pull API via async I/O. */
+
+typedef struct {
+       GMainLoop *loop;
+       GByteArray *chunk;
+} SyncAsyncData;
+
+static void        sync_async_send       (SoupSession *session,
+                                         SoupMessage *msg);
+static GByteArray *sync_async_read_chunk (SoupMessage *msg);
+static void        sync_async_cleanup    (SoupMessage *msg);
+
+static void sync_async_got_headers (SoupMessage *msg, gpointer user_data);
+static void sync_async_copy_chunk  (SoupMessage *msg, gpointer user_data);
+static void sync_async_finished    (SoupMessage *msg, gpointer user_data);
+
+static void
+do_synchronously_async_test (SoupSession *session,
+                            const char *base_uri, const char *sub_uri,
+                            guint expected_status)
+{
+       SoupMessage *msg;
+       char *uri;
+       gsize read_so_far;
+       GByteArray *chunk;
+
+       uri = g_build_filename (base_uri, sub_uri, NULL);
+       dprintf (1, "GET %s\n", uri);
+
+       msg = soup_message_new (SOUP_METHOD_GET, uri);
+       g_free (uri);
+
+       /* As in the fully-async case, we set OVERWRITE_CHUNKS as an
+        * optimization.
+        */
+       soup_message_set_flags (msg, SOUP_MESSAGE_OVERWRITE_CHUNKS);
+
+       /* Send the message, get back headers */
+       sync_async_send (session, msg);
+       if (msg->status == SOUP_MESSAGE_STATUS_FINISHED &&
+           expected_status == SOUP_STATUS_OK) {
+               dprintf (1, "  finished without reading response!\n");
+               errors++;
+       } else if (msg->status != SOUP_MESSAGE_STATUS_FINISHED &&
+                  expected_status != SOUP_STATUS_OK) {
+               dprintf (1, "  request failed to fail!\n");
+               errors++;
+       }
+
+       /* Now we're ready to read the response body (though we could
+        * put that off until later if we really wanted).
+        */
+       read_so_far = 0;
+       while ((chunk = sync_async_read_chunk (msg))) {
+               dprintf (2, "  read chunk from %lu - %lu\n",
+                        (unsigned long) read_so_far,
+                        (unsigned long) read_so_far + chunk->len);
+
+               if (read_so_far + chunk->len > correct_response_len) {
+                       dprintf (1, "  read too far! (%lu > %lu)\n",
+                                (unsigned long) read_so_far + chunk->len,
+                                (unsigned long) correct_response_len);
+                       errors++;
+               } else if (memcmp (chunk->data,
+                                  correct_response + read_so_far,
+                                  chunk->len) != 0) {
+                       dprintf (1, "  data mismatch in block starting at %lu\n",
+                                (unsigned long) read_so_far);
+                       errors++;
+               }
+               read_so_far += chunk->len;
+               g_byte_array_free (chunk, TRUE);
+       }
+
+       if (msg->status != SOUP_MESSAGE_STATUS_FINISHED ||
+           (msg->status_code == SOUP_STATUS_OK &&
+            read_so_far != correct_response_len)) {
+               dprintf (1, "  loop ended before message was fully read!\n");
+               errors++;
+       } else if (msg->status_code != expected_status) {
+               dprintf (1, "  unexpected final status: %d %s !\n",
+                        msg->status_code, msg->reason_phrase);
+               errors++;
+       }
+
+       sync_async_cleanup (msg);
+       g_object_unref (msg);
+}
+
+/* Sends @msg on async session @session and returns after the headers
+ * of a successful response (or the complete body of a failed
+ * response) have been read.
+ */
+static void
+sync_async_send (SoupSession *session, SoupMessage *msg)
+{
+       SyncAsyncData *ad;
+
+       ad = g_new0 (SyncAsyncData, 1);
+       g_object_set_data (G_OBJECT (msg), "SyncAsyncData", ad);
+
+       /* In this case, unlike the fully-async case, the loop
+        * actually belongs to us, not the application; it will only
+        * be run when we're waiting for chunks, not at other times.
+        *
+        * If session has an async_context associated with it, we'd
+        * want to pass that, rather than NULL, here.
+        */
+       ad->loop = g_main_loop_new (NULL, FALSE);
+
+       g_signal_connect (msg, "got_headers",
+                         G_CALLBACK (sync_async_got_headers), ad);
+
+       /* Start the request by queuing it and then running our main
+        * loop. Note: we have to use soup_session_queue_message()
+        * here; soup_session_send_message() won't work, for several
+        * reasons. Also, since soup_session_queue_message() steals a
+        * ref to the message and then unrefs it after invoking the
+        * callback, we have to add an extra ref before calling it.
+        */
+       g_object_ref (msg);
+       soup_session_queue_message (session, msg, sync_async_finished, ad);
+       g_main_loop_run (ad->loop);
+
+       /* At this point, one of two things has happened; either the
+        * got_headers handler got headers it liked, and so stopped
+        * the loop, or else the message was fully processed without
+        * the got_headers handler interrupting it, and so the final
+        * callback (sync_async_finished) was invoked, and stopped the
+        * loop.
+        *
+        * Either way, we're done, so we return to the caller.
+        */
+}
+
+static void
+sync_async_got_headers (SoupMessage *msg, gpointer user_data)
+{
+       SyncAsyncData *ad = user_data;
+
+       dprintf (1, "  %d %s\n", msg->status_code, msg->reason_phrase);
+       if (msg->status_code == SOUP_STATUS_UNAUTHORIZED) {
+               /* Let soup handle this one; this got_headers handler
+                * will get called again next time around.
+                */
+               return;
+       } else if (msg->status_code != SOUP_STATUS_OK) {
+               dprintf (1, "  unexpected status: %d %s\n",
+                        msg->status_code, msg->reason_phrase);
+               errors++;
+               return;
+       }
+
+       /* Stop I/O and return to the caller */
+       soup_message_io_pause (msg);
+       g_main_loop_quit (ad->loop);
+}
+
+/* Tries to read a chunk. Returns %NULL on error/end-of-response. (The
+ * cases can be distinguished by looking at msg->status and
+ * msg->status_code.)
+ */
+static GByteArray *
+sync_async_read_chunk (SoupMessage *msg)
+{
+       SyncAsyncData *ad = g_object_get_data (G_OBJECT (msg), "SyncAsyncData");
+       guint handler;
+
+       if (msg->status == SOUP_MESSAGE_STATUS_FINISHED)
+               return NULL;
+
+       ad->chunk = NULL;
+       handler = g_signal_connect (msg, "got_chunk",
+                                   G_CALLBACK (sync_async_copy_chunk),
+                                   ad);
+       soup_message_io_unpause (msg);
+       g_main_loop_run (ad->loop);
+       g_signal_handler_disconnect (msg, handler);
+
+       return ad->chunk;
+}
+
+static void
+sync_async_copy_chunk (SoupMessage *msg, gpointer user_data)
+{
+       SyncAsyncData *ad = user_data;
+
+       /* It's unfortunate that we have to do an extra copy here,
+        * but the data in msg->response.body won't last beyond
+        * the invocation of this handler.
+        */
+       ad->chunk = g_byte_array_new ();
+       g_byte_array_append (ad->chunk, (gpointer)msg->response.body,
+                            msg->response.length);
+
+       /* Now pause and return from the g_main_loop_run() call in
+        * sync_async_read_chunk().
+        */
+       soup_message_io_pause (msg);
+       g_main_loop_quit (ad->loop);
+}
+
+static void
+sync_async_finished (SoupMessage *msg, gpointer user_data)
+{
+       SyncAsyncData *ad = user_data;
+
+       /* Unlike in the fully_async_case, we don't need to do much
+        * here, because control will return to
+        * do_synchronously_async_test() when we're done, and we do
+        * the final tests there.
+        */
+       g_main_loop_quit (ad->loop);
+}
+
+static void
+sync_async_cleanup (SoupMessage *msg)
+{
+       SyncAsyncData *ad = g_object_get_data (G_OBJECT (msg), "SyncAsyncData");
+
+       g_main_loop_unref (ad->loop);
+       g_free (ad);
+}
+
+
+int
+main (int argc, char **argv)
+{
+       SoupSession *session;
+       char *base_uri;
+       int opt;
+
+       g_type_init ();
+       g_thread_init (NULL);
+
+       while ((opt = getopt (argc, argv, "d")) != -1) {
+               switch (opt) {
+               case 'd':
+                       debug++;
+                       break;
+               default:
+                       fprintf (stderr, "Usage: %s [-d [-d]]\n", argv[0]);
+                       return 1;
+               }
+       }
+
+       if (!apache_init ()) {
+               fprintf (stderr, "Could not start apache\n");
+               return 1;
+       }
+       base_uri = "http://localhost:47524/";
+       get_correct_response (base_uri);
+
+       dprintf (1, "\nFully async, fast requests\n");
+       session = soup_session_async_new ();
+       g_signal_connect (session, "authenticate",
+                         G_CALLBACK (authenticate), NULL);
+       do_fully_async_test (session, base_uri, "/",
+                            TRUE, SOUP_STATUS_OK);
+       do_fully_async_test (session, base_uri, "/Basic/realm1/",
+                            TRUE, SOUP_STATUS_UNAUTHORIZED);
+       do_fully_async_test (session, base_uri, "/Basic/realm2/",
+                            TRUE, SOUP_STATUS_OK);
+       soup_session_abort (session);
+       g_object_unref (session);
+
+       dprintf (1, "\nFully async, slow requests\n");
+       session = soup_session_async_new ();
+       g_signal_connect (session, "authenticate",
+                         G_CALLBACK (authenticate), NULL);
+       do_fully_async_test (session, base_uri, "/",
+                            FALSE, SOUP_STATUS_OK);
+       do_fully_async_test (session, base_uri, "/Basic/realm1/",
+                            FALSE, SOUP_STATUS_UNAUTHORIZED);
+       do_fully_async_test (session, base_uri, "/Basic/realm2/",
+                            FALSE, SOUP_STATUS_OK);
+       soup_session_abort (session);
+       g_object_unref (session);
+
+       dprintf (1, "\nSynchronously async\n");
+       session = soup_session_async_new ();
+       g_signal_connect (session, "authenticate",
+                         G_CALLBACK (authenticate), NULL);
+       do_synchronously_async_test (session, base_uri, "/",
+                                    SOUP_STATUS_OK);
+       do_synchronously_async_test (session, base_uri, "/Basic/realm1/",
+                                    SOUP_STATUS_UNAUTHORIZED);
+       do_synchronously_async_test (session, base_uri, "/Basic/realm2/",
+                                    SOUP_STATUS_OK);
+
+       soup_session_abort (session);
+       g_object_unref (session);
+
+       g_free (correct_response);
+
+       apache_cleanup ();
+
+       dprintf (1, "\n");
+       if (errors) {
+               printf ("pull-api: %d error(s). Run with '-d' for details\n",
+                       errors);
+       } else
+               printf ("pull-api: OK\n");
+       return errors;
+}