Re: VMS fixes needed to allow building

2013-03-13 Thread Yang Tse
Tom and John,

Issues mentioned here have been addressed with following commits:

https://github.com/bagder/curl/commit/17c088fb45
https://github.com/bagder/curl/commit/8ae9ee0cf2

Daily snapshot (http://curl.haxx.se/snapshots/) of March 14 should
include these.

Thanks,
-- 
-=[Yang]=-
---
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette:  http://curl.haxx.se/mail/etiquette.html


Re: VMS fixes needed to allow building.

2013-03-13 Thread Yang Tse
On Wed, Mar 13, John E. Malmberg wb8...@qsl.net wrote:

 I have a git clone in one directory tree now and it has the command
 procedures needed to build the .h files.  I have not tested them.
 I can not run autoconf on VMS to generate the configure and
 lib/curl_config_in.

 [...]

 I pulled down the March 13th, 2013 snapshot and unpacked it.  It is also
 missing the VMS specific build files in the packages/vms directory that I
 can see in the git repository.

Fixed now with commit:

https://github.com/bagder/curl/commit/308dc625f7

March 14 daily snapshot should include them now.

Something I've noticed about the build process...

build_curlbuild_h.com attempts to generate file curlbuild.h. But the
file it generates is not a proper one. It has dependencies on several
HAVE_* preprocessor macros which is wrong for curlbuild.h.

Given that it is not possible to run autoconf, I suggest you make
direct use of curlbuild.h if it exists (daily and release tarballs),
and simply copy curlbuild.h.dist to curlbuild.h when it doesn't exist
(git pull).

This will also ensure that whatever changes are done to
curlbuild.h.dist are automatically taken in account for VMS builds,
without someone having to figure out that VMS builds get broken.

-- 
-=[Yang]=-
---
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette:  http://curl.haxx.se/mail/etiquette.html


Avoid write callbacks

2013-03-13 Thread Florian Weimer
Is there a way to avoid callbacks, while still supporting incremental
retrieval of data?  In a nutshell, I'm looking for an iterator-like
interface.

I could use the multi interface with a custom write function which
writes to an in-memory buffer.  I would run the event loop until that
buffer contains some data.  My iterator would return data from the
buffer as long as some is available.  It would run some iterations of
the event loop to get more data.

But I wonder if there is an easier way to accomplish this.
---
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette:  http://curl.haxx.se/mail/etiquette.html


RE: CURLE_OPERATION_TIMEDOUT using curl_multi_socket_action

2013-03-13 Thread Paras S
 I will work on writing a sample code and will mail it by tomorrow.

Find the sample program attached which illustrates the problem I am facing.
I am using Mozilla's NSPR: http://www.mozilla.org/projects/nspr/
  #include sys/epoll.h
#include curl/curl.h
#include prtpool.h
#include prlock.h
#include prcvar.h

#define EASY_COUNT 100

PRThreadPool *gPool;
CURLM *gMulti;
int gEpollFd;
PRLock *gIoQueueLock;
PRCondVar *gIoQueueWait;
PRLock *gMultiLock;
int gIoQueueCount;

struct ConnectionInfo {
  CURL *easy;
  curl_socket_t socket;
  int action;
  PRJob *job;
} gEasy[EASY_COUNT];

size_t curl_writer(void *ptr, size_t size, size_t nmemb, void *param) {
  return size*nmemb;
}

void setup_easy(CURL *easy) {
  curl_easy_setopt(easy, CURLOPT_TIMEOUT, 300L);
  curl_easy_setopt(easy, CURLOPT_CONNECTTIMEOUT, 30L);
  curl_easy_setopt(easy, CURLOPT_FOLLOWLOCATION, 0L);
  curl_easy_setopt(easy, CURLOPT_VERBOSE, 1L);
  curl_easy_setopt(easy, CURLOPT_WRITEFUNCTION, curl_writer); //Ignore output 
from server
  curl_easy_setopt(easy, CURLOPT_SSL_VERIFYPEER, 0L);
  curl_easy_setopt(easy, CURLOPT_URL, https://www.google.com/ncr;);
  curl_easy_setopt(easy, CURLOPT_SSL_SESSIONID_CACHE, 0L);
}

void curl_calls(void *arg) {
  ConnectionInfo *info = (ConnectionInfo*) arg;
  int still_running;
  
  PR_Lock(gMultiLock);
  if (info-socket == CURL_SOCKET_BAD) { //Job is running for the first time.
//Do some operation which takes a couple of seconds.
PR_Sleep(PR_SecondsToInterval(1));
curl_multi_add_handle(gMulti, info-easy);
  }
  curl_multi_socket_action(gMulti, info-socket, info-action, still_running);
  PR_Unlock(gMultiLock);

  if (info-action  CURL_POLL_INOUT) {
epoll_event event;
event.events = EPOLLRDHUP | EPOLLONESHOT
  | (info-action  CURL_POLL_IN ? EPOLLIN : 0)
  | (info-action  CURL_POLL_OUT ? EPOLLOUT : 0);
event.data.ptr = info;
epoll_ctl(gEpollFd, EPOLL_CTL_ADD, info-socket, event);
PR_Lock(gIoQueueLock);
gIoQueueCount++;
info-job = PR_QueueJob_Timer(gPool, PR_SecondsToInterval(300), curl_calls, 
info, PR_FALSE);
PR_NotifyCondVar(gIoQueueWait);
PR_Unlock(gIoQueueLock);
  }
}

int socket_callback(CURL *easy, curl_socket_t socket, int action, void 
*multi_data, void *socket_data) {
  ConnectionInfo *info;
  curl_easy_getinfo(easy, CURLINFO_PRIVATE, info);
  info-action = action;
  info-socket = socket;
  return 0;
}

void epoll_calls(void *arg) {
  PR_Lock(gIoQueueLock);
  while(true) {
PR_WaitCondVar(gIoQueueWait, PR_INTERVAL_NO_TIMEOUT);
epoll_event events[10];
int n;
do {
  PR_Unlock(gIoQueueLock);
  if ((n = epoll_wait(gEpollFd, events, 10, 3000))  0) {
PR_Lock(gIoQueueLock);
for (int i = 0; i  n; ++i) {
  ConnectionInfo *info = (ConnectionInfo*) events[i].data.ptr;
  PR_CancelJob(info-job);
  epoll_ctl(gEpollFd, EPOLL_CTL_DEL, info-socket, NULL);
  info-job = PR_QueueJob(gPool, curl_calls, info, PR_FALSE);
}
gIoQueueCount -= n;
PR_Unlock(gIoQueueLock);
  }
  PR_Lock(gIoQueueLock);
} while (gIoQueueCount  0);
  }
}

int main() {
  curl_global_init(CURL_GLOBAL_ALL);
  gEpollFd = epoll_create(1);
  gIoQueueLock = PR_NewLock();
  gIoQueueWait = PR_NewCondVar(gIoQueueLock);
  gMultiLock = PR_NewLock();
  gPool = PR_CreateThreadPool(5, 5, 1024*1024);
  gMulti = curl_multi_init();
  curl_multi_setopt(gMulti, CURLMOPT_SOCKETFUNCTION, socket_callback);

  PR_QueueJob(gPool, epoll_calls, NULL, PR_FALSE);

  for (int i = 0; i  EASY_COUNT; ++i) {
gEasy[i].socket = CURL_SOCKET_BAD;
gEasy[i].easy = curl_easy_init();
curl_easy_setopt(gEasy[i].easy, CURLOPT_PRIVATE, gEasy + i);
setup_easy(gEasy[i].easy);

gEasy[i].job = PR_QueueJob(gPool, curl_calls, gEasy + i, PR_FALSE);
  }
  PR_JoinThreadPool(gPool);
  return 0;
}---
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette:  http://curl.haxx.se/mail/etiquette.html

Re: VMS fixes needed to allow building

2013-03-13 Thread Tom Grace
Date: Tue, 12 Mar 2013 22:02:45 -0500
From: John E. Malmberg wb8...@qsl.net
Subject: Re: VMS fixes needed to allow building
Message-ID: khoq6v$q6d$1...@ger.gmane.org

On 3/12/2013 7:17 PM, Tom Grace wrote:
 Using extern int vms_show = 0 also creates
 a  globaldef.

globaldef is only for use with code intended to be compiled with the
very obsolete VAXC compiler.  It should not be used for anything new or
current.

Yes your exactly right,   I should of said that the use of
extern int vms_show = 0 ;   defines a global symbol internally
just like the old-form globaldef .  (in addition to the psect ref)
So that the linker will be happy.

So does the form, but it is a weak ? globaldef.
int vms_show;   /* outside a function*/

so is the recommendation?   one extern int vms_show = 0;
and multiple extern int vms_show



This message and the information contained herein is proprietary and 
confidential and subject to the Amdocs policy statement,
you may review at http://www.amdocs.com/email_disclaimer.asp
---
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette:  http://curl.haxx.se/mail/etiquette.html

Strange performance discrepancy with proxy

2013-03-13 Thread Matt Kunze
We have recently integrated libcurl into our application to provide the
underlying HTTP transport (replacing WinINET, which is a huge improvement,
thanks!). The application is using the multi interface, though for the most
part on a single request is made at a given time.

I'm seeing strange behavior where requests are _much_ faster when routed
through a proxy (in this case the Fiddler diagnostic tool). Note that this
is
not a caching proxy, and all the requests are POSTs anyway, so I don't
think
that is the explanation. If I run the app with an HTTP_PROXY environment
variable defined it is much faster than without - the code is the same in
both
cases. I've instrumented the code as well to display the progression of
requests, and it appears to be the same in both cases except the proxied
requests return much faster.

I'd love to have the same performance regardless of whether or not a proxy
is
used, so is there something I'm potentially missing that might speed up the
non- proxied case as well?

thanks

matt
---
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette:  http://curl.haxx.se/mail/etiquette.html

Re: Avoid write callbacks

2013-03-13 Thread Dan Fandrich
On Wed, Mar 13, 2013 at 01:01:35PM +0100, Florian Weimer wrote:
 Is there a way to avoid callbacks, while still supporting incremental
 retrieval of data?  

Unless you're writing to a FILE*, libcurl gives no other option for
writing received data without using callbacks. But, you can certainly
wrap libcurl in such a way that the use of callbacks is hidden from the 
application.

 In a nutshell, I'm looking for an iterator-like
 interface.
 
 I could use the multi interface with a custom write function which
 writes to an in-memory buffer.  I would run the event loop until that
 buffer contains some data.  My iterator would return data from the
 buffer as long as some is available.  It would run some iterations of
 the event loop to get more data.

That solution sounds perfectly doable. Take a look at the fopen.c example
program for an example of a libcurl wrapper that provides a stdio-like
interface.

 But I wonder if there is an easier way to accomplish this.

It sounds like the API you want doesn't quite match the API libcurl provides,
in which case some amount of code is going to be necessary to handle the
mismatch. It doesn't have to be a lot. Take a look also at the existing C++
binding (or bindings?) to see if that might not better suit you.

 Dan
---
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette:  http://curl.haxx.se/mail/etiquette.html


Re: [PATCH] Addition of trailer headers in HTTP requests generated by libcurl

2013-03-13 Thread Daniel Stenberg

On Mon, 11 Mar 2013, Chrysovaladis Datsios wrote:


changes are in the attached patch.


Thanks. I would say that this is close to getting merged. My main issue is 
remark #4 which kind of made #5 slip in...


1 - invalid email in the Author: field

2 - incomplete commit message

3 - transfer.c:245:11: error: conversion to 'int' from 'size_t' may alter its
value [-Werror=conversion]

4 - lack of test cases. It makes it really hard for us to say that this works
even in corner cases.

5 - this version still has memory leaks, like if the realloc (on
transfer.c:228) fails the previous trailer_headers_buf is not freed.

6 - getting the two new options documented

The window for new features is just closed for 7.30.0, but it is looking good 
for getting merged when we open it again after that release.


--

 / daniel.haxx.se
---
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette:  http://curl.haxx.se/mail/etiquette.html


Re: [PATCH] Addition of trailer headers in HTTP requests generated by libcurl

2013-03-13 Thread Dan Fandrich
On Mon, Mar 11, 2013 at 06:09:29PM +0200, Chrysovaladis Datsios wrote:
 --- a/lib/transfer.c
 +++ b/lib/transfer.c
 @@ -193,6 +193,71 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, 
 int bytes, int *nreadp)
  /* copy the prefix to the buffer, leaving out the NUL */
  memcpy(data-req.upload_fromhere, hexbuffer, hexlen);
  
 +/* If is the last chunk, here put the trailer headers if any */
 +if((nread - hexlen) == 0) {
 +  if(data-set.trailerheaders_func) {
 +struct curl_slist *trailer_headers;
 +struct curl_slist *list_head;
 +
 +/* The callback function that adds trailer header values */
 +trailer_headers = (data-set.trailerheaders_func)(data,
 +  data-set.trailer_udata);
 +list_head = trailer_headers;
 +if(trailer_headers) {
 +  char *ptr;

While we're here, this could be made const char *ptr (and it could be moved
into the body of the while loop).

 +  size_t headers_buf_size;
 +  size_t endl_len;
 +  size_t data_len;
 +  size_t headers_index;
 +  char *trailer_headers_buf;
 +
 +  endl_len = strlen(endofline_native);
 +  headers_buf_size = HEADERSIZE;
 +  trailer_headers_buf = malloc(headers_buf_size);
 +  if(trailer_headers_buf == NULL)
 +return CURLE_BAD_FUNCTION_ARGUMENT;
 +  memcpy(trailer_headers_buf, hexbuffer, hexlen);
 +  headers_index = hexlen;
 +
 +  while(trailer_headers) {
 +/* header name_field : header value_field */
 +ptr = strchr(trailer_headers-data, ':');
 +if(ptr) {
 +  data_len = strlen(trailer_headers-data);
 +  if(headers_index + data_len + 2*endl_len  headers_buf_size) {
 +size_t newsize = headers_index + data_len + 2*endl_len;
 +if(newsize  CURL_MAX_HTTP_HEADER) {
 +  curl_slist_free_all(list_head);
 +  list_head = NULL;
 +  return CURLE_BAD_FUNCTION_ARGUMENT;

trailer_headers_buf will leak here.

 +}
 +trailer_headers_buf = realloc(trailer_headers_buf, newsize);
 +if(trailer_headers_buf == NULL) {
 +  curl_slist_free_all(list_head);
 +  list_head = NULL;

I wouldn't bother setting a local variable to NULL immediately before
returning. Same just above. 

 +  return CURLE_BAD_FUNCTION_ARGUMENT;
 +}
 +headers_buf_size = newsize;
 +  }
 +  memcpy(trailer_headers_buf + headers_index,
 + trailer_headers-data, 
 data_len);
 +  headers_index += data_len;
 +  memcpy(trailer_headers_buf + headers_index,
 +  endofline_native, 
 endl_len);
 +  headers_index += endl_len;
 +}
 +trailer_headers = trailer_headers-next;
 +  }
 +  nread = headers_index;
 +  data-req.upload_fromhere = trailer_headers_buf;

I still don't see where trailer_headers_buf is ever freed.

 +  curl_slist_free_all(list_head);
 +  list_head = NULL;

I wouldn't bother with this NULL setting either, since list_head goes
out of scope here anyway.

 +}
 +  }
 +  /* mark this as done once this chunk is transferred */
 +  data-req.upload_done = TRUE;

Moving this here changes the behaviour when the CURL_DOES_CONVERSIONS
exits due to an error. This is probably fine, but have you verified that there
aren't any unexpected effects through the error path?

 +}
 +
  /* always append ASCII CRLF to the data */
  memcpy(data-req.upload_fromhere + nread,
 endofline_network,
 @@ -215,10 +280,6 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, 
 int bytes, int *nreadp)
return(res);
  #endif /* CURL_DOES_CONVERSIONS */
  
 -if((nread - hexlen) == 0)
 -  /* mark this as done once this chunk is transferred */
 -  data-req.upload_done = TRUE;
 -
  nread+=(int)strlen(endofline_native); /* for the added end of line */
}
  #ifdef CURL_DOES_CONVERSIONS

 Dan
---
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette:  http://curl.haxx.se/mail/etiquette.html


Re: VMS fixes needed to allow building

2013-03-13 Thread Yang Tse
On Wed, Mar 13, 2013 at 4:13 PM, Tor Arntsen kspt@gmail.com wrote:

 [...] Usually the latter is achieved by having extern int
 vms_show; in a header file and including it in the necessary .c files
 (and in exactly one of them you put the 'int vms_show=0;')

Removed redundant 'extern' now with
https://github.com/bagder/curl/commit/911b2d3f67

Thanks,
-- 
-=[Yang]=-
---
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette:  http://curl.haxx.se/mail/etiquette.html


vms_show hack explained

2013-03-13 Thread John E. Malmberg
The vms_show hack can definitely be improved and simplified.  I just 
have not had the time to investigate it.


What is going on is that on VMS, the parameter to exit() is a packed 
bitmap that encodes a pointer to a message text and also a severity code.


On exit, if that severity code is for warning or more severe level, the 
message associated with the packed bitmap is displayed by the DCL shell.


This message can be suppressed by setting a bit in the bitmap, which is 
done if the application has already displayed it.


Now what was done on VMS, is that the vms_show variable is being set to 
indicate that an error message has been displayed.


Then on vms_special_exit() the Unix exit status is mapped to the VMS 
packed exit code, and the vms_show is used to suppress the message.


But there is one more wrinkle.  This VMS status code is useful for the 
VMS shell, but is the wrong code for programs like bash, that may have 
launched curl.


So when curl is run under Bash, it needs to encode the UNIX exit code so 
that can be then decoded by Bash.


Normally this is done at compile time by mapping exit() to actually be 
posix_exit() and the UNIX program does not need VMS specific code.


But curl was ported to use its own VMS specific exit codes first, and 
those can not be passed to the posix_exit() routine.


So the vms_special_exit() needs to check to see which variant of exit 
that it should call.


Now if we know at the time that vms_special_exit is called that any exit 
status other than CURLE_OK means that an error message has been written, 
there is no need to have the vms_show hack at all.


We just need to have the VMS specific wrapper to exit() handle 
everything.  If that a VMS specific wrapper is changed to be a macro in 
a VMS header file, then this all can be hidden from the common Unix code.



One feature of the separate message file on VMS is that it can be built 
as a shared image, and you can have a different shared image for 
different languages, but one program executable.  The VMS port of curl 
does not take advantage of this, as the messages in the VMS message file 
are never displayed.



Regards,
-John
wb8...@qsl.net
Personal Opinion Only

---
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette:  http://curl.haxx.se/mail/etiquette.html