Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1490524
  • 博文数量: 129
  • 博客积分: 1449
  • 博客等级: 上尉
  • 技术积分: 3048
  • 用 户 组: 普通用户
  • 注册时间: 2012-07-24 18:36
文章分类

全部博文(129)

文章存档

2015年(3)

2014年(20)

2013年(65)

2012年(41)

分类: LINUX

2013-01-04 13:38:44

#define IO_BUFFER 256
#define BUFFER_SIZE 1024
#define MAX_FRAME_SIZE (256*1024)
#define TEN_K (10*1024)

/* the boundary is used for the M-JPEG stream, it separates the multipart stream of pictures */
#define BOUNDARY "boundarydonotcross"
#define STD_HEADER "Connection: close\r\n" \
                   "Server: MJPG-Streamer/0.2\r\n" \
                   "Cache-Control: no-store, no-cache, must-revalidate, pre-check=0, post-check=0, max-age=0\r\n" \
                   "Pragma: no-cache\r\n" \
                   "Expires: Mon, 3 Jan 2000 12:34:56 GMT\r\n"


点击(此处)折叠或打开

  1. void send_file(int id, int fd, char *parameter) {
  2.   char buffer[BUFFER_SIZE] = {0};
  3.   char *extension, *mimetype=NULL;
  4.   int i, lfd;
  5.   config conf = servers[id].conf;

  6.   /* in case no parameter was given */
  7.   if ( parameter == NULL || strlen(parameter) == 0 )
  8.     parameter = "index.html";

  9.   /* find file-extension */
  10.   if ( (extension = strstr(parameter, ".")) == NULL ) {
  11.     send_error(fd, 400, "No file extension found");
  12.     return;
  13.   }

  14.   /* determine mime-type */
  15.   for ( i=0; i < LENGTH_OF(mimetypes); i++ ) {
  16.     if ( strcmp(mimetypes[i].dot_extension, extension) == 0 ) {
  17.       mimetype = (char *)mimetypes[i].mimetype;
  18.       break;
  19.     }
  20.   }

  21.   /* in case of unknown mimetype or extension leave */
  22.   if ( mimetype == NULL ) {
  23.     send_error(fd, 404, "MIME-TYPE not known");
  24.     return;
  25.   }

  26.   /* now filename, mimetype and extension are known */
  27.   DBG("trying to serve file \"%s\", extension: \"%s\" mime: \"%s\"\n", parameter, extension, mimetype);

  28.   /* build the absolute path to the file */
  29.   strncat(buffer, conf.www_folder, sizeof(buffer)-1);
  30.   strncat(buffer, parameter, sizeof(buffer)-strlen(buffer)-1);

  31.   /* try to open that file */
  32.   if ( (lfd = open(buffer, O_RDONLY)) < 0 ) {
  33.     DBG("file %s not accessible\n", buffer);
  34.     send_error(fd, 404, "Could not open file");
  35.     return;
  36.   }
  37.   DBG("opened file: %s\n", buffer);

  38.   /* prepare HTTP header */
  39.   sprintf(buffer, "HTTP/1.0 200 OK\r\n" \
  40.                   "Content-type: %s\r\n" \
  41.                   STD_HEADER \
  42.                   "\r\n", mimetype);
  43.   i = strlen(buffer);

  44.   /* first transmit HTTP-header, afterwards transmit content of file */
  45.   do {
  46.     if ( write(fd, buffer, i) < 0 ) {
  47.       close(lfd);
  48.       return;
  49.     }
  50.   } while ( (i=read(lfd, buffer, sizeof(buffer))) > 0 );

  51.   /* close file, job done */
  52.   close(lfd);
  53. }


点击(此处)折叠或打开

  1. void send_snapshot(int fd) {
  2.   unsigned char *frame=NULL;
  3.   int frame_size=0;
  4.   char buffer[BUFFER_SIZE] = {0};

  5.   /* wait for a fresh frame */
  6.   pthread_cond_wait(&pglobal->db_update, &pglobal->db);

  7.   /* read buffer */
  8.   frame_size = pglobal->size;

  9.   /* allocate a buffer for this single frame */
  10.   if ( (frame = malloc(frame_size+1)) == NULL ) {
  11.     free(frame);
  12.     pthread_mutex_unlock( &pglobal->db );
  13.     send_error(fd, 500, "not enough memory");
  14.     return;
  15.   }

  16.   memcpy(frame, pglobal->buf, frame_size);
  17.   DBG("got frame (size: %d kB)\n", frame_size/1024);

  18.   pthread_mutex_unlock( &pglobal->db );

  19.   /* write the response */
  20.   sprintf(buffer, "HTTP/1.0 200 OK\r\n" \
  21.                   STD_HEADER \
  22.                   "Content-type: image/jpeg\r\n" \
  23.                   "\r\n");

  24.   /* send header and image now */
  25.   if( write(fd, buffer, strlen(buffer)) < 0 ) {
  26.     free(frame);
  27.     return;
  28.   }
  29.   write(fd, frame, frame_size);

  30.   free(frame);
  31. }

点击(此处)折叠或打开

  1. void send_stream(int fd) {
  2.   unsigned char *frame=NULL, *tmp=NULL;
  3.   int frame_size=0, max_frame_size=0;
  4.   char buffer[BUFFER_SIZE] = {0};

  5.   DBG("preparing header\n");

  6.   sprintf(buffer, "HTTP/1.0 200 OK\r\n" \
  7.                   STD_HEADER \
  8.                   "Content-Type: multipart/x-mixed-replace;boundary=" BOUNDARY "\r\n" \
  9.                   "\r\n" \
  10.                   "--" BOUNDARY "\r\n");

  11.   if ( write(fd, buffer, strlen(buffer)) < 0 ) {
  12.     free(frame);
  13.     return;
  14.   }

  15.   DBG("Headers send, sending stream now\n");

  16.   while ( !pglobal->stop ) {

  17.     /* wait for fresh frames */
  18.     pthread_cond_wait(&pglobal->db_update, &pglobal->db);

  19.     /* read buffer */
  20.     frame_size = pglobal->size;

  21.     /* check if framebuffer is large enough, increase it if necessary */
  22.     if ( frame_size > max_frame_size ) {
  23.       DBG("increasing buffer size to %d\n", frame_size);

  24.       max_frame_size = frame_size+TEN_K;
  25.       if ( (tmp = realloc(frame, max_frame_size)) == NULL ) {
  26.         free(frame);
  27.         pthread_mutex_unlock( &pglobal->db );
  28.         send_error(fd, 500, "not enough memory");
  29.         return;
  30.       }

  31.       frame = tmp;
  32.     }

  33.     memcpy(frame, pglobal->buf, frame_size);
  34.     DBG("got frame (size: %d kB)\n", frame_size/1024);

  35.     pthread_mutex_unlock( &pglobal->db );

  36.     /*
  37.      * print the individual mimetype and the length
  38.      * sending the content-length fixes random stream disruption observed with firefox
  39.      */
  40.     sprintf(buffer, "Content-Type: image/jpeg\r\n" \
  41.                     "Content-Length: %d\r\n" \
  42.                     "\r\n", frame_size);
  43.     DBG("sending intemdiate header\n");
  44.     if ( write(fd, buffer, strlen(buffer)) < 0 ) break;

  45.     DBG("sending frame\n");
  46.     if( write(fd, frame, frame_size) < 0 ) break;

  47.     DBG("sending boundary\n");
  48.     sprintf(buffer, "\r\n--" BOUNDARY "\r\n");
  49.     if ( write(fd, buffer, strlen(buffer)) < 0 ) break;
  50.   }

  51.   free(frame);
  52. }


点击(此处)折叠或打开

  1. void send_error(int fd, int which, char *message) {
  2.   char buffer[BUFFER_SIZE] = {0};

  3.   if ( which == 401 ) {
  4.     sprintf(buffer, "HTTP/1.0 401 Unauthorized\r\n" \
  5.                     "Content-type: text/plain\r\n" \
  6.                     STD_HEADER \
  7.                     "WWW-Authenticate: Basic realm=\"MJPG-Streamer\"\r\n" \
  8.                     "\r\n" \
  9.                     "401: Not Authenticated!\r\n" \
  10.                     "%s", message);
  11.   } else if ( which == 404 ) {
  12.     sprintf(buffer, "HTTP/1.0 404 Not Found\r\n" \
  13.                     "Content-type: text/plain\r\n" \
  14.                     STD_HEADER \
  15.                     "\r\n" \
  16.                     "404: Not Found!\r\n" \
  17.                     "%s", message);
  18.   } else if ( which == 500 ) {
  19.     sprintf(buffer, "HTTP/1.0 500 Internal Server Error\r\n" \
  20.                     "Content-type: text/plain\r\n" \
  21.                     STD_HEADER \
  22.                     "\r\n" \
  23.                     "500: Internal Server Error!\r\n" \
  24.                     "%s", message);
  25.   } else if ( which == 400 ) {
  26.     sprintf(buffer, "HTTP/1.0 400 Bad Request\r\n" \
  27.                     "Content-type: text/plain\r\n" \
  28.                     STD_HEADER \
  29.                     "\r\n" \
  30.                     "400: Not Found!\r\n" \
  31.                     "%s", message);
  32.   } else {
  33.     sprintf(buffer, "HTTP/1.0 501 Not Implemented\r\n" \
  34.                     "Content-type: text/plain\r\n" \
  35.                     STD_HEADER \
  36.                     "\r\n" \
  37.                     "501: Not Implemented!\r\n" \
  38.                     "%s", message);
  39.   }

  40.   write(fd, buffer, strlen(buffer));
  41. }


阅读(1760) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~