Exemple #1
0
/* Called by:  zxid_soap_call_raw */
struct zx_str* zxid_http_cli(zxid_conf* cf, int url_len, const char* url, int len, const char* data, const char* content_type, const char* headers, int flags)
{
#ifdef USE_CURL
  struct zx_str* ret;
  CURLcode res;
  struct zxid_curl_ctx rc;
  struct zxid_curl_ctx wc;
  struct curl_slist content_type_curl;
  struct curl_slist headers_curl;
  char* urli;
  rc.buf = rc.p = ZX_ALLOC(cf->ctx, ZXID_INIT_SOAP_BUF+1);
  rc.lim = rc.buf + ZXID_INIT_SOAP_BUF;

  /* The underlying HTTP client is libcurl. While libcurl is documented to
   * be "entirely thread safe", one limitation is that curl handle can not
   * be shared between threads. Since we keep the curl handle as a part
   * of the configuration object, which may be shared between threads,
   * we need to take a lock for duration of the curl operation. Thus any
   * given configuration object can have only one HTTP request active
   * at a time. If you need more parallelism, you need more configuration
   * objects.
   */

#if 0
  cf->curl = curl_easy_init();
  curl_easy_reset(cf->curl);
  LOCK_INIT(cf->curl_mx);
  LOCK(cf->curl_mx, "curl-cli");
#else
  LOCK(cf->curl_mx, "curl-cli");
  curl_easy_reset(cf->curl);
#endif

  curl_easy_setopt(cf->curl, CURLOPT_WRITEDATA, &rc);
  curl_easy_setopt(cf->curl, CURLOPT_WRITEFUNCTION, zxid_curl_write_data);
  curl_easy_setopt(cf->curl, CURLOPT_NOPROGRESS, 1);
  curl_easy_setopt(cf->curl, CURLOPT_SSL_VERIFYPEER, 0);  /* *** arrange verification */
  curl_easy_setopt(cf->curl, CURLOPT_SSL_VERIFYHOST, 0);  /* *** arrange verification */
  //curl_easy_setopt(cf->curl, CURLOPT_CERTINFO, 1);

  if (!(flags & 0x02)) {
    curl_easy_setopt(cf->curl, CURLOPT_FOLLOWLOCATION, 1);
    curl_easy_setopt(cf->curl, CURLOPT_MAXREDIRS, 110);
  }
  
  if (flags & 0x01)
    curl_easy_setopt(cf->curl, CURLOPT_HEADER, 1); /* response shall have Heacers CRLF CRLF Body */

  if (url_len == -1)
    url_len = strlen(url);
  urli = ZX_ALLOC(cf->ctx, url_len+1);
  memcpy(urli, url, url_len);
  urli[url_len] = 0;
  DD("urli(%s) len=%d", urli, len);
  curl_easy_setopt(cf->curl, CURLOPT_URL, urli);
  
  if (data) {
    if (len == -1)
      len = strlen(data);
    wc.buf = wc.p = (char*)data;
    wc.lim = (char*)data + len;
  
    curl_easy_setopt(cf->curl, CURLOPT_POST, 1);
    curl_easy_setopt(cf->curl, CURLOPT_POSTFIELDSIZE, len);
    curl_easy_setopt(cf->curl, CURLOPT_READDATA, &wc);
    curl_easy_setopt(cf->curl, CURLOPT_READFUNCTION, zxid_curl_read_data);
  
    ZERO(&content_type_curl, sizeof(content_type_curl));
    content_type_curl.data = (char*)content_type;
    if (headers) {
      ZERO(&headers_curl, sizeof(headers_curl));
      headers_curl.data = (char*)headers;
      headers_curl.next = &content_type_curl;    //curl_slist_append(3)
      curl_easy_setopt(cf->curl, CURLOPT_HTTPHEADER, &headers_curl);
    } else {
      curl_easy_setopt(cf->curl, CURLOPT_HTTPHEADER, &content_type_curl);
    }
  } else {
    if (headers) {
      ZERO(&headers_curl, sizeof(headers_curl));
      headers_curl.data = (char*)headers;
      curl_easy_setopt(cf->curl, CURLOPT_HTTPHEADER, &headers_curl);
    }
  }
  
  INFO("----------- call(%s) -----------", urli);
  DD("HTTP_CLI post(%.*s) len=%d\n", len, STRNULLCHK(data), len);
  D_XML_BLOB(cf, "HTTP_CLI POST", len, STRNULLCHK(data));
  res = curl_easy_perform(cf->curl);  /* <========= Actual call, blocks. */
  switch (res) {
  case 0: break;
  case CURLE_SSL_CONNECT_ERROR:
    ERR("Is the URL(%s) really an https url? Check that certificate of the server is valid and that certification authority is known to the client. CURLcode(%d) CURLerr(%s)", urli, res, CURL_EASY_STRERR(res));
    DD("buf(%.*s)", rc.lim-rc.buf, rc.buf);
#if 0
    struct curl_certinfo* ci;
    res = curl_easy_getinfo(cf->curl, CURLINFO_CERTINFO, &ci);  /* CURLINFO_SSL_VERIFYRESULT */
    if (!res && ci) {
      int i;
      struct curl_slist *slist;
      D("%d certs", ci->num_of_certs);
      for (i = 0; i < ci->num_of_certs; ++i)
	for (slist = ci->certinfo[i]; slist; slist = slist->next)
	  D("%d: %s", i, slist->data);
    }
#endif
    break;
  default:
    ERR("Failed post to url(%s) CURLcode(%d) CURLerr(%s)", urli, res, CURL_EASY_STRERR(res));
    DD("buf(%.*s)", rc.lim-rc.buf, rc.buf);
  }

  /*curl_easy_getinfo(cf->curl, CURLINFO_CONTENT_TYPE, char*);*/

  UNLOCK(cf->curl_mx, "curl-cli");
  ZX_FREE(cf->ctx, urli);
  rc.lim = rc.p;
  rc.p[0] = 0;

  DD("HTTP_CLI got(%s)", rc.buf);
  DD_XML_BLOB(cf, "HTTP_CLI GOT", rc.lim - rc.buf, rc.buf);
  
  ret = zx_ref_len_str(cf->ctx, rc.lim - rc.buf, rc.buf);
  return ret;
#else
  ERR("This copy of zxid was compiled to NOT use libcurl. SOAP calls (such as Artifact profile and WSC) are not supported. Add -DUSE_CURL (make ENA_CURL=1) and recompile. %d", 0);
  return 0;
#endif
}
Exemple #2
0
/* Called by:  zxid_soap_call_raw */
struct zx_str* zxid_http_post_raw(zxid_conf* cf, int url_len, const char* url, int len, const char* data, const char* SOAPaction)
{
#ifdef USE_CURL
  struct zx_str* ret;
  CURLcode res;
  struct zxid_curl_ctx rc;
  struct zxid_curl_ctx wc;
  struct curl_slist content_type;
  struct curl_slist SOAPaction_curl;
  char* urli;
  rc.buf = rc.p = ZX_ALLOC(cf->ctx, ZXID_INIT_SOAP_BUF+1);
  rc.lim = rc.buf + ZXID_INIT_SOAP_BUF;
#if 0
  cf->curl = curl_easy_init();
  curl_easy_reset(cf->curl);
  LOCK_INIT(cf->curl_mx);
  LOCK(cf->curl_mx, "curl-soap");
#else
  LOCK(cf->curl_mx, "curl-soap");
  curl_easy_reset(cf->curl);
#endif
  curl_easy_setopt(cf->curl, CURLOPT_WRITEDATA, &rc);
  curl_easy_setopt(cf->curl, CURLOPT_WRITEFUNCTION, zxid_curl_write_data);
  curl_easy_setopt(cf->curl, CURLOPT_NOPROGRESS, 1);
  curl_easy_setopt(cf->curl, CURLOPT_FOLLOWLOCATION, 1);
  curl_easy_setopt(cf->curl, CURLOPT_MAXREDIRS, 110);
  curl_easy_setopt(cf->curl, CURLOPT_SSL_VERIFYPEER, 0);  /* *** arrange verification */
  curl_easy_setopt(cf->curl, CURLOPT_SSL_VERIFYHOST, 0);  /* *** arrange verification */
  //curl_easy_setopt(cf->curl, CURLOPT_CERTINFO, 1);

  if (url_len == -1)
    url_len = strlen(url);
  urli = ZX_ALLOC(cf->ctx, url_len+1);
  memcpy(urli, url, url_len);
  urli[url_len] = 0;
  DD("urli(%s) len=%d", urli, len);
  curl_easy_setopt(cf->curl, CURLOPT_URL, urli);
  
  if (len == -1)
    len = strlen(data);
  wc.buf = wc.p = (char*)data;
  wc.lim = (char*)data + len;
  
  curl_easy_setopt(cf->curl, CURLOPT_POST, 1);
  curl_easy_setopt(cf->curl, CURLOPT_POSTFIELDSIZE, len);
  curl_easy_setopt(cf->curl, CURLOPT_READDATA, &wc);
  curl_easy_setopt(cf->curl, CURLOPT_READFUNCTION, zxid_curl_read_data);

  ZERO(&content_type, sizeof(content_type));
  content_type.data = cf->wsc_soap_content_type; /* SOAP11: "Content-Type: text/xml" */
  if (SOAPaction) {
    ZERO(&SOAPaction_curl, sizeof(SOAPaction_curl));
    SOAPaction_curl.data = (char*)SOAPaction;
    SOAPaction_curl.next = &content_type;    //curl_slist_append(3)
    curl_easy_setopt(cf->curl, CURLOPT_HTTPHEADER, &SOAPaction_curl);
  } else {
    curl_easy_setopt(cf->curl, CURLOPT_HTTPHEADER, &content_type);
  }
  
  INFO("----------- call(%s) -----------", urli);
  DD("SOAP_CALL post(%.*s) len=%d\n", len, data, len);
  D_XML_BLOB(cf, "SOAPCALL POST", len, data);
  res = curl_easy_perform(cf->curl);  /* <========= Actual call, blocks. */
  switch (res) {
  case 0: break;
  case CURLE_SSL_CONNECT_ERROR:
    ERR("Is the URL(%s) really an https url? Check that certificate of the server is valid and that certification authority is known to the client. CURLcode(%d) CURLerr(%s)", urli, res, CURL_EASY_STRERR(res));
    DD("buf(%.*s)", rc.lim-rc.buf, rc.buf);
#if 0
    struct curl_certinfo* ci;
    res = curl_easy_getinfo(cf->curl, CURLINFO_CERTINFO, &ci);  /* CURLINFO_SSL_VERIFYRESULT */
    if (!res && ci) {
      int i;
      struct curl_slist *slist;
      D("%d certs", ci->num_of_certs);
      for (i = 0; i < ci->num_of_certs; ++i)
	for (slist = ci->certinfo[i]; slist; slist = slist->next)
	  D("%d: %s", i, slist->data);
    }
#endif
    break;
  default:
    ERR("Failed post to url(%s) CURLcode(%d) CURLerr(%s)", urli, res, CURL_EASY_STRERR(res));
    DD("buf(%.*s)", rc.lim-rc.buf, rc.buf);
  }

  /*curl_easy_getinfo(cf->curl, CURLINFO_CONTENT_TYPE, char*);*/

  UNLOCK(cf->curl_mx, "curl-soap");
  ZX_FREE(cf->ctx, urli);
  rc.lim = rc.p;
  rc.p[0] = 0;

  DD("SOAP_CALL got(%s)", rc.buf);
  D_XML_BLOB(cf, "SOAPCALL GOT", rc.lim - rc.buf, rc.buf);
  
  ret = zx_ref_len_str(cf->ctx, rc.lim - rc.buf, rc.buf);
  return ret;
#else
  ERR("This copy of zxid was compiled to NOT use libcurl. SOAP calls (such as Artifact profile and WSC) are not supported. Add -DUSE_CURL (make ENA_CURL=1) and recompile. %d", 0);
  return 0;
#endif
}