quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

lib2700.c (6377B)


      1 /***************************************************************************
      2  *                                  _   _ ____  _
      3  *  Project                     ___| | | |  _ \| |
      4  *                             / __| | | | |_) | |
      5  *                            | (__| |_| |  _ <| |___
      6  *                             \___|\___/|_| \_\_____|
      7  *
      8  * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
      9  *
     10  * This software is licensed as described in the file COPYING, which
     11  * you should have received as part of this distribution. The terms
     12  * are also available at https://curl.se/docs/copyright.html.
     13  *
     14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
     15  * copies of the Software, and permit persons to whom the Software is
     16  * furnished to do so, under the terms of the COPYING file.
     17  *
     18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
     19  * KIND, either express or implied.
     20  *
     21  * SPDX-License-Identifier: curl
     22  *
     23  ***************************************************************************/
     24 #include "first.h"
     25 
     26 #include "testtrace.h"
     27 #include "memdebug.h"
     28 
     29 #ifndef CURL_DISABLE_WEBSOCKETS
     30 
     31 static const char *descr_flags(int flags)
     32 {
     33   if(flags & CURLWS_TEXT)
     34     return flags & CURLWS_CONT ? "txt ---" : "txt fin";
     35   if(flags & CURLWS_BINARY)
     36     return flags & CURLWS_CONT ? "bin ---" : "bin fin";
     37   if(flags & CURLWS_PING)
     38     return "ping";
     39   if(flags & CURLWS_PONG)
     40     return "pong";
     41   if(flags & CURLWS_CLOSE)
     42     return "close";
     43   assert(false);
     44   return "";
     45 }
     46 
     47 static CURLcode send_header(CURL *curl, int flags, size_t size)
     48 {
     49   CURLcode res = CURLE_OK;
     50   size_t nsent;
     51 
     52 retry:
     53   res = curl_ws_send(curl, NULL, 0, &nsent, (curl_off_t)size,
     54                      flags | CURLWS_OFFSET);
     55   if(res == CURLE_AGAIN) {
     56     assert(nsent == 0);
     57     goto retry;
     58   }
     59   if(res) {
     60     curl_mfprintf(stderr, "%s:%d curl_ws_send() failed with code %d (%s)\n",
     61                   __FILE__, __LINE__, res, curl_easy_strerror(res));
     62     assert(nsent == 0);
     63     return res;
     64   }
     65 
     66   assert(nsent == 0);
     67 
     68   return CURLE_OK;
     69 }
     70 
     71 static CURLcode recv_header(CURL *curl, int *flags, curl_off_t *offset,
     72                             curl_off_t *bytesleft)
     73 {
     74   CURLcode res = CURLE_OK;
     75   size_t nread;
     76   const struct curl_ws_frame *meta;
     77 
     78   *flags = 0;
     79   *offset = 0;
     80   *bytesleft = 0;
     81 
     82 retry:
     83   res = curl_ws_recv(curl, NULL, 0, &nread, &meta);
     84   if(res == CURLE_AGAIN) {
     85     assert(nread == 0);
     86     goto retry;
     87   }
     88   if(res) {
     89     curl_mfprintf(stderr, "%s:%d curl_ws_recv() failed with code %d (%s)\n",
     90                   __FILE__, __LINE__, res, curl_easy_strerror(res));
     91     assert(nread == 0);
     92     return res;
     93   }
     94 
     95   assert(nread == 0);
     96   assert(meta != NULL);
     97   assert(meta->flags);
     98   assert(meta->offset == 0);
     99 
    100   *flags = meta->flags;
    101   *offset = meta->offset;
    102   *bytesleft = meta->bytesleft;
    103 
    104   curl_mfprintf(stdout, "%s [%" FMT_OFF_T "]", descr_flags(meta->flags),
    105                 meta->bytesleft);
    106 
    107   if(meta->bytesleft > 0)
    108     curl_mfprintf(stdout, " ");
    109 
    110   res = send_header(curl, meta->flags, (size_t)meta->bytesleft);
    111   if(res)
    112     return res;
    113 
    114   return CURLE_OK;
    115 }
    116 
    117 static CURLcode send_chunk(CURL *curl, int flags, const char *buffer,
    118                            size_t size, size_t *offset)
    119 {
    120   CURLcode res = CURLE_OK;
    121   size_t nsent;
    122 
    123 retry:
    124     res = curl_ws_send(curl, buffer + *offset, size - *offset, &nsent, 0,
    125                        flags);
    126   if(res == CURLE_AGAIN) {
    127     assert(nsent == 0);
    128     goto retry;
    129   }
    130   if(res) {
    131     curl_mfprintf(stderr, "%s:%d curl_ws_send() failed with code %d (%s)\n",
    132                   __FILE__, __LINE__, res, curl_easy_strerror(res));
    133     assert(nsent == 0);
    134     return res;
    135   }
    136 
    137   assert(nsent <= size - *offset);
    138 
    139   *offset += nsent;
    140 
    141   return CURLE_OK;
    142 }
    143 
    144 static CURLcode recv_chunk(CURL *curl, int flags, curl_off_t *offset,
    145                            curl_off_t *bytesleft)
    146 {
    147   CURLcode res = CURLE_OK;
    148   char buffer[256];
    149   size_t nread;
    150   const struct curl_ws_frame *meta;
    151   size_t sendoffset = 0;
    152 
    153 retry:
    154   res = curl_ws_recv(curl, buffer, sizeof(buffer), &nread, &meta);
    155   if(res == CURLE_AGAIN) {
    156     assert(nread == 0);
    157     goto retry;
    158   }
    159   if(res) {
    160     curl_mfprintf(stderr, "%s:%d curl_ws_recv() failed with code %d (%s)\n",
    161                   __FILE__, __LINE__, res, curl_easy_strerror(res));
    162     assert(nread == 0);
    163     return res;
    164   }
    165 
    166   assert(nread <= sizeof(buffer));
    167   assert(meta != NULL);
    168   assert(meta->flags == flags);
    169   assert(meta->offset == *offset);
    170   assert(meta->bytesleft == (*bytesleft - (curl_off_t)nread));
    171 
    172   *offset += nread;
    173   *bytesleft -= nread;
    174 
    175   fwrite(buffer, 1, nread, stdout);
    176 
    177   while(sendoffset < nread) {
    178     res = send_chunk(curl, flags, buffer, nread, &sendoffset);
    179     if(res)
    180       return res;
    181   }
    182 
    183   return CURLE_OK;
    184 }
    185 
    186 static CURLcode recv_frame(CURL *curl, bool *stop)
    187 {
    188   CURLcode res = CURLE_OK;
    189   int flags = 0;
    190   curl_off_t offset = 0;
    191   curl_off_t bytesleft = 0;
    192 
    193   res = recv_header(curl, &flags, &offset, &bytesleft);
    194   if(res)
    195     return res;
    196 
    197   while(bytesleft > 0) {
    198     res = recv_chunk(curl, flags, &offset, &bytesleft);
    199     if(res)
    200       return res;
    201   }
    202 
    203   if(flags & CURLWS_CLOSE)
    204     *stop = true;
    205 
    206   curl_mfprintf(stdout, "\n");
    207 
    208   return res;
    209 }
    210 #endif
    211 
    212 static CURLcode test_lib2700(char *URL)
    213 {
    214 #ifndef CURL_DISABLE_WEBSOCKETS
    215   CURLcode res = CURLE_OK;
    216   bool stop = false;
    217   CURL *curl;
    218 
    219   global_init(CURL_GLOBAL_ALL);
    220   curl_global_trace("ws");
    221   easy_init(curl);
    222 
    223   easy_setopt(curl, CURLOPT_URL, URL);
    224   easy_setopt(curl, CURLOPT_USERAGENT, "client/test2700");
    225   libtest_debug_config.nohex = 1;
    226   libtest_debug_config.tracetime = 1;
    227   easy_setopt(curl, CURLOPT_DEBUGDATA, &libtest_debug_config);
    228   easy_setopt(curl, CURLOPT_DEBUGFUNCTION, libtest_debug_cb);
    229   easy_setopt(curl, CURLOPT_VERBOSE, 1L);
    230   easy_setopt(curl, CURLOPT_CONNECT_ONLY, 2L);
    231   if(!getenv("LIB2700_AUTO_PONG"))
    232     easy_setopt(curl, CURLOPT_WS_OPTIONS, (long)CURLWS_NOAUTOPONG);
    233 
    234   res = curl_easy_perform(curl);
    235   if(res) {
    236     curl_mfprintf(stderr,
    237                   "%s:%d curl_easy_perform() failed with code %d (%s)\n",
    238                   __FILE__, __LINE__, res, curl_easy_strerror(res));
    239     goto test_cleanup;
    240   }
    241 
    242   while(!stop) {
    243     res = recv_frame(curl, &stop);
    244     if(res)
    245       goto test_cleanup;
    246   }
    247 
    248 test_cleanup:
    249   curl_easy_cleanup(curl);
    250   curl_global_cleanup();
    251   return res;
    252 #else
    253   NO_SUPPORT_BUILT_IN
    254 #endif
    255 }