static gpg_error_t part_data (void *cookie, const void *data, size_t datalen) { receive_ctx_t ctx = cookie; if (data) { if (opt.debug) log_debug ("part_data: '%.*s'\n", (int)datalen, (const char*)data); if (ctx->collect_key_data) { if (es_write (ctx->key_data, data, datalen, NULL) || es_fputs ("\n", ctx->key_data)) return gpg_error_from_syserror (); } if (ctx->collect_wkd_data) { if (es_write (ctx->wkd_data, data, datalen, NULL) || es_fputs ("\n", ctx->wkd_data)) return gpg_error_from_syserror (); } } else { if (opt.debug) log_debug ("part_data: finished\n"); ctx->collect_key_data = 0; ctx->collect_wkd_data = 0; } return 0; }
/* Copy all data from IN to OUT. */ static gpg_error_t copy_stream (estream_t in, estream_t out) { char buffer[512]; size_t nread; while (!es_read (in, buffer, sizeof buffer, &nread)) { if (!nread) return 0; /* EOF */ if (es_write (out, buffer, nread, NULL)) break; } return gpg_error_from_syserror (); }
/* The thread started by start_reader. */ static void * reader_thread_main (void *arg) { gpg_error_t err = 0; struct reader_thread_parms *parm = arg; char buffer[4096]; int nread; while ( (nread = npth_read (parm->fd, buffer, sizeof buffer)) ) { if (nread < 0) { if (errno == EINTR) continue; err = my_error_from_syserror (); break; /* Read error. */ } if (parm->stream) { const char *p = buffer; size_t nwritten; while (nread) { err = es_write (parm->stream, p, nread, &nwritten); if (err) { log_error ("writing stream failed: %s\n", gpg_strerror (err)); goto leave; } nread -= nwritten; p += nwritten; } } else put_membuf (parm->mb, buffer, nread); } leave: *parm->err_addr = err; if (close (parm->fd)) log_error ("closing reader fd %d failed: %s\n", parm->fd, strerror (errno)); xfree (parm); return NULL; }
/* Data callback for the WKD_GET command. */ static gpg_error_t wkd_get_data_cb (void *opaque, const void *data, size_t datalen) { struct wkd_get_parm_s *parm = opaque; gpg_error_t err = 0; size_t nwritten; if (!data) return 0; /* Ignore END commands. */ if (!parm->memfp) return 0; /* Data is not required. */ if (es_write (parm->memfp, data, datalen, &nwritten)) err = gpg_error_from_syserror (); return err; }
/* Helper for ks_hkp_put. */ static gpg_error_t put_post_cb (void *opaque, http_t http) { struct put_post_parm_s *parm = opaque; gpg_error_t err = 0; estream_t fp; size_t len; fp = http_get_write_ptr (http); len = strlen (parm->datastring); es_fprintf (fp, "Content-Type: application/x-www-form-urlencoded\r\n" "Content-Length: %zu\r\n", len+8 /* 8 is for "keytext" */); http_start_data (http); if (es_fputs ("keytext=", fp) || es_write (fp, parm->datastring, len, NULL)) err = gpg_error_from_syserror (); return err; }
/* The thread started by start_feede3. */ static void * feeder_thread (void *arg) { struct feeder_thread_parms *parm = arg; char buffer[4096]; int rc; if (parm->direction) { size_t nread = 0; DWORD nwritten; log_debug ("feeder_thread estream->pipe: stream=%p pipe=%p\n", parm->stream, parm->hd); while (parm->stream_valid && !es_read (parm->stream, buffer, sizeof buffer, &nread)) { do { pth_enter (); rc = WriteFile (parm->hd, buffer, nread, &nwritten, NULL); pth_leave (); if (!rc) { log_debug ("feeder(%p): WriteFile error: rc=%d\n", parm->hd, (int)GetLastError ()); goto leave; } nread -= nwritten; } while (nread); } if (!parm->stream_valid) log_debug ("feeder(%p): closed by other thread\n", parm->hd); else if (nread) log_debug ("feeder(%p): es_read error: %s\n", parm->hd, strerror (errno)); } else { DWORD nread = 0; size_t nwritten; log_debug ("feeder_thread pipe->estream: stream=%p pipe=%p\n", parm->stream, parm->hd); while ( (pth_enter (), (rc = ReadFile (parm->hd, buffer, sizeof buffer, &nread, NULL)), pth_leave (), rc) && nread) { log_debug ("feeder_thread pipe->estream: read %d bytes\n", (int)nread); do { if (parm->stream_valid && es_write (parm->stream, buffer, nread, &nwritten)) { log_debug ("feeder(%p): es_write error: %s\n", parm->hd, strerror (errno)); goto leave; } log_debug ("feeder_thread pipe->estream: es_wrote %d bytes\n", (int)nwritten); nread -= nwritten; } while (nread && parm->stream_valid); } if (!parm->stream_valid) log_debug ("feeder(%p): closed by other thread\n", parm->hd); else if (nread) log_debug ("feeder(%p): ReadFile error: rc=%d\n", parm->hd, (int)GetLastError ()); else log_debug ("feeder(%p): eof\n", parm->hd); } leave: log_debug ("feeder(%p): waiting for es_fclose\n", parm->hd); while (parm->stream_valid) pth_yield (NULL); log_debug ("feeder(%p): about to close the pipe handle\n", parm->hd); CloseHandle (parm->hd); log_debug ("feeder(%p): pipe handle closed\n", parm->hd); xfree (parm); return NULL; }
static void test_poll (void) { int ret; gpgrt_poll_t fds[3]; char buffer[16]; size_t used, nwritten; int c; memset (fds, 0, sizeof fds); fds[0].stream = test_stdin; fds[0].want_read = 1; fds[1].stream = test_stdout; fds[1].want_write = 1; /* FIXME: We don't use the next stream at all. */ fds[2].stream = test_stderr; fds[2].want_write = 1; fds[2].ignore = 1; used = 0; while (used || !fds[0].ignore) { ret = gpgrt_poll (fds, DIM(fds), -1); if (ret == -1) { fail ("gpgrt_poll failed: %s\n", strerror (errno)); continue; } if (!ret) { fail ("gpgrt_poll unexpectedly timed out\n"); continue; } show ("gpgrt_poll detected %d events\n", ret); if (fds[0].got_read) { /* Read from the producer. */ for (;;) { c = es_fgetc (fds[0].stream); if (c == EOF) { if (es_feof (fds[0].stream)) { show ("reading '%s': EOF\n", peer_stdin.name); fds[0].ignore = 1; /* Not anymore needed. */ peer_stdin.stop_me = 1; /* Tell the thread to stop. */ } else if (es_ferror (fds[0].stream)) { fail ("error reading '%s': %s\n", peer_stdin.name, strerror (errno)); fds[0].ignore = 1; /* Disable. */ peer_stdin.stop_me = 1; /* Tell the thread to stop. */ } else show ("reading '%s': EAGAIN\n", peer_stdin.name); break; } else { if (used <= sizeof buffer -1) buffer[used++] = c; if (used == sizeof buffer) { show ("throttling reading from '%s'\n", peer_stdin.name); fds[0].ignore = 1; break; } } } show ("read from '%s': %zu bytes\n", peer_stdin.name, used); if (used) fds[1].ignore = 0; /* Data to send. */ } if (fds[1].got_write) { if (used) { ret = es_write (fds[1].stream, buffer, used, &nwritten); show ("result for writing to '%s': ret=%d, n=%zu, nwritten=%zu\n", peer_stdout.name, ret, used, nwritten); if (!ret) { assert (nwritten <= used); /* Move the remaining data to the front of buffer. */ memmove (buffer, buffer + nwritten, sizeof buffer - nwritten); used -= nwritten; } ret = es_fflush (fds[1].stream); if (ret) fail ("Flushing for '%s' failed: %s\n", peer_stdout.name, strerror (errno)); } if (!used) fds[1].ignore = 1; /* No need to send data. */ } if (used < sizeof buffer / 2 && !peer_stdin.stop_me && fds[0].ignore) { show ("accelerate reading from '%s'\n", peer_stdin.name); fds[0].ignore = 0; } } }
CURLcode curl_easy_perform(CURL *curl) { int rc; CURLcode err=CURLE_OK; const char *errstr=NULL; char *proxy=NULL; struct http_srv srv; memset(&srv,0,sizeof(srv)); /* Emulate the libcurl proxy behavior. If the calling program set a proxy, use it. If it didn't set a proxy or set it to NULL, check for one in the environment. If the calling program explicitly set a null-string proxy the http code doesn't use a proxy at all. */ if(curl->proxy) proxy=curl->proxy; else proxy=getenv(HTTP_PROXY_ENV); if(curl->srvtag) srv.srvtag=curl->srvtag; if(curl->flags.verbose) { fprintf(curl->errors,"* HTTP proxy is \"%s\"\n",proxy?proxy:"null"); fprintf(curl->errors,"* HTTP URL is \"%s\"\n",curl->url); if(srv.srvtag) fprintf(curl->errors, "* SRV tag is \"%s\": host and port may be overridden\n", srv.srvtag); fprintf(curl->errors,"* HTTP auth is \"%s\"\n", curl->auth?curl->auth:"null"); fprintf(curl->errors,"* HTTP method is %s\n", curl->flags.post?"POST":"GET"); } if(curl->flags.post) { rc = http_open (&curl->hd, HTTP_REQ_POST, curl->url, curl->auth, 0, proxy, NULL, &srv, curl->headers?curl->headers->list:NULL); if (!rc) { unsigned int post_len = strlen(curl->postfields); if(curl->flags.verbose && srv.used_server && srv.used_port) fprintf (curl->errors, "* HTTP host:port post-SRV is \"%s:%hu\"\n", srv.used_server, srv.used_port); es_fprintf (http_get_write_ptr (curl->hd), "Content-Type: application/x-www-form-urlencoded\r\n" "Content-Length: %u\r\n", post_len); http_start_data (curl->hd); es_write (http_get_write_ptr (curl->hd), curl->postfields, post_len, NULL); rc = http_wait_response (curl->hd); curl->status = http_get_status_code (curl->hd); if (!rc && curl->flags.failonerror && curl->status>=300) err = CURLE_HTTP_RETURNED_ERROR; http_close (curl->hd, 0); curl->hd = NULL; } } else { rc = http_open (&curl->hd, HTTP_REQ_GET, curl->url, curl->auth, 0, proxy, NULL, &srv, curl->headers?curl->headers->list:NULL); if (!rc) { if(curl->flags.verbose && srv.used_server && srv.used_port) fprintf (curl->errors, "* HTTP host:port post-SRV is \"%s:%hu\"\n", srv.used_server, srv.used_port); rc = http_wait_response (curl->hd); curl->status = http_get_status_code (curl->hd); if (!rc) { if (curl->flags.failonerror && curl->status>=300) err = CURLE_HTTP_RETURNED_ERROR; else { size_t maxlen = 1024; size_t buflen; unsigned int len; char *line = NULL; while ((len = es_read_line (http_get_read_ptr (curl->hd), &line, &buflen, &maxlen))) { size_t ret; maxlen=1024; ret=(curl->writer)(line,len,1,curl->file); if(ret!=len) { err=CURLE_WRITE_ERROR; break; } } es_free (line); http_close(curl->hd, 0); curl->hd = NULL; } } else { http_close (curl->hd, 0); curl->hd = NULL; } } } xfree(srv.used_server); switch(gpg_err_code (rc)) { case 0: break; case GPG_ERR_INV_URI: err=CURLE_UNSUPPORTED_PROTOCOL; break; default: errstr=gpg_strerror (rc); err=CURLE_COULDNT_CONNECT; break; } return handle_error(curl,err,errstr); }