libmicrohttpd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[libmicrohttpd] Re: libmicrohttpd - question on tutorial


From: Christian Grothoff
Subject: [libmicrohttpd] Re: libmicrohttpd - question on tutorial
Date: Thu, 17 Feb 2011 18:15:26 +0100
User-agent: KMail/1.13.5 (Linux/2.6.32-trunk-vserver-amd64; KDE/4.4.5; x86_64; ; )

sendfile64 here refers to 64-bit 'off_t' ("large files"), not to 64-bit 
'size_t' 
(heap/pointer size).   Still, this could be related to 32 vs. 64-bit issues.  

Based on what I've read so far, MHD's calculation of the length argument 
("connection->response->total_size - offset") would not seem to be 
correct/working for files larger than 2^32 (and the 'ret' value would be 
insufficient for values > 2^31, as I've seen in some discussions on sendfile 
online now).  The solution to this will be to cap the length argument at 2 GB, 
I'll probably take care of that later once we understand the real issue here 
better:

Since  your file is not larger than 2 GB, this "minor" issue does NOT explain 
your problem.  Could you add

fprintf (stderr, "offset: %llu, size: %llu, delta: %llu\n",
          (unsigned long long) offset,
         (unsigned long long) connection->response->total_size,
          (unsigned long long) (connection->response->total_size - offset));

on the line before the 'sendfile' call?  That way, we can see if the odd length 
argument comes from within MHD (=> MHD bug) or from libc's handling of the 
arguments (=> libc bug).

Thanks!

Christian

On Thursday 17 February 2011 17:27:14 Neil D'Souza wrote:
> I think I have the culprit. Pasted below is the output with the offending
> linehighlighted. But I do not know why this is happening? I was using an
> image file about 1.3 mb earlier - I changed it to a file 72 kb - just to
> check that there are no internal restrictions on the file size which have
> to be changed by some config parameter. It has failed again for a 72 kb
> file in the sendfile64 call.
> 
> I quickly ran this check to verify that my system is 32 bit
> 
> #include <iostream>
> 
> using namespace std;
> 
> int main()
> {
>     char * ptr;
>     cout << "sizeof(ptr): " << sizeof(ptr) << endl;
> }
> 
> 
> /media/sda3/home/nxd/Prog/C/microhttpd/tutorial>./sizeof_ptr
> sizeof(ptr): 4
> 
> I find it odd that the kernel is calling sendfile64 when the system is
> 32bit - because sendfile64 shows up in the man page, however my knowledge
> of the linux kernel is close to 0. So I should not hazard any guesses.
> 
> 
> 
> pid  5695] select(5, [4], [], [], {1, 0}) = 0 (Timeout)
> [pid  5695] select(5, [4], [], [], {1, 0}) = 0 (Timeout)
> [pid  5695] select(5, [4], [], [], {1, 0}) = 0 (Timeout)
> [pid  5695] select(5, [4], [], [], {1, 0}) = 0 (Timeout)
> [pid  5695] select(5, [4], [], [], {1, 0}) = 0 (Timeout)
> [pid  5695] select(5, [4], [], [], {1, 0}) = 1 (in [4], left {0, 564047})
> [pid  5695] accept(4, {sa_family=AF_INET, sin_port=htons(49723),
> sin_addr=inet_addr("127.0.0.1")}, [16]) = 5
> [pid  5695] time(NULL)                  = 1297958855
> [pid  5695] mmap2(NULL, 32768, PROT_READ|PROT_WRITE,
> MAP_FILE|MAP_ANONYMOUS, -1, 0) = -1 EINVAL (Invalid argument)
> [pid  5695] select(6, [4 5], [], [], {1, 0}) = 1 (in [5], left {0, 999995})
> [pid  5695] time(NULL)                  = 1297958855
> [pid  5695] recv(5, "GET / HTTP/1.1\r\nHost: localhost:"..., 2048,
> MSG_DONTWAIT|MSG_NOSIGNAL) = 383
> [pid  5695] fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 1),
> ...}) = 0 [pid  5695] mmap2(NULL, 4096, PROT_READ|PROT_WRITE,
> MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb789f000
> [pid  5695] write(1, "New GET request for / using vers"..., 45New GET
> request for / using version HTTP/1.1
> ) = 45
> [pid  5695] open("after-the-rain.jpg", O_RDONLY) = 6
> [pid  5695] fstat64(6, {st_mode=S_IFREG|0644, st_size=72313, ...}) = 0
> [pid  5695] shutdown(5, 0 /* receive */) = 0
> [pid  5695] write(1, "queued response\n", 16queued response
> ) = 16
> [pid  5695] time(NULL)                  = 1297958855
> [pid  5695] open("/etc/localtime", O_RDONLY) = 7
> [pid  5695] fstat64(7, {st_mode=S_IFREG|0644, st_size=265, ...}) = 0
> [pid  5695] fstat64(7, {st_mode=S_IFREG|0644, st_size=265, ...}) = 0
> [pid  5695] mmap2(NULL, 4096, PROT_READ|PROT_WRITE,
> MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb789e000
> [pid  5695] read(7,
> "TZif2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\4\0\0\0\4\0\0\0\0"..., 4096) =
> 265 [pid  5695] _llseek(7, -10, [255], SEEK_CUR) = 0
> [pid  5695] read(7, "\nIST-5:30\n", 4096) = 10
> [pid  5695] close(7)                    = 0
> [pid  5695] munmap(0xb789e000, 4096)    = 0
> [pid  5695] setsockopt(5, SOL_TCP, TCP_CORK, [1], 4) = 0
> [pid  5695] select(6, [4], [5], [], {1, 0}) = 1 (out [5], left {0, 999996})
> [pid  5695] time(NULL)                  = 1297958855
> [pid  5695] send(5, "HTTP/1.1 200 OK\r\nContent-Length:"..., 104,
> MSG_DONTWAIT|MSG_NOSIGNAL) = 104
> [pid  5695] select(6, [4], [5], [], {1, 0}) = 1 (out [5], left {0, 999996})
> [pid  5695] time(NULL)                  = 1297958855
> [pid  5695] sendfile64(5, 6, [683649624044470272], 72313) = -1 EOVERFLOW
> (Value too large for defined data type)
> [pid  5695] shutdown(5, 2 /* send and receive */) = 0
> [pid  5695] close(5)                    = 0
> [pid  5695] close(6)                    = 0
> 
> 
> Thanks
> Neil
> 
> 
> ________________________________
> From: Christian Grothoff <address@hidden>
> To: Neil D'Souza <address@hidden>
> Cc: address@hidden
> Sent: Thu, February 17, 2011 8:31:19 PM
> Subject: Re: libmicrohttpd - question on tutorial
> 
> Hi!
> 
> I just tried this:
> 
> $ echo test > picture.png
> $ gcc -o srv -g -I /usr/local/include/ \
>     -L/usr/local/lib/ -lmicrohttpd responseheaders.c
> $ ./srv &
> $ telnet localhost 8888
> Trying ::1...
> Trying 127.0.0.1...
> Connected to localhost.
> Escape character is '^]'.
> GET /dontcare HTTP/1.1
> Host: itsme
> 
> HTTP/1.1 200 OK
> Content-Length: 5
> Content-Type: image/png
> Date: Thu, 17 Feb 2011 14:47:53 GMT
> 
> test
> Connection closed by foreign host.
> 
> 
> So this worked on my system (which is Debian, but should make no
> difference) using the (except #includes) unmodified responseheaders.c
> against MHD 0.9.7.
> 
> So this is rather confusing, especially given that you did use the same
> code (!?).  Does your image file have some access permissions that might
> cause problems? Try running the server with 'strace -f' and see what the
> system calls do -- there SHOULD be one to 'sendfile' for the actual
> transmission (shortly after your 'open' call to picture.png).  That might
> help.  Here is what mine looks like:
> 
> After telnet accept, select waits for 'GET' (I post the entire request at
> once with middle-mouse click):
> [pid 19650] select(6, [4 5], [], [], {1, 0}) = 1 (in [5], left {0, 556551})
> [pid 19650] recvfrom(5, "GET / HTTP/1.1\r\nHost: me\r\n\r\n", 2048,
> MSG_DONTWAIT|MSG_NOSIGNAL, NULL, NULL) = 28
> 
> Here is the open call:
> [pid 19650] open("picture.png", O_RDONLY) = 6
> [pid 19650] fstat(6, {st_mode=S_IFREG|0644, st_size=5, ...}) = 0
> [pid 19650] shutdown(5, 0 /* receive */) = 0
> 
> Part of MHD header response creation involves getting system time:
> [pid 19650] open("/etc/localtime", O_RDONLY) = 7
> [pid 19650] fstat(7, {st_mode=S_IFREG|0644, st_size=2309, ...}) = 0
> [pid 19650] fstat(7, {st_mode=S_IFREG|0644, st_size=2309, ...}) = 0
> [pid 19650] mmap(NULL, 4096, PROT_READ|PROT_WRITE,
> MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fe5da3b7000
> [pid 19650] read(7,
> "TZif2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\10\0\0\0\10\0\0\0\0"..., 4096) =
> 2309
> [pid 19650] lseek(7, -1467, SEEK_CUR)   = 842
> [pid 19650] read(7,
> "TZif2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\t\0\0\0\t\0\0\0\0"..., 4096) =
> 1467 [pid 19650] close(7)                    = 0
> [pid 19650] munmap(0x7fe5da3b7000, 4096) = 0
> 
> Then MHD sends the header (cork on):
> [pid 19650] setsockopt(5, SOL_TCP, TCP_CORK, [1], 4) = 0
> [pid 19650] select(6, [4], [5], [], {1, 0}) = 1 (out [5], left {0, 999998})
> [pid 19650] sendto(5, "HTTP/1.1 200 OK\r\nContent-Length:"..., 100,
> MSG_DONTWAIT|MSG_NOSIGNAL, NULL, 0) = 100
> 
> Then MHD waits again to send the body (cork off):
> [pid 19650] select(6, [4], [5], [], {1, 0}) = 1 (out [5], left {0, 999998})
> [pid 19650] sendfile(5, 6, [0], 5)      = 5
> [pid 19650] setsockopt(5, SOL_TCP, TCP_CORK, [0], 4) = 0
> 
> Finally, we're done and close the file and socket:
> [pid 19650] close(6)                    = 0
> [pid 19650] shutdown(5, 2 /* send and receive */) = 0
> [pid 19650] close(5)                    = 0
> 
> Back to waiting for more:
> [pid 19650] select(5, [4], [], [], {1, 0}) = 0 (Timeout)
> 
> 
> Any changes from this sequence (return values, etc.) might help explain
> what's going on...
> 
> Happy hacking,
> 
> Christian
> 
> On Thursday 17 February 2011 15:26:05 Neil D'Souza wrote:
> > Hello Christian,
> > 
> > First of all Thank you for the excellently written tutorial. I myself am
> > working on a language for scripting questionnaires for the Market
> > Research industry. You can see the project here
> > http://sourceforge.net/projects/xtcc - the compiler is called qscript
> > (for Questionnaire Script).
> > 
> > It currently generates code for simple data entry in an ncurses
> > interface. Installing the compiler requires the presence of gcc, ncurses
> > and compiling qscript from source - which can be big barriers for
> > adoption/trying. I am trying to embed the generated code inside a
> > web-server and demo what the interface looks like and the programming
> > language looks like - hence my interest in libmicrohttpd. I am going
> > through the tutorial so that I can understand libmicrohttpd usage.
> > 
> > I have reached Chapter 4 where we send the png image. below is a slightly
> > modified function just for me to be sure that things were working.
> > However the image did not appear in the browser. So I telnetted to port
> > 8888. As you can see the png file is not sent - otherwise there should
> > have been a bytestream of the image data. It seems that after getting
> > enqueued the file is not transmitted. Just wanted to check if I am
> > missing something. I tried with Konqueror and Firefox before resorting
> > to telnet.
> > 
> > Also wanted to add that you need to include
> > #include <sys/stat.h>
> > #include <fcntl.h>
> > 
> >  to responseheaders.c to compile with gcc version 4.4.1 . I am using
> >  ubuntu
> > 
> > 9.10 in case it is of any use and microhttpd version is 0.9.7 and was
> > compiled by me from source and installed in /usr/local .
> > 
> > Many thanks for your help in advance.
> > 
> > Kind Regards,
> > Neil
> > 
> > 
> > /media/sda3/home/nxd/Prog/C/microhttpd/tutorial>telnet localhost 8888
> > Trying 127.0.0.1...
> > Connected to localhost.
> > Escape character is '^]'.
> > GET /dontcare HTTP/1.1
> > Host: itsme
> > 
> > HTTP/1.1 200 OK
> > Content-Length: 1340341
> > Content-Type: image/png
> > Date: Thu, 17 Feb 2011 13:54:52 GMT
> > 
> > Connection closed by foreign host.
> > 
> > 
> > 
> > // ==================
> > static int
> > answer_to_connection (void *cls, struct MHD_Connection *connection,
> > 
> >                       const char *url, const char *method,
> >                       const char *version, const char *upload_data,
> >                       size_t *upload_data_size, void **con_cls)
> > 
> > {
> > 
> >   struct MHD_Response *response;
> >   int fd;
> >   int ret;
> >   struct stat sbuf;
> >   printf ("New %s request for %s using version %s\n", method, url,
> > 
> > version);
> > 
> >   if (0 != strcmp (method, "GET"))
> >   
> >     return MHD_NO;
> >   
> >   if ( (-1 == (fd = open (FILENAME, O_RDONLY))) ||
> >   
> >        (0 != fstat (fd, &sbuf)) )
> >     
> >     {
> >     
> >       /* error accessing file */
> >       if (fd != -1) close (fd);
> >       const char *errorstr =
> >       
> >         "<html><body>An internal server error has occured!\
> >         
> >                               </body></html>";
> >       
> >       response =
> >     
> >     MHD_create_response_from_buffer (strlen (errorstr),
> >     
> >                      (void *) errorstr,
> >                      MHD_RESPMEM_PERSISTENT);
> >       
> >       if (response)
> >       
> >         {
> >         
> >           ret =
> >           
> >             MHD_queue_response (connection,
> >             MHD_HTTP_INTERNAL_SERVER_ERROR,
> >             
> >                                 response);
> >           
> >           MHD_destroy_response (response);
> >           
> >           return MHD_YES;
> >         
> >         }
> >       
> >       else
> >       
> >         return MHD_NO;
> >     
> >     }
> >   
> >   response =
> >   
> >     MHD_create_response_from_fd_at_offset (sbuf.st_size, fd, 0);
> >   
> >   MHD_add_response_header (response, "Content-Type", MIMETYPE);
> >   ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
> >   if (ret == MHD_YES)
> >   
> >       printf ("queued response\n");
> >   
> >   else
> >   
> >       printf ("could not queue response\n");
> >   
> >   MHD_destroy_response (response);
> >   
> >   return ret;
> > 
> > }
> > 
> > // ===============



reply via email to

[Prev in Thread] Current Thread [Next in Thread]