diff options
author | phintuka <phintuka> | 2007-01-01 08:50:53 +0000 |
---|---|---|
committer | phintuka <phintuka> | 2007-01-01 08:50:53 +0000 |
commit | efeb2cae0ee5352467581e8b436fc19428dd39c0 (patch) | |
tree | ed7a744601e8e088765cdf578b7f6712003fcf06 | |
parent | cfedfb7cc965cb206e5d28a51b4aa29f25c7dbd9 (diff) | |
download | xineliboutput-efeb2cae0ee5352467581e8b436fc19428dd39c0.tar.gz xineliboutput-efeb2cae0ee5352467581e8b436fc19428dd39c0.tar.bz2 |
All discovery stuff moved to own module
HTTP streaming module integrated
-rw-r--r-- | frontend_svr.c | 179 |
1 files changed, 98 insertions, 81 deletions
diff --git a/frontend_svr.c b/frontend_svr.c index beb3a4a2..4bcfa799 100644 --- a/frontend_svr.c +++ b/frontend_svr.c @@ -4,7 +4,7 @@ * See the main source file 'xineliboutput.c' for copyright information and * how to reach the author. * - * $Id: frontend_svr.c,v 1.32 2006-12-31 22:36:47 phintuka Exp $ + * $Id: frontend_svr.c,v 1.33 2007-01-01 08:50:53 phintuka Exp $ * */ @@ -38,12 +38,12 @@ #include "tools/future.h" #include "tools/backgroundwriter.h" #include "tools/udp_pes_scheduler.h" +#include "tools/http.h" +#include "tools/vdrdiscovery.h" #include "frontend_svr.h" #include "device.h" -class cConnState {}; - #define LOG_OSD_BANDWIDTH (128*1024) /* log messages if OSD bandwidth > 1 Mbit/s */ typedef struct { @@ -64,9 +64,9 @@ enum { ctDetecting = 0, ctControl, ctHttp, - ctHttpPlay, // client can't access file that is just played -> stream over http - ctRtsp, - ctRtspMux // multiplexed RTSP control + RTP/RTCP data/control + //ctHttpPlay, // client can't access file that is just played -> stream over http + ctRtsp, // TCP/RTSP + UDP/RTP + ctRtspMux // TCP: multiplexed RTSP control + RTP/RTCP data/control }; // (data) connection types @@ -131,6 +131,8 @@ cXinelibServer::~cXinelibServer() CLOSESOCKET(fd_listen); CLOSESOCKET(fd_discovery); + + cHttpStreamer::CloseAll(); for(i=0; i<MAXCLIENTS; i++) CloseConnection(i); @@ -625,8 +627,10 @@ bool cXinelibServer::HasClients(void) int cXinelibServer::PlayFileCtrl(const char *Cmd) { /* Check if there are any clients */ - if(!HasClients()) + if(!HasClients()) { + cHttpStreamer::CloseAll(); return -1; + } bool bPlayfile = false /*, bGet = false, bFlush = false*/; if((!strncmp(Cmd, "FLUSH", 5) /*&& (bFlush=true)*/) || @@ -678,7 +682,10 @@ int cXinelibServer::PlayFileCtrl(const char *Cmd) return future.Value(); } - return cXinelibThread::PlayFileCtrl(Cmd); + bool result = cXinelibThread::PlayFileCtrl(Cmd); + if(!m_FileName) + cHttpStreamer::CloseAll(); + return result; } @@ -694,6 +701,7 @@ bool cXinelibServer::Listen(int listen_port) CLOSESOCKET(fd_discovery); if(m_Scheduler) m_Scheduler->RemoveRtp(); + cHttpStreamer::CloseAll(); LOGMSG("Not listening for remote connections"); return false; } @@ -730,27 +738,11 @@ bool cXinelibServer::Listen(int listen_port) // set listen for discovery messages CLOSESOCKET(fd_discovery); if(xc.remote_usebcast) { - struct sockaddr_in sin; - if ((fd_discovery = socket(PF_INET, SOCK_DGRAM, 0/*IPPROTO_TCP*/)) < 0) { - LOGERR("socket() failed (UDP discovery)"); - } else { - int iBroadcast = 1, iReuse = 1; - setsockopt(fd_discovery, SOL_SOCKET, SO_BROADCAST, &iBroadcast, sizeof(int)); - setsockopt(fd_discovery, SOL_SOCKET, SO_REUSEADDR, &iReuse, sizeof(int)); - sin.sin_family = AF_INET; - sin.sin_port = htons(DISCOVERY_PORT); - sin.sin_addr.s_addr = htonl(INADDR_BROADCAST); //INADDR_ANY grabs rtp too ... - - if (bind(fd_discovery, (struct sockaddr *)&sin, sizeof(sin)) < 0) { - LOGERR("bind() failed (UDP discovery)"); - CLOSESOCKET(fd_discovery); - } else { - if(udp_discovery_broadcast(fd_discovery, m_Port) < 0) - CLOSESOCKET(fd_discovery); - else - LOGMSG("Listening for UDP broadcasts on port %d", m_Port); - } - } + fd_discovery = udp_discovery_init(); + if(udp_discovery_broadcast(fd_discovery, m_Port) < 0) + CLOSESOCKET(fd_discovery); + else + LOGMSG("Listening for UDP broadcasts on port %d", m_Port); } // set up multicast sockets @@ -1135,41 +1127,90 @@ void cXinelibServer::Handle_Control_GRAB(int cli, const char *arg) void cXinelibServer::Handle_Control_CONTROL(int cli, const char *arg) { - char str[256]; - sprintf(str, - "VDR-" VDRVERSION " " - "xineliboutput-" XINELIBOUTPUT_VERSION " " - "READY\r\nCLIENT-ID %d\r\n", cli); - write_cmd(fd_control[cli], str); + printf_cmd(fd_control[cli], + "VDR-" VDRVERSION " " + "xineliboutput-" XINELIBOUTPUT_VERSION " " + "READY\r\nCLIENT-ID %d\r\n", cli); m_ConnType[cli] = ctControl; } + void cXinelibServer::Handle_Control_HTTP(int cli, const char *arg) { - if(m_ConnType[cli] == ctDetecting) { - if(!strncmp(arg, "GET / HTTP/1.", 13)) { - LOGDBG("Accepted HTTP request: %s", arg); - - write_cmd(fd_control[cli], - "HTTP/1.1 200 OK\r\n" - "Content-type: video/mp2p\r\n" - "Connection: Close\r\n" - "\r\n" - ); - if(m_Writer[cli]) - delete m_Writer[cli]; - m_Writer[cli] = new cBackgroundWriter(fd_control[cli], KILOBYTE(1024), true); - m_ConnType[cli] = ctHttp; - } - else { - LOGMSG("Rejected HTTP request: %s", arg); + LOGDBG("HTTP(%d): %s", cli, arg); + + if(m_ConnType[cli] == ctDetecting || !m_State[cli]) { + LOGDBG("HTTP request: %s", arg); + + DELETENULL(m_Writer[cli]); + DELETENULL(m_State[cli]); + + m_State[cli] = new cConnState; + if( !m_State[cli]->SetCommand(arg) || + strcmp(m_State[cli]->Name(), "GET")) { + LOGMSG("invalid HTTP request: %s", arg); CloseConnection(cli); + return; } + + m_ConnType[cli] = ctHttp; return; } else if(m_ConnType[cli] == ctHttp) { LOGDBG("HTTP(%d): %s", cli, arg); + + if(*arg) { + m_State[cli]->AddHeader(arg); + return; + } + + LOGMSG("HTTP Request complete"); + + // primary device output + if(!strcmp(m_State[cli]->Uri(), "/")) { + LOGMSG("HTTP streaming primary device feed"); + write_cmd(fd_control[cli], HTTP_REPLY_200_PRIMARY); +#if 1 + // pack header (scr 0, mux rate 0x6270) + write(fd_control[cli], + "\x00\x00\x01\xba" "\x44\x00\x04\x00" + "\x04\x01\x01\x89" "\xc3\xf8", 14); +#endif +#if 1 + // system header + write(fd_control[cli], + "\x00\x00\x01\xbb" "\x00\x12" + "\x80\xc4\xe1" "\x00\xe1" "\x7f" + "\xb9\xe0\xe8" "\xb8\xc0\x20" + "\xbd\xe0\x3a" "\xbf\xe0\x02", 24); +#endif + m_Writer[cli] = new cBackgroundWriter(fd_control[cli], KILOBYTE(1024), true); + + DELETENULL(m_State[cli]); + return; + } + + // currently playing media file + else if(!strncmp(m_State[cli]->Uri(), "/PLAYFILE", 9)) { + if( m_FileName && m_bPlayingFile) { + LOGMSG("HTTP streaming media file"); + + new cHttpStreamer(fd_control[cli], m_FileName, m_State[cli]->Header("Range")->Value()); + // detach socket + fd_control[cli] = -1; + CloseConnection(cli); + return; + } + else + LOGDBG("No currently playing file"); + } + + // nothing else will be served ... + LOGMSG("Rejected HTTP request for \'%s\'", *m_State[cli]->Uri()); + write_cmd(fd_control[cli], HTTP_REPLY_401); + LOGDBG("HTTP Reply: HTTP/1.1 401 Unauthorized"); + CloseConnection(cli); } } @@ -1353,42 +1394,18 @@ void cXinelibServer::Handle_ClientConnected(int fd) void cXinelibServer::Handle_Discovery_Broadcast() { - char buf[1024], ip[64]; - struct sockaddr_in from; - socklen_t fromlen = sizeof(from); - if(!xc.remote_usebcast) { LOGDBG("BROADCASTS disabled in configuration"); CLOSESOCKET(fd_discovery); return; } - memset(&from, 0, sizeof(from)); - memset(buf, 0, sizeof(buf)); - errno = 0; - - int n = recvfrom(fd_discovery, buf, 1023, 0, - (struct sockaddr *)&from, &fromlen); - - if(n<=0) { - LOGDBG("fd_discovery recv() error"); - //CLOSESOCKET(fd_discovery); - return; - } - - char *id_string = DISCOVERY_1_0_HDR "Client:"; - - if(!strncmp(id_string, buf, strlen(id_string))) { - LOGMSG("Received valid discovery message from %s", - cxSocket::ip2txt(from.sin_addr.s_addr, from.sin_port, ip)); + char buf[DISCOVERY_MSG_MAXSIZE] = {0}; + struct sockaddr_in from; - if(udp_discovery_broadcast(fd_discovery, m_Port) < 0) - LOGERR("Discovery broadcast send error"); - } else { - LOGDBG("BROADCAST: (%d bytes from %s): %s", n, - cxSocket::ip2txt(from.sin_addr.s_addr, from.sin_port, ip), - buf); - } + if(udp_discovery_recv(fd_discovery, buf, 0, &from) > 0) + if(udp_discovery_is_valid_search(buf)) + udp_discovery_broadcast(fd_discovery, m_Port); } void cXinelibServer::Action(void) |