libmicrohttpd
[Top][All Lists]
Advanced

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

[libmicrohttpd] seeking file server


From: Ronny Falk
Subject: [libmicrohttpd] seeking file server
Date: Sun, 1 Aug 2010 23:40:38 -0400

Hi,
I am trying to implement a seeking file server with MHD. My prototype looks almost like the fileserver example (see below).

A few questions regarding this:
I am playing a file via mplayer http://localhost:8001/anything
mplayers HTTP GET commands look like this:
GET /s.avi HTTP/1.0
Host: macbook.local
User-Agent: MPlayer VERSION
Icy-MetaData: 1
Connection: close

GET /s.avi HTTP/1.0
Host: macbook.local
User-Agent: MPlayer VERSION
Icy-MetaData: 1
Range: bytes=14159872-
Connection: close

GET /s.avi HTTP/1.0
Host: macbook.local
User-Agent: MPlayer VERSION
Icy-MetaData: 1
Range: bytes=10240-
Connection: close

GET /s.avi HTTP/1.0
Host: macbook.local
User-Agent: MPlayer VERSION
Icy-MetaData: 1
Range: bytes=13590528-
Connection: close

So I thought, I need to reply to the range: bytes=n header.

Is there a good way of doing this, rather than this:
{
char br[64]; sprintf(br, "bytes %lu-", byteRange); fseek(file, byteRange, SEEK_SET);
response = MHD_create_response_from_callback (MHD_SIZE_UNKNOWN, 
  32 * 1024,     /* 32k page size */
  &file_reader,
  file,
  &free_callback);
MHD_add_response_header(response, MHD_HTTP_HEADER_CONTENT_TYPE, "video/x-msvideo");
//MHD_add_response_header(response, MHD_HTTP_HEADER_ETAG, "519240-d8e800-489aa5cc98940");
MHD_add_response_header(response, MHD_HTTP_HEADER_ACCEPT_RANGES, "bytes");
//MHD_add_response_header(response, MHD_HTTP_HEADER_CONTENT_LENGTH, "14215168");
MHD_add_response_header(response, MHD_HTTP_HEADER_CONTENT_RANGE, br);
...
}

I do not get the video to play, I get those connection headers though:
Connection:close
Icy-MetaData:1
User-Agent:MPlayer/SVN-r31524-4.0.1
Host:localhost:8001
result h:4, byteRange:0

Connection:close
Icy-MetaData:1
User-Agent:MPlayer/SVN-r31524-4.0.1
Host:localhost:8001
result h:4, byteRange:0

Connection:close
Range:bytes=14159872-
Icy-MetaData:1
User-Agent:MPlayer/SVN-r31524-4.0.1
Host:localhost:8001
result h:5, byteRange:14159872

Connection:close
Range:bytes=14159872-
Icy-MetaData:1
User-Agent:MPlayer/SVN-r31524-4.0.1
Host:localhost:8001
result h:5, byteRange:14159872

Please help, I am stuck on this one for a couple of days now. 

cheers
Ronny

/*
 This file is part of libmicrohttpd
 (C) 2007 Christian Grothoff (and other contributing authors)
 
 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public
 License as published by the Free Software Foundation; either
 version 2.1 of the License, or (at your option) any later version.
 
 This library is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 Lesser General Public License for more details.
 
 You should have received a copy of the GNU Lesser General Public
 License along with this library; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

/**
 * @file fileserver_example.c
 * @brief minimal example for how to use libmicrohttpd to serve files
 * @author Christian Grothoff
 */


#include <fcntl.h>
#include <stdio.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <microhttpd.h>
#include <unistd.h>

#define PAGE "<html><head><title>File not found</title></head><body>File not found</body></html>"

static int
file_reader (void *cls, uint64_t pos, char *buf, int max)
{
FILE *file = cls;
//(void)  fseek (file, pos, SEEK_SET);
return fread (buf, 1, max, file);
}

static void
free_callback (void *cls)
{
FILE *file = cls;
fclose (file);
}

static int
header_iterator (void *cls, 
enum MHD_ValueKind kind, 
const char *key, 
const char *value) {
printf("%s:%s\n", key, value);
if (!strcmp(key, MHD_HTTP_HEADER_RANGE)) { //parse Range //HACKHACK: assume "bytes=%i-" *(long*)cls = atoi(value + 6); }
return MHD_YES;
}

static int
ahc_echo (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 **ptr)
{
static int aptr;
struct MHD_Response *response;
int ret;
FILE *file;
char *fileURL = "/tmp/s.avi";
struct stat buf;
long byteRange;
if (0 != strcmp (method, MHD_HTTP_METHOD_GET))
return MHD_NO;              /* unexpected method */
int h = MHD_get_connection_values(connection,
 MHD_HEADER_KIND,
 &header_iterator,
 &byteRange);
// printf("result h:%i\n", h);
if (&aptr != *ptr)
    {
/* do never respond on first call */
*ptr = &aptr;
return MHD_YES;
    }
*ptr = NULL;                  /* reset when done */
if (0 == stat (fileURL, &buf))
file = fopen (fileURL, "rb");
else
file = NULL;
if (file == NULL)
    {
response = MHD_create_response_from_data (strlen (PAGE),
 (void *) PAGE,
 MHD_NO, MHD_NO);
ret = MHD_queue_response (connection, MHD_HTTP_NOT_FOUND, response);
MHD_destroy_response (response);
    }
else
    {
char br[64]; sprintf(br, "bytes %lu-", byteRange); fseek(file, byteRange, SEEK_SET);
response = MHD_create_response_from_callback (MHD_SIZE_UNKNOWN, 
 32 * 1024,     /* 32k page size */
 &file_reader,
 file,
 &free_callback);
MHD_add_response_header(response, MHD_HTTP_HEADER_CONTENT_TYPE, "video/x-msvideo");
//MHD_add_response_header(response, MHD_HTTP_HEADER_ETAG, "519240-d8e800-489aa5cc98940");
MHD_add_response_header(response, MHD_HTTP_HEADER_ACCEPT_RANGES, "bytes");
//MHD_add_response_header(response, MHD_HTTP_HEADER_CONTENT_LENGTH, "14215168");
MHD_add_response_header(response, MHD_HTTP_HEADER_CONTENT_RANGE, br);
if (response == NULL)
{
fclose (file);
return MHD_NO;
}
ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
MHD_destroy_response (response);
    }
return ret;
}

int
main (int argc, char *const *argv)
{
struct MHD_Daemon *d;
// if (argc != 2)
//    {
// printf ("%s PORT\n", argv[0]);
// return 1;
//    }
d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG,
 8001,
 NULL, NULL, &ahc_echo, PAGE, MHD_OPTION_END);
if (d == NULL)
return 1;
(void) getc (stdin);
MHD_stop_daemon (d);
return 0;
}

reply via email to

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