⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 relay.c

📁 一个很棒的视频服务器
💻 C
📖 第 1 页 / 共 2 页
字号:
/*  camserv - An internet streaming picture application * *  Copyright (C) 1999-2002  Jon Travis (jtravis@p00p.org) * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. * *  This program 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 General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#include "camserv_config.h"#include <stdio.h>#include <stdlib.h>#include <string.h>#include <signal.h>#include "databuf.h"#include "socket.h"#include "sockset.h"#include "manager.h"#include "sock_field.h"#include "log.h"#define MODNAME "relay"#define BACKLOG  20extern int errno;#define CLIENT_T_UNK              0#define CLIENT_T_CAMSERV          1#define CLIENT_T_BROWSER          2#define CLIENT_T_PROXY            3#define CLIENT_T_SINGLE           4#define CAMSTATE_SEND_PROXY       1  /* Sending proxy notifier            */#define CAMSTATE_RECV_SIZE        2  /* Receiving the size of the picture */#define CAMSTATE_RECV_PICTURE     3  /* Receiving the actual picture      */#define BROWSERSTATE_SEND_PREAMBLE  0 /* Sending the preamble  */#define BROWSERSTATE_SEND_PICTURE   1 /* Sending the picture   */#define BROWSERSTATE_SEND_SEPERATOR 2 /* Sending the seperator */#define PROXYCLSTATE_SEND_PICSIZE   0 /* Sending the pic size */#define PROXYCLSTATE_SEND_PICTURE   1 /* Sending the actual picture */typedef struct client_data_st {  int clienttype;               /* one of CLIENT_T_* */  DataBuf *writebuf;  DataBuf *readbuf;           struct camdata_st {           /* Valid only if clientttype == CAMSERV  */    unsigned long int picsize;  /* Picture size in network order */    char *picbuf;               /* Actual picture data           */    int camstate;               /* State of camera               */  } camdata;  struct browser_st {              int browserstate;    void *management_data;    int last_pic_id;  } browserdata;  struct proxycl_st {    int proxystate;    unsigned long int picsize;  /* Picture size in network order */    void *management_data;    int last_pic_id;    char *pic_data;  } proxycldata;  char junkbuf[ 1024 ];} ClientData;typedef struct relay_data_st {  char camera_ip[ 1024 ];   /* IP of the remote camserv or relay   */  int camera_port;          /* Port of the remote camserv or relay */  Socket *camera_sock;      /* Connection of camera sock           */} RelayData;#define RANDOMSTRING "ThisRandomString"#define CONTENTTYPE  "image/jpeg"staticchar *get_preamble_text( size_t *len, int multi ){#define MPREAMBLE_STR "HTTP/1.0 200 OK\n"  \  "Content-type: multipart/x-mixed-replace;boundary=" RANDOMSTRING "\n" \  "Cache-Control: no-cache\n" \  "Cache-Control: private\n" \  "Pragma: no-cache\n\n" \  "--" RANDOMSTRING "\n" \  "Content-type: " CONTENTTYPE "\n\n"#define SPREAMBLE_STR "HTTP/1.0 200 OK\n"  \  "Content-type: " CONTENTTYPE "\n" \  "Cache-Control: no-cache\n" \  "Cache-Control: private\n" \  "Pragma: no-cache\n\n"     if( multi ) {    if( len != NULL ) *len = sizeof( MPREAMBLE_STR ) - 1;    return MPREAMBLE_STR;  } else {    if( len != NULL ) *len = sizeof( SPREAMBLE_STR ) - 1;    return SPREAMBLE_STR;  }}staticchar *get_seperator_text( size_t *len ){#define SEPERATOR_TEXT "\n--" RANDOMSTRING "\n"  \  "Content-type: " CONTENTTYPE "\n\n" /* XXX */  if( len != NULL ) *len = sizeof( SEPERATOR_TEXT ) - 1;  return SEPERATOR_TEXT;}/* * client_data_new:  Create and initialize a new clientinfo structure. *                  * Return values:    Returns NULL on failure, else a valid new clientdata *                   on success. */staticClientData *client_data_new(){  ClientData *res;  if( (res = malloc( sizeof( *res ))) == NULL )    return NULL;  if( (res->readbuf = databuf_new()) == NULL ){    free( res );    return NULL;  }  if( (res->writebuf = databuf_new()) == NULL ){    databuf_dest( res->readbuf );    free( res );    return NULL;  }  res->clienttype = CLIENT_T_UNK;  return res;}/* * client_data_dest:  Destroy a client data structure. * * Arguments:         cldata = Clientdata to destroy */staticvoid client_data_dest( ClientData *cldata ){  databuf_dest( cldata->readbuf );  databuf_dest( cldata->writebuf );  free( cldata );}/* * relay_connect_camserv:  Connect to a camera server.   * * Arguments:              rdata = Relay data with info of where to connect. * * Return values:          Returns -1 if the connection could not be made, else *                         0.  If successful, rdata->camera_sock will be *                         set to the new sock, else it will be set to NULL */staticint relay_connect_camserv( SockField_Data *sfdata, RelayData *rdata ){  ClientData *cldata;  rdata->camera_sock = socket_connect( rdata->camera_ip, rdata->camera_port );  if( rdata->camera_sock == NULL )    return -1;  if( (cldata = client_data_new()) == NULL ){    camserv_log( MODNAME, "Error mallocing clientdata");    socket_dest( rdata->camera_sock );    return -1;  }  cldata->clienttype = CLIENT_T_CAMSERV;    if( sock_field_manage_socket( sfdata, rdata->camera_sock, 				cldata ) == -1 )  {      camserv_log( MODNAME, "Error managing connect camera socket!");      client_data_dest( cldata );      socket_dest( rdata->camera_sock );      rdata->camera_sock = NULL;      return -1;  }  /* Send the proxy keyword */  databuf_buf_set( cldata->writebuf, "PROXY", sizeof( "PROXY" ));  cldata->camdata.picsize  = 0;  cldata->camdata.picbuf   = NULL;  cldata->camdata.camstate = CAMSTATE_SEND_PROXY;    return 0;}/* * relay_init:  Initialize the relay.  This involves making the connection *              to the camera server if possible.   * * Arguments:   sfdata = Sockfield data passed from the almighty. * * Return values:  Returns SOCKFIELD_OK on success, else SOCKFIELD_CLOSE. */staticint relay_init( SockField_Data *sfdata, void *sys_cldata ){  RelayData *rdata = sys_cldata;    if( relay_connect_camserv( sfdata, rdata ) == -1 )    camserv_log( MODNAME, "Couldn't connect to camserv: %s %d", 	     rdata->camera_ip, rdata->camera_port );  return SOCKFIELD_OK;}/* * relay_preclose:  Called by the field loop prior to closing a socket. *                  This routine should cleanup any of the clientdata passed *                  to the fieldloop management routines on socket init. * * Arguments:       sock   = Socket about to be closed. *                  cldata = Clientdata passed in for socket @ manage time. *                  sys_cldata = System clientdata, passed in as argument *                               to main field_loop */staticvoid relay_preclose( Socket *sock, void *cldata, void *sys_cldata ){  RelayData *rdata = sys_cldata;  ClientData *clientdata = cldata;  if( clientdata->clienttype == CLIENT_T_CAMSERV ) {    camserv_log( MODNAME, "Closing connection to camsera server!" );    /* Camera sock is now invalid */    rdata->camera_sock = NULL;  } else {    camserv_log( MODNAME, "Closing client from: \"%s\"", 		 socket_query_remote_name( sock ));  }  client_data_dest( cldata );}/* * read_camera:  This routine is called everytime the camserv socket has *               sent us some data to read.  It is in 2 states the entire *               time -- that of getting the size of the next picture, then *               actually receiving the picture.  After a successful *               receipt of a picture, it is then put into the management bins. *  * Arguments:    sfdata = SockField data *               sock   = Socket of the camserv object *               cldata = Clientdata of the camserv object. * * Return values:  Returns one of SOCKFIELD_* */staticint read_camera( SockField_Data *sfdata, Socket *sock, ClientData *cldata ){  if( cldata->camdata.camstate == CAMSTATE_RECV_SIZE ) {    /* We just got the size ... malloc the data and attempt to receive it too*/    cldata->camdata.camstate = CAMSTATE_RECV_PICTURE;    cldata->camdata.picbuf  = malloc( ntohl( cldata->camdata.picsize ));    if( cldata->camdata.picbuf == NULL ) {      camserv_log( MODNAME, "Couldn't malloc: %ld bytes for picture!",		   (long)ntohl( cldata->camdata.picsize ));      return SOCKFIELD_CLOSE;    }    databuf_buf_set( cldata->readbuf, cldata->camdata.picbuf,		     ntohl( cldata->camdata.picsize ) );  } else {    /* Else we just completed getting a whole picture */    cldata->camdata.camstate = CAMSTATE_RECV_SIZE;    databuf_buf_set( cldata->readbuf, &cldata->camdata.picsize,		     sizeof( cldata->camdata.picsize ) );    if( manager_new_picture( cldata->camdata.picbuf, 			     ntohl( cldata->camdata.picsize ), 100 ) == -1 )    {      camserv_log( MODNAME, "Unable to manage picture!");      free( cldata->camdata.picbuf );      return SOCKFIELD_CLOSE;    }    sock_field_unhold_write( sfdata );  }  return SOCKFIELD_OK;}/* * read_client:  Called when a client has sent data to the relay.  We just *               ignore everything the client sends us after initialization. */staticint read_client( SockField_Data *sfdata, Socket *sock, ClientData *cldata ){  /* Just refill the buffer .. client's that write anything, we are really     just disregarded */  databuf_buf_set( cldata->readbuf, &cldata->junkbuf[ 0 ],		   sizeof( cldata->junkbuf ));  return SOCKFIELD_OK;}/* * set_client_writebuf:  Set the writebuffer of the client for the first *                       time.  This is usually the 'init' state for the *                       client. * * Arguments:            cldata = client to set the writebuffer for. */staticvoid set_client_writebuf( ClientData *cldata  ){  size_t len;  char *cp;  if( cldata->clienttype == CLIENT_T_BROWSER ){    cp = get_preamble_text( &len, 1 );    cldata->browserdata.browserstate = BROWSERSTATE_SEND_PREAMBLE;  } else if( cldata->clienttype == CLIENT_T_SINGLE ) {    cp = get_preamble_text( &len, 0 );    cldata->browserdata.browserstate = BROWSERSTATE_SEND_PREAMBLE;  } else if( cldata->clienttype == CLIENT_T_PROXY ) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -