From 19f89fc2a12ef4218286fa8c5233cfcdb382e538 Mon Sep 17 00:00:00 2001 From: MuMuDVB Date: Fri, 15 Jan 2010 22:27:48 +0100 Subject: [PATCH 01/28] RTSP First step : we split unicast common and the HTTP --- src/Makefile.am | 4 +-- src/autoconf.c | 1 + src/mumudvb.c | 3 +- src/unicast.h | 44 ++++++++++++++++++++++++++ src/unicast_clients.c | 1 + src/unicast_common.c | 73 +++++++++++++++++++++++++++++++++++++++++++ src/unicast_http.c | 60 ++++++++++++++++++----------------- src/unicast_http.h | 12 ++----- src/unicast_queue.c | 1 + 9 files changed, 157 insertions(+), 42 deletions(-) create mode 100644 src/unicast.h create mode 100644 src/unicast_common.c diff --git a/src/Makefile.am b/src/Makefile.am index 1c9bab39..688125cf 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -4,10 +4,10 @@ AM_LDFLAGS = bin_PROGRAMS = mumudvb mumudvb_SOURCES = autoconf.c crc32.c dvb.h log.c log.h multicast.c mumudvb.h network.h rewrite.h \ - rtp.h sap.h ts.h tune.h unicast_http.h autoconf.h dvb.c errors.h \ + rtp.h sap.h ts.h tune.h unicast_http.h autoconf.h dvb.c errors.h unicast_common.h \ mumudvb.c mumudvb_common.c network.c pat_rewrite.c rewrite.c sdt_rewrite.c \ rtp.c sap.c ts.c tune.c unicast_http.c unicast_queue.c autoconf_sdt.c autoconf_atsc.c \ - autoconf_pmt.c autoconf_nit.c unicast_clients.c + autoconf_pmt.c autoconf_nit.c unicast_clients.c unicast_common.c if BUILD_CAMSUPPORT mumudvb_SOURCES += $(SOURCES_camsupport) diff --git a/src/autoconf.c b/src/autoconf.c index 8b4a281d..2ce4cc57 100644 --- a/src/autoconf.c +++ b/src/autoconf.c @@ -74,6 +74,7 @@ #include "autoconf.h" #include "rtp.h" #include "log.h" +#include "unicast.h" extern int Interrupted; extern int server_id; diff --git a/src/mumudvb.c b/src/mumudvb.c index 23e1375c..13299f30 100644 --- a/src/mumudvb.c +++ b/src/mumudvb.c @@ -122,6 +122,7 @@ #include "sap.h" #include "rewrite.h" #include "unicast_http.h" +#include "unicast.h" #include "rtp.h" #include "log.h" #ifdef ENABLE_TRANSCODING @@ -1207,7 +1208,7 @@ int if(unicast_vars.unicast) { log_message(MSG_INFO,"Unicast : We open the Master http socket for address %s:%d\n",unicast_vars.ipOut, unicast_vars.portOut); - unicast_create_listening_socket(UNICAST_MASTER, -1, unicast_vars.ipOut, unicast_vars.portOut, &unicast_vars.sIn, &unicast_vars.socketIn, &fds, &unicast_vars); + unicast_create_listening_socket(UNICAST_MASTER_HTTP, -1, unicast_vars.ipOut, unicast_vars.portOut, &unicast_vars.sIn, &unicast_vars.socketIn, &fds, &unicast_vars); /** open the unicast listening connections fo the channels */ for (curr_channel = 0; curr_channel < chan_and_pids.number_of_channels; curr_channel++) if(chan_and_pids.channels[curr_channel].unicast_port) diff --git a/src/unicast.h b/src/unicast.h new file mode 100644 index 00000000..a82376aa --- /dev/null +++ b/src/unicast.h @@ -0,0 +1,44 @@ +/* + * mumudvb - UDP-ize a DVB transport stream. + * + * (C) 2009 Brice DUBOST + * + * The latest version can be found at http://mumudvb.braice.net + * + * Copyright notice: + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/**@file + * @brief HTML unicast headers + */ + +#ifndef _UNICAST_H +#define _UNICAST_H + +#include "mumudvb.h" +#include "unicast_queue.h" + +/** @brief The different fd/socket types */ +enum + { + UNICAST_MASTER_HTTP=1, + UNICAST_LISTEN_CHANNEL, + UNICAST_CLIENT, + }; + + +#endif diff --git a/src/unicast_clients.c b/src/unicast_clients.c index ea77c799..3fbdafbd 100644 --- a/src/unicast_clients.c +++ b/src/unicast_clients.c @@ -51,6 +51,7 @@ #include "mumudvb.h" #include "errors.h" #include "log.h" +#include "unicast.h" diff --git a/src/unicast_common.c b/src/unicast_common.c new file mode 100644 index 00000000..b5653279 --- /dev/null +++ b/src/unicast_common.c @@ -0,0 +1,73 @@ +/* +* MuMuDVB - Stream a DVB transport stream. +* +* (C) 2009-2010 Brice DUBOST +* +* The latest version can be found at http://mumudvb.braice.net +* +* Copyright notice: +* +* 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/** @file +* @brief File for HTTP unicast common fonctions +* @author Brice DUBOST +* @date 2009-2010 +*/ + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "unicast_http.h" +#include "unicast_queue.h" +#include "mumudvb.h" +#include "errors.h" +#include "log.h" +#include "unicast.h" + + + + + + + + + + + + + + + + diff --git a/src/unicast_http.c b/src/unicast_http.c index 51b6df20..515bddd9 100644 --- a/src/unicast_http.c +++ b/src/unicast_http.c @@ -62,6 +62,7 @@ Todo list #include "mumudvb.h" #include "errors.h" #include "log.h" +#include "unicast.h" extern int Interrupted; @@ -91,7 +92,7 @@ int unicast_handle_message(unicast_parameters_t *unicast_vars, unicast_client_t #define REPLY_BODY 1 #define REPLY_SIZE_STEP 256 -struct unicast_reply { +typedef struct unicast_reply_t { char* buffer_header; char* buffer_body; int length_header; @@ -99,11 +100,12 @@ struct unicast_reply { int used_header; int used_body; int type; -}; -static struct unicast_reply* unicast_reply_init(); -static int unicast_reply_free(struct unicast_reply *reply); -static int unicast_reply_write(struct unicast_reply *reply, const char* msg, ...); -static int unicast_reply_send(struct unicast_reply *reply, int socket, int code, const char* content_type); +}unicast_reply_t; + +static unicast_reply_t* unicast_reply_init(); +static int unicast_reply_free(unicast_reply_t *reply); +static int unicast_reply_write(unicast_reply_t *reply, const char* msg, ...); +static int unicast_reply_send(unicast_reply_t *reply, int socket, int code, const char* content_type); /**@todo : deal with the RTP over http case ie implement RTSP*/ @@ -271,7 +273,7 @@ int unicast_handle_fd_event(unicast_parameters_t *unicast_vars, fds_t *fds, mumu } if((fds->pfds[actual_fd].revents&POLLIN)||(fds->pfds[actual_fd].revents&POLLPRI)) { - if((unicast_vars->fd_info[actual_fd].type==UNICAST_MASTER)|| + if((unicast_vars->fd_info[actual_fd].type==UNICAST_MASTER_HTTP)|| (unicast_vars->fd_info[actual_fd].type==UNICAST_LISTEN_CHANNEL)) { //Event on the master connection or listenin channel @@ -533,7 +535,7 @@ int unicast_handle_message(unicast_parameters_t *unicast_vars, unicast_client_t requested_channel=0; pos=0; err404=0; - struct unicast_reply* reply=NULL; + unicast_reply_t* reply=NULL; log_message(MSG_DEBUG,"Unicast : End of HTTP request, we parse it\n"); @@ -765,9 +767,9 @@ int unicast_handle_message(unicast_parameters_t *unicast_vars, unicast_client_t /** @brief Init reply structure * */ -struct unicast_reply* unicast_reply_init() +unicast_reply_t* unicast_reply_init() { - struct unicast_reply* reply = malloc(sizeof (struct unicast_reply)); + unicast_reply_t* reply = malloc(sizeof (unicast_reply_t)); if (NULL == reply) { log_message(MSG_ERROR,"Problem with malloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); @@ -799,7 +801,7 @@ struct unicast_reply* unicast_reply_init() /** @brief Release the reply structure * */ -int unicast_reply_free(struct unicast_reply *reply) +int unicast_reply_free(unicast_reply_t *reply) { if (NULL == reply) return 1; @@ -817,7 +819,7 @@ int unicast_reply_free(struct unicast_reply *reply) * * auto-realloc buffer if needed */ -int unicast_reply_write(struct unicast_reply *reply, const char* msg, ...) +int unicast_reply_write(unicast_reply_t *reply, const char* msg, ...) { char **buffer; char *temp_buffer; @@ -869,7 +871,7 @@ int unicast_reply_write(struct unicast_reply *reply, const char* msg, ...) /** @brief Dump the filled buffer on the socket adding HTTP header informations */ -int unicast_reply_send(struct unicast_reply *reply, int socket, int code, const char* content_type) +int unicast_reply_send(unicast_reply_t *reply, int socket, int code, const char* content_type) { //we add the header information reply->type = REPLY_HEADER; @@ -917,7 +919,7 @@ int unicast_send_streamed_channels_list (int number_of_channels, mumudvb_channel_t *channels, int Socket, char *host) { - struct unicast_reply* reply = unicast_reply_init(); + unicast_reply_t* reply = unicast_reply_init(); if (NULL == reply) { log_message(MSG_INFO,"Unicast : Error when creating the HTTP reply\n"); return -1; @@ -935,19 +937,19 @@ unicast_send_streamed_channels_list (int number_of_channels, mumudvb_channel_t * host,curr_channel+1, host,curr_channel+1, channels[curr_channel].ipOut,channels[curr_channel].portOut); - else - unicast_reply_write(reply, "Channel number %d : \"%s\"
Multicast ip : %s:%d

\r\n",curr_channel,channels[curr_channel].name,channels[curr_channel].ipOut,channels[curr_channel].portOut); + else + unicast_reply_write(reply, "Channel number %d : \"%s\"
Multicast ip : %s:%d

\r\n",curr_channel,channels[curr_channel].name,channels[curr_channel].ipOut,channels[curr_channel].portOut); } - unicast_reply_write(reply, HTTP_CHANNELS_REPLY_END); + unicast_reply_write(reply, HTTP_CHANNELS_REPLY_END); - unicast_reply_send(reply, Socket, 200, "text/html"); + unicast_reply_send(reply, Socket, 200, "text/html"); - if (0 != unicast_reply_free(reply)) { - log_message(MSG_INFO,"Unicast : Error when releasing the HTTP reply after sendinf it\n"); - return -1; - } + if (0 != unicast_reply_free(reply)) { + log_message(MSG_INFO,"Unicast : Error when releasing the HTTP reply after sendinf it\n"); + return -1; + } - return 0; + return 0; } @@ -963,7 +965,7 @@ unicast_send_play_list_unicast (int number_of_channels, mumudvb_channel_t *chann { int curr_channel; - struct unicast_reply* reply = unicast_reply_init(); + unicast_reply_t* reply = unicast_reply_init(); if (NULL == reply) { log_message(MSG_INFO,"Unicast : Error when creating the HTTP reply\n"); return -1; @@ -998,7 +1000,7 @@ unicast_send_play_list_unicast (int number_of_channels, mumudvb_channel_t *chann } } - unicast_reply_send(reply, Socket, 200, "audio/x-mpegurl"); + unicast_reply_send(reply, Socket, 200, "audio/x-mpegurl"); if (0 != unicast_reply_free(reply)) { log_message(MSG_INFO,"Unicast : Error when releasing the HTTP reply after sendinf it\n"); @@ -1022,7 +1024,7 @@ unicast_send_play_list_multicast (int number_of_channels, mumudvb_channel_t *cha char vlcchar[2]; extern multicast_parameters_t multicast_vars; - struct unicast_reply* reply = unicast_reply_init(); + unicast_reply_t* reply = unicast_reply_init(); if (NULL == reply) { log_message(MSG_INFO,"Unicast : Error when creating the HTTP reply\n"); return -1; @@ -1077,7 +1079,7 @@ int unicast_send_streamed_channels_list_js (int number_of_channels, mumudvb_chan unicast_client_t *unicast_client=NULL; int clients=0; - struct unicast_reply* reply = unicast_reply_init(); + unicast_reply_t* reply = unicast_reply_init(); if (NULL == reply) { log_message(MSG_INFO,"Unicast : Error when creating the HTTP reply\n"); return -1; @@ -1138,7 +1140,7 @@ int unicast_send_signal_power_js (int Socket, fds_t *fds) { int strength, ber, snr; - struct unicast_reply* reply = unicast_reply_init(); + unicast_reply_t* reply = unicast_reply_init(); if (NULL == reply) { log_message(MSG_INFO,"Unicast : Error when creating the HTTP reply\n"); @@ -1174,7 +1176,7 @@ unicast_send_channel_traffic_js (int number_of_channels, mumudvb_channel_t *chan int curr_channel; extern long real_start_time; - struct unicast_reply* reply = unicast_reply_init(); + unicast_reply_t* reply = unicast_reply_init(); if (NULL == reply) { log_message(MSG_INFO,"Unicast : Error when creating the HTTP reply\n"); return -1; diff --git a/src/unicast_http.h b/src/unicast_http.h index 2ec51b7c..e743665d 100644 --- a/src/unicast_http.h +++ b/src/unicast_http.h @@ -26,20 +26,12 @@ * @brief HTML unicast headers */ -#ifndef _UNICAST_H -#define _UNICAST_H +#ifndef _UNICAST_HTTP_H +#define _UNICAST_HTTP_H #include "mumudvb.h" #include "unicast_queue.h" -/** @brief The different fd/socket types */ -enum - { - UNICAST_MASTER=1, - UNICAST_LISTEN_CHANNEL, - UNICAST_CLIENT, - }; - #define RECV_BUFFER_MULTIPLE 100 diff --git a/src/unicast_queue.c b/src/unicast_queue.c index 7dda9c30..2673d414 100644 --- a/src/unicast_queue.c +++ b/src/unicast_queue.c @@ -38,6 +38,7 @@ #include "mumudvb.h" #include "errors.h" #include "log.h" +#include "unicast.h" int unicast_queue_remove_data(unicast_queue_header_t *header); From 76b2e83382faec322159ac7abc5bc44c908c495c Mon Sep 17 00:00:00 2001 From: MuMuDVB Date: Fri, 15 Jan 2010 23:26:09 +0100 Subject: [PATCH 02/28] Unicast: Splitting ... for RTSP --- src/Makefile.am | 2 +- src/mumudvb.c | 1 - src/unicast.h | 107 ++++++++++++ src/unicast_clients.c | 5 +- src/unicast_common.c | 348 +++++++++++++++++++++++++++++++++++++ src/unicast_common.h | 57 ++++++ src/unicast_http.c | 395 ++---------------------------------------- src/unicast_http.h | 95 +--------- src/unicast_queue.c | 1 + src/unicast_rtsp.h | 41 +++++ 10 files changed, 575 insertions(+), 477 deletions(-) create mode 100644 src/unicast_common.h create mode 100644 src/unicast_rtsp.h diff --git a/src/Makefile.am b/src/Makefile.am index 688125cf..a1978819 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -7,7 +7,7 @@ mumudvb_SOURCES = autoconf.c crc32.c dvb.h log.c log.h multicast.c mumudvb.h net rtp.h sap.h ts.h tune.h unicast_http.h autoconf.h dvb.c errors.h unicast_common.h \ mumudvb.c mumudvb_common.c network.c pat_rewrite.c rewrite.c sdt_rewrite.c \ rtp.c sap.c ts.c tune.c unicast_http.c unicast_queue.c autoconf_sdt.c autoconf_atsc.c \ - autoconf_pmt.c autoconf_nit.c unicast_clients.c unicast_common.c + autoconf_pmt.c autoconf_nit.c unicast_clients.c unicast_common.c unicast_common.h if BUILD_CAMSUPPORT mumudvb_SOURCES += $(SOURCES_camsupport) diff --git a/src/mumudvb.c b/src/mumudvb.c index 13299f30..9e76150f 100644 --- a/src/mumudvb.c +++ b/src/mumudvb.c @@ -121,7 +121,6 @@ #include "autoconf.h" #include "sap.h" #include "rewrite.h" -#include "unicast_http.h" #include "unicast.h" #include "rtp.h" #include "log.h" diff --git a/src/unicast.h b/src/unicast.h index a82376aa..1b2c1ee5 100644 --- a/src/unicast.h +++ b/src/unicast.h @@ -32,6 +32,8 @@ #include "mumudvb.h" #include "unicast_queue.h" +#define RTSP_PORT 554 + /** @brief The different fd/socket types */ enum { @@ -40,5 +42,110 @@ enum UNICAST_CLIENT, }; +/** @brief The different client types */ +enum + { + CLIENT_HTTP, + CLIENT_RTSP, + }; + + +#define RECV_BUFFER_MULTIPLE 100 +/**@brief the timeout for disconnecting a client with only consecutive errors*/ +#define UNICAST_CONSECUTIVE_ERROR_TIMEOUT 5 + + + +/** @brief A client connected to the unicast connection. + * + *There is two chained list of client : a global one wich contain all the clients. Another one in each channel wich contain the associated clients. + */ +typedef struct unicast_client_t{ + /** The type of client */ + int client_type; + /**HTTP/Control socket*/ + struct sockaddr_in SocketAddr; + /**HTTP/Contol socket*/ + int Socket; + /**Reception buffer*/ + char *buffer; + /**Size of the buffer*/ + int buffersize; + /**Position in the buffer*/ + int bufferpos; + /**Is there consecutive errors ?*/ + int consecutive_errors; + /**When the first consecutive error happeard*/ + long first_error_time; + /**Channel : -1 if not associated yet*/ + int channel; + /**Future channel : we will set the channel when we will receive the get*/ + int askedChannel; + /**Next client*/ + struct unicast_client_t *next; + /**Previous client*/ + struct unicast_client_t *prev; + /**Next client in the channel*/ + struct unicast_client_t *chan_next; + /**Previous client in the channel*/ + struct unicast_client_t *chan_prev; + /** The packets in queue*/ + unicast_queue_header_t queue; + /** The latest write error for this client*/ + int last_write_error; +}unicast_client_t; + + +/** @brief The information on the unicast file descriptors/sockets + * There is three kind of descriptors : + * The master connection : this connection will interpret the HTTP path asked, to give the channel, the channel list or debugging information + * Client connections : This is the connections for connected clients + * Channel listening connections : When a client connect to one of these sockets, the associated channel will be given directly without interpreting the PATH + * + * The numbering of this socket information is the same as the file descriptors numbering + */ +typedef struct unicast_fd_info_t{ + /**The fd/socket type*/ + int type; + /** The channel if it's a channel socket*/ + int channel; + /** The client if it's a client socket*/ + unicast_client_t *client; +}unicast_fd_info_t; + + +/** @brief The parameters for unicast +*/ +typedef struct unicast_parameters_t{ + /** Do we activate unicast ?*/ + int unicast; + /**The "HTTP" ip address*/ + char ipOut[20]; + /** The "HTTP" port*/ + int portOut; + /** The "HTTP" port string version before parsing*/ + char *portOut_str; + /** The HTTP input socket*/ + struct sockaddr_in sIn; + /** The HTTP input socket*/ + int socketIn; + /** The clients, contains all the clients, associated to a channel or not*/ + unicast_client_t *clients; + /** The number of connected clients*/ + int client_number; + /** The maximum number of simultaneous clients allowed*/ + int max_clients; + /** The timeout before disconnecting a client wich does only errors*/ + int consecutive_errors_timeout; + /** The information on the file descriptors : ie the type of FD, the client associated if it's a client fd, the channel if it's a channel fd */ + unicast_fd_info_t *fd_info; + /** The maximim size of the queue */ + int queue_max_size; +}unicast_parameters_t; + + +int read_unicast_configuration(unicast_parameters_t *unicast_vars, mumudvb_channel_t *current_channel, int ip_ok, char *substring); + +int unicast_create_listening_socket(int socket_type, int socket_channel, char *ipOut, int port, struct sockaddr_in *sIn, int *socketIn, fds_t *fds, unicast_parameters_t *unicast_vars); #endif diff --git a/src/unicast_clients.c b/src/unicast_clients.c index 3fbdafbd..bde4fd30 100644 --- a/src/unicast_clients.c +++ b/src/unicast_clients.c @@ -52,7 +52,7 @@ #include "errors.h" #include "log.h" #include "unicast.h" - +#include "unicast_common.h" /** @brief Add a client to the chained list of clients @@ -62,7 +62,7 @@ * @param SocketAddr The socket address * @param Socket The socket number */ -unicast_client_t *unicast_add_client(unicast_parameters_t *unicast_vars, struct sockaddr_in SocketAddr, int Socket) +unicast_client_t *unicast_add_client(unicast_parameters_t *unicast_vars, struct sockaddr_in SocketAddr, int Socket, int client_type) { unicast_client_t *client; @@ -110,6 +110,7 @@ unicast_client_t *unicast_add_client(unicast_parameters_t *unicast_vars, struct client->queue.packets_in_queue=0; client->queue.first=NULL; client->queue.last=NULL; + client->client_type=client_type; unicast_vars->client_number++; diff --git a/src/unicast_common.c b/src/unicast_common.c index b5653279..6b78edf4 100644 --- a/src/unicast_common.c +++ b/src/unicast_common.c @@ -55,10 +55,358 @@ #include "errors.h" #include "log.h" #include "unicast.h" +#include "unicast_common.h" +/** @brief Read a line of the configuration file to check if there is a unicast parameter +* +* @param unicast_vars the unicast parameters +* @param substring The currrent line +*/ +int read_unicast_configuration(unicast_parameters_t *unicast_vars, mumudvb_channel_t *current_channel, int ip_ok, char *substring) +{ + + char delimiteurs[] = CONFIG_FILE_SEPARATOR; + + if (!strcmp (substring, "ip_http")) + { + substring = strtok (NULL, delimiteurs); + if(strlen(substring)>19) + { + log_message( MSG_ERROR, + "The Ip address %s is too long.\n", substring); + exit(ERROR_CONF); + } + sscanf (substring, "%s\n", unicast_vars->ipOut); + if(unicast_vars->ipOut) + { + if(unicast_vars->unicast==0) + { + log_message( MSG_WARN,"You should use the option \"unicast\" to activate unicast instead of ip_http\n"); + unicast_vars->unicast=1; + log_message( MSG_WARN,"You have enabled the support for HTTP Unicast. This feature is quite youg, please report any bug/comment\n"); + } + } + } + else if (!strcmp (substring, "unicast")) + { + substring = strtok (NULL, delimiteurs); + unicast_vars->unicast = atoi (substring); + if(unicast_vars->unicast) + { + log_message( MSG_WARN, + "You have enabled the support for HTTP Unicast. This feature is quite youg, please report any bug/comment\n"); + } + } + else if (!strcmp (substring, "unicast_consecutive_errors_timeout")) + { + substring = strtok (NULL, delimiteurs); + unicast_vars->consecutive_errors_timeout = atoi (substring); + if(unicast_vars->consecutive_errors_timeout<=0) + log_message( MSG_WARN, + "Warning : You have desactivated the unicast timeout for disconnecting clients, this can lead to an accumulation of zombie clients, this is unadvised, prefer a long timeout\n"); + } + else if (!strcmp (substring, "unicast_max_clients")) + { + substring = strtok (NULL, delimiteurs); + unicast_vars->max_clients = atoi (substring); + } + else if (!strcmp (substring, "unicast_queue_size")) + { + substring = strtok (NULL, delimiteurs); + unicast_vars->queue_max_size = atoi (substring); + } + else if (!strcmp (substring, "port_http")) + { + substring = strtok (NULL, ""); + if((strchr(substring,'*')!=NULL)||(strchr(substring,'+')!=NULL)||(strchr(substring,'%')!=NULL)) + { + unicast_vars->portOut_str=malloc(sizeof(char)*(strlen(substring)+1)); + strcpy(unicast_vars->portOut_str,substring); + } + else + unicast_vars->portOut = atoi (substring); + } + else if (!strcmp (substring, "unicast_port")) + { + if ( ip_ok == 0) + { + log_message( MSG_ERROR, + "unicast_port : You have to start a channel first (using ip= or channel_next)\n"); + exit(ERROR_CONF); + } + substring = strtok (NULL, delimiteurs); + current_channel->unicast_port = atoi (substring); + } + else + return 0; //Nothing concerning tuning, we return 0 to explore the other possibilities + + return 1;//We found something for tuning, we tell main to go for the next line + +} + + + +/** @brief Create a listening socket and add it to the list of polling file descriptors if success +* +* +* +*/ +int unicast_create_listening_socket(int socket_type, int socket_channel, char *ipOut, int port, struct sockaddr_in *sIn, int *socketIn, fds_t *fds, unicast_parameters_t *unicast_vars) +{ + *socketIn= makeTCPclientsocket(ipOut, port, sIn); + //We add them to the poll descriptors + if(*socketIn>0) + { + fds->pfdsnum++; + log_message(MSG_DEBUG, "unicast : fds->pfdsnum : %d\n", fds->pfdsnum); + fds->pfds=realloc(fds->pfds,(fds->pfdsnum+1)*sizeof(struct pollfd)); + if (fds->pfds==NULL) + { + log_message(MSG_ERROR,"Problem with realloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); + return -1; + } + fds->pfds[fds->pfdsnum-1].fd = *socketIn; + fds->pfds[fds->pfdsnum-1].events = POLLIN | POLLPRI; + fds->pfds[fds->pfdsnum-1].revents = 0; + fds->pfds[fds->pfdsnum].fd = 0; + fds->pfds[fds->pfdsnum].events = POLLIN | POLLPRI; + fds->pfds[fds->pfdsnum].revents = 0; + //Information about the descriptor + unicast_vars->fd_info=realloc(unicast_vars->fd_info,(fds->pfdsnum)*sizeof(unicast_fd_info_t)); + if (unicast_vars->fd_info==NULL) + { + log_message(MSG_ERROR,"Problem with realloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); + return -1; + } + //Master connection + unicast_vars->fd_info[fds->pfdsnum-1].type=socket_type; + unicast_vars->fd_info[fds->pfdsnum-1].channel=socket_channel; + unicast_vars->fd_info[fds->pfdsnum-1].client=NULL; + } + else + { + log_message( MSG_WARN, "Problem creating the socket %s:%d : %s\n",ipOut,port,strerror(errno) ); + return -1; + } + + return 0; + +} + +/** @brief Close an unicast connection and delete the client +* +* @param unicast_vars the unicast parameters +* @param fds The polling file descriptors +* @param Socket The socket of the client we want to disconnect +* @param channels The channel list +*/ +void unicast_close_connection(unicast_parameters_t *unicast_vars, fds_t *fds, int Socket, mumudvb_channel_t *channels) +{ + + int actual_fd; + actual_fd=0; + //We find the FD correspondig to this client + while((actual_fdpfdsnum) && (fds->pfds[actual_fd].fd!=Socket)) + actual_fd++; + + if(actual_fd==fds->pfdsnum) + { + log_message(MSG_ERROR,"Unicast : close connection : we did't find the file descriptor this should never happend, please contact\n"); + actual_fd=0; + //We find the FD correspondig to this client + while(actual_fdpfdsnum) + { + log_message(MSG_ERROR,"Unicast : fds->pfds[actual_fd].fd %d Socket %d \n", fds->pfds[actual_fd].fd,Socket); + actual_fd++; + } + return; + } + + log_message(MSG_DEBUG,"Unicast : We close the connection\n"); + //We delete the client + unicast_del_client(unicast_vars, unicast_vars->fd_info[actual_fd].client, channels); + //We move the last fd to the actual/deleted one, and decrease the number of fds by one + fds->pfds[actual_fd].fd = fds->pfds[fds->pfdsnum-1].fd; + fds->pfds[actual_fd].events = fds->pfds[fds->pfdsnum-1].events; + fds->pfds[actual_fd].revents = fds->pfds[fds->pfdsnum-1].revents; + //we move the file descriptor information + unicast_vars->fd_info[actual_fd] = unicast_vars->fd_info[fds->pfdsnum-1]; + //last one set to 0 for poll() + fds->pfds[fds->pfdsnum-1].fd=0; + fds->pfds[fds->pfdsnum-1].events=POLLIN|POLLPRI; + fds->pfds[fds->pfdsnum-1].revents=0; //We clear it to avoid nasty bugs ... + fds->pfdsnum--; + fds->pfds=realloc(fds->pfds,(fds->pfdsnum+1)*sizeof(struct pollfd)); + if (fds->pfds==NULL) + { + log_message(MSG_ERROR,"Problem with realloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); + Interrupted=ERROR_MEMORY<<8; + } + unicast_vars->fd_info=realloc(unicast_vars->fd_info,(fds->pfdsnum)*sizeof(unicast_fd_info_t)); + if (unicast_vars->fd_info==NULL) + { + log_message(MSG_ERROR,"Problem with realloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); + Interrupted=ERROR_MEMORY<<8; + } + log_message(MSG_DEBUG,"Unicast : Number of clients : %d\n", unicast_vars->client_number); + +} + + + + + + +//////////////////////// +// HTTP/RTSP Toolbox // +//////////////////////// + + + +/** @brief Init reply structure +* +*/ +unicast_reply_t* unicast_reply_init() +{ + unicast_reply_t* reply = malloc(sizeof (unicast_reply_t)); + if (NULL == reply) + { + log_message(MSG_ERROR,"Problem with malloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); + return NULL; + } + reply->buffer_header = malloc(REPLY_SIZE_STEP * sizeof (char)); + if (NULL == reply->buffer_header) + { + free(reply); + log_message(MSG_ERROR,"Problem with malloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); + return NULL; + } + reply->length_header = REPLY_SIZE_STEP; + reply->used_header = 0; + reply->buffer_body = malloc(REPLY_SIZE_STEP * sizeof (char)); + if (NULL == reply->buffer_body) + { + free(reply->buffer_header); + free(reply); + log_message(MSG_ERROR,"Problem with malloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); + return NULL; + } + reply->length_body = REPLY_SIZE_STEP; + reply->used_body = 0; + reply->type = REPLY_BODY; + return reply; +} + +/** @brief Release the reply structure +* +*/ +int unicast_reply_free(unicast_reply_t *reply) +{ + if (NULL == reply) + return 1; + if ((NULL == reply->buffer_header)&&(NULL == reply->buffer_body)) + return 1; + if(reply->buffer_header != NULL) + free(reply->buffer_header); + if(reply->buffer_body != NULL) + free(reply->buffer_body); + free(reply); + return 0; +} + +/** @brief Write data in a buffer using the same syntax that printf() +* +* auto-realloc buffer if needed +*/ +int unicast_reply_write(unicast_reply_t *reply, const char* msg, ...) +{ + char **buffer; + char *temp_buffer; + int *length; + int *used; + buffer=NULL; + va_list args; + if (NULL == msg) + return -1; + switch(reply->type) + { + case REPLY_HEADER: + buffer=&reply->buffer_header; + length=&reply->length_header; + used=&reply->used_header; + break; + case REPLY_BODY: + buffer=&reply->buffer_body; + length=&reply->length_body; + used=&reply->used_body; + break; + default: + log_message(MSG_WARN,"Unicast : unicast_reply_write with wrong type, please contact\n"); + return -1; + } + va_start(args, msg); + int estimated_len = vsnprintf(NULL, 0, msg, args); /* !! imply gcc -std=c99 */ + //Since vsnprintf put the mess we reinitiate the args + va_end(args); + va_start(args, msg); + while (*length - *used < estimated_len) { + temp_buffer = realloc(*buffer, *length + REPLY_SIZE_STEP); + if(temp_buffer == NULL) + { + log_message(MSG_ERROR,"Problem with realloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); + return -1; + } + *buffer=temp_buffer; + *length += REPLY_SIZE_STEP; + } + int real_len = vsnprintf(*buffer+*used, *length - *used, msg, args); + if (real_len != estimated_len) { + log_message(MSG_WARN,"Unicast : Error when writing the HTTP reply\n"); + } + *used += real_len; + va_end(args); + return 0; +} + +/** @brief Dump the filled buffer on the socket adding HTTP header informations +*/ +int unicast_reply_send(unicast_reply_t *reply, int socket, int code, const char* content_type) +{ + //we add the header information + reply->type = REPLY_HEADER; + unicast_reply_write(reply, "HTTP/1.0 "); + switch(code) + { + case 200: + unicast_reply_write(reply, "200 OK\r\n"); + break; + case 404: + unicast_reply_write(reply, "404 Not found\r\n"); + break; + default: + log_message(MSG_ERROR,"reply send with bad code please contact\n"); + return 0; + } + unicast_reply_write(reply, "Server: mumudvb/" VERSION "\r\n"); + unicast_reply_write(reply, "Content-type: %s\r\n", content_type); + unicast_reply_write(reply, "Content-length: %d\r\n", reply->used_body); + unicast_reply_write(reply, "\r\n"); /* end header */ + //we merge the header and the body + reply->buffer_header = realloc(reply->buffer_header, reply->used_header+reply->used_body); + memcpy(&reply->buffer_header[reply->used_header],reply->buffer_body,sizeof(char)*reply->used_body); + reply->used_header+=reply->used_body; + //now we write the data + int size = write(socket, reply->buffer_header, reply->used_header); + return size; +} + + +////////////////////// +// End HTTP Toolbox // +////////////////////// diff --git a/src/unicast_common.h b/src/unicast_common.h new file mode 100644 index 00000000..00ac292c --- /dev/null +++ b/src/unicast_common.h @@ -0,0 +1,57 @@ +/* + * MuMuDVB -Stream a DVB transport stream. + * + * (C) 2010 Brice DUBOST + * + * The latest version can be found at http://mumudvb.braice.net + * + * Copyright notice: + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/**@file + * @brief HTML unicast headers + */ + +#ifndef _UNICAST_COMMON_H +#define _UNICAST_COMMON_H + +#include "mumudvb.h" +#include "unicast_queue.h" + + +#define REPLY_HEADER 0 +#define REPLY_BODY 1 +#define REPLY_SIZE_STEP 256 + +typedef struct unicast_reply_t { + char* buffer_header; + char* buffer_body; + int length_header; + int length_body; + int used_header; + int used_body; + int type; +}unicast_reply_t; + +unicast_reply_t* unicast_reply_init(); +int unicast_reply_free(unicast_reply_t *reply); +int unicast_reply_write(unicast_reply_t *reply, const char* msg, ...); +int unicast_reply_send(unicast_reply_t *reply, int socket, int code, const char* content_type); + +void unicast_close_connection(unicast_parameters_t *unicast_vars, fds_t *fds, int Socket, mumudvb_channel_t *channels); + +#endif diff --git a/src/unicast_http.c b/src/unicast_http.c index 515bddd9..806aa496 100644 --- a/src/unicast_http.c +++ b/src/unicast_http.c @@ -63,15 +63,16 @@ Todo list #include "errors.h" #include "log.h" #include "unicast.h" +#include "unicast_common.h" extern int Interrupted; //from unicast_client.c -unicast_client_t *unicast_add_client(unicast_parameters_t *unicast_vars, struct sockaddr_in SocketAddr, int Socket); +unicast_client_t *unicast_add_client(unicast_parameters_t *unicast_vars, struct sockaddr_in SocketAddr, int Socket, int client_type); int channel_add_unicast_client(unicast_client_t *client,mumudvb_channel_t *channel); -unicast_client_t *unicast_accept_connection(unicast_parameters_t *unicast_vars, int socketIn); -void unicast_close_connection(unicast_parameters_t *unicast_vars, fds_t *fds, int Socket, mumudvb_channel_t *channels); +unicast_client_t *unicast_accept_http_connection(unicast_parameters_t *unicast_vars, int socketIn); + int unicast_send_streamed_channels_list (int number_of_channels, mumudvb_channel_t *channels, int Socket, char *host); @@ -86,166 +87,8 @@ unicast_send_signal_power_js (int Socket, fds_t *fds); int unicast_send_channel_traffic_js (int number_of_channels, mumudvb_channel_t *channels, int Socket); -int unicast_handle_message(unicast_parameters_t *unicast_vars, unicast_client_t *client, mumudvb_channel_t *channels, int num_of_channels, fds_t *fds); - -#define REPLY_HEADER 0 -#define REPLY_BODY 1 -#define REPLY_SIZE_STEP 256 - -typedef struct unicast_reply_t { - char* buffer_header; - char* buffer_body; - int length_header; - int length_body; - int used_header; - int used_body; - int type; -}unicast_reply_t; - -static unicast_reply_t* unicast_reply_init(); -static int unicast_reply_free(unicast_reply_t *reply); -static int unicast_reply_write(unicast_reply_t *reply, const char* msg, ...); -static int unicast_reply_send(unicast_reply_t *reply, int socket, int code, const char* content_type); - +int unicast_handle_http_message(unicast_parameters_t *unicast_vars, unicast_client_t *client, mumudvb_channel_t *channels, int num_of_channels, fds_t *fds); -/**@todo : deal with the RTP over http case ie implement RTSP*/ - - -/** @brief Read a line of the configuration file to check if there is a unicast parameter -* -* @param unicast_vars the unicast parameters -* @param substring The currrent line -*/ -int read_unicast_configuration(unicast_parameters_t *unicast_vars, mumudvb_channel_t *current_channel, int ip_ok, char *substring) -{ - - char delimiteurs[] = CONFIG_FILE_SEPARATOR; - - if (!strcmp (substring, "ip_http")) - { - substring = strtok (NULL, delimiteurs); - if(strlen(substring)>19) - { - log_message( MSG_ERROR, - "The Ip address %s is too long.\n", substring); - exit(ERROR_CONF); - } - sscanf (substring, "%s\n", unicast_vars->ipOut); - if(unicast_vars->ipOut) - { - if(unicast_vars->unicast==0) - { - log_message( MSG_WARN,"You should use the option \"unicast\" to activate unicast instead of ip_http\n"); - unicast_vars->unicast=1; - log_message( MSG_WARN,"You have enabled the support for HTTP Unicast. This feature is quite youg, please report any bug/comment\n"); - } - } - } - else if (!strcmp (substring, "unicast")) - { - substring = strtok (NULL, delimiteurs); - unicast_vars->unicast = atoi (substring); - if(unicast_vars->unicast) - { - log_message( MSG_WARN, - "You have enabled the support for HTTP Unicast. This feature is quite youg, please report any bug/comment\n"); - } - } - else if (!strcmp (substring, "unicast_consecutive_errors_timeout")) - { - substring = strtok (NULL, delimiteurs); - unicast_vars->consecutive_errors_timeout = atoi (substring); - if(unicast_vars->consecutive_errors_timeout<=0) - log_message( MSG_WARN, - "Warning : You have desactivated the unicast timeout for disconnecting clients, this can lead to an accumulation of zombie clients, this is unadvised, prefer a long timeout\n"); - } - else if (!strcmp (substring, "unicast_max_clients")) - { - substring = strtok (NULL, delimiteurs); - unicast_vars->max_clients = atoi (substring); - } - else if (!strcmp (substring, "unicast_queue_size")) - { - substring = strtok (NULL, delimiteurs); - unicast_vars->queue_max_size = atoi (substring); - } - else if (!strcmp (substring, "port_http")) - { - substring = strtok (NULL, ""); - if((strchr(substring,'*')!=NULL)||(strchr(substring,'+')!=NULL)||(strchr(substring,'%')!=NULL)) - { - unicast_vars->portOut_str=malloc(sizeof(char)*(strlen(substring)+1)); - strcpy(unicast_vars->portOut_str,substring); - } - else - unicast_vars->portOut = atoi (substring); - } - else if (!strcmp (substring, "unicast_port")) - { - if ( ip_ok == 0) - { - log_message( MSG_ERROR, - "unicast_port : You have to start a channel first (using ip= or channel_next)\n"); - exit(ERROR_CONF); - } - substring = strtok (NULL, delimiteurs); - current_channel->unicast_port = atoi (substring); - } - else - return 0; //Nothing concerning tuning, we return 0 to explore the other possibilities - - return 1;//We found something for tuning, we tell main to go for the next line - -} - - - -/** @brief Create a listening socket and add it to the list of polling file descriptors if success -* -* -* -*/ -int unicast_create_listening_socket(int socket_type, int socket_channel, char *ipOut, int port, struct sockaddr_in *sIn, int *socketIn, fds_t *fds, unicast_parameters_t *unicast_vars) -{ - *socketIn= makeTCPclientsocket(ipOut, port, sIn); - //We add them to the poll descriptors - if(*socketIn>0) - { - fds->pfdsnum++; - log_message(MSG_DEBUG, "unicast : fds->pfdsnum : %d\n", fds->pfdsnum); - fds->pfds=realloc(fds->pfds,(fds->pfdsnum+1)*sizeof(struct pollfd)); - if (fds->pfds==NULL) - { - log_message(MSG_ERROR,"Problem with realloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); - return -1; - } - fds->pfds[fds->pfdsnum-1].fd = *socketIn; - fds->pfds[fds->pfdsnum-1].events = POLLIN | POLLPRI; - fds->pfds[fds->pfdsnum-1].revents = 0; - fds->pfds[fds->pfdsnum].fd = 0; - fds->pfds[fds->pfdsnum].events = POLLIN | POLLPRI; - fds->pfds[fds->pfdsnum].revents = 0; - //Information about the descriptor - unicast_vars->fd_info=realloc(unicast_vars->fd_info,(fds->pfdsnum)*sizeof(unicast_fd_info_t)); - if (unicast_vars->fd_info==NULL) - { - log_message(MSG_ERROR,"Problem with realloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); - return -1; - } - //Master connection - unicast_vars->fd_info[fds->pfdsnum-1].type=socket_type; - unicast_vars->fd_info[fds->pfdsnum-1].channel=socket_channel; - unicast_vars->fd_info[fds->pfdsnum-1].client=NULL; - } - else - { - log_message( MSG_WARN, "Problem creating the socket %s:%d : %s\n",ipOut,port,strerror(errno) ); - return -1; - } - - return 0; - -} /** @brief Handle an "event" on the unicast file descriptors * If the event is on an already open client connection, it handle the message @@ -282,7 +125,7 @@ int unicast_handle_fd_event(unicast_parameters_t *unicast_vars, fds_t *fds, mumu int tempSocket; unicast_client_t *tempClient; //we accept the incoming connection - tempClient=unicast_accept_connection(unicast_vars, fds->pfds[actual_fd].fd); + tempClient=unicast_accept_http_connection(unicast_vars, fds->pfds[actual_fd].fd); if(tempClient!=NULL) { @@ -332,7 +175,7 @@ int unicast_handle_fd_event(unicast_parameters_t *unicast_vars, fds_t *fds, mumu { //Event on a client connectio i.e. the client asked something log_message(MSG_FLOOD,"Unicast : New message for socket %d\n", fds->pfds[actual_fd].fd); - iRet=unicast_handle_message(unicast_vars,unicast_vars->fd_info[actual_fd].client, channels, number_of_channels, fds); + iRet=unicast_handle_http_message(unicast_vars,unicast_vars->fd_info[actual_fd].client, channels, number_of_channels, fds); if (iRet==-2 ) //iRet==-2 --> 0 received data or error, we close the connection { unicast_close_connection(unicast_vars,fds,fds->pfds[actual_fd].fd,channels); @@ -361,7 +204,7 @@ int unicast_handle_fd_event(unicast_parameters_t *unicast_vars, fds_t *fds, mumu * @param unicast_vars the unicast parameters * @param socketIn the socket on wich the connection was made */ -unicast_client_t *unicast_accept_connection(unicast_parameters_t *unicast_vars, int socketIn) +unicast_client_t *unicast_accept_http_connection(unicast_parameters_t *unicast_vars, int socketIn) { unsigned int l; @@ -401,7 +244,7 @@ unicast_client_t *unicast_accept_connection(unicast_parameters_t *unicast_vars, return NULL; } - tempClient=unicast_add_client(unicast_vars, tempSocketAddrIn, tempSocket); + tempClient=unicast_add_client(unicast_vars, tempSocketAddrIn, tempSocket, CLIENT_HTTP); if( tempClient == NULL) { //We cannot create the client, we close the socket cleanly @@ -414,64 +257,6 @@ unicast_client_t *unicast_accept_connection(unicast_parameters_t *unicast_vars, } -/** @brief Close an unicast connection and delete the client -* -* @param unicast_vars the unicast parameters -* @param fds The polling file descriptors -* @param Socket The socket of the client we want to disconnect -* @param channels The channel list -*/ -void unicast_close_connection(unicast_parameters_t *unicast_vars, fds_t *fds, int Socket, mumudvb_channel_t *channels) -{ - - int actual_fd; - actual_fd=0; - //We find the FD correspondig to this client - while((actual_fdpfdsnum) && (fds->pfds[actual_fd].fd!=Socket)) - actual_fd++; - - if(actual_fd==fds->pfdsnum) - { - log_message(MSG_ERROR,"Unicast : close connection : we did't find the file descriptor this should never happend, please contact\n"); - actual_fd=0; - //We find the FD correspondig to this client - while(actual_fdpfdsnum) - { - log_message(MSG_ERROR,"Unicast : fds->pfds[actual_fd].fd %d Socket %d \n", fds->pfds[actual_fd].fd,Socket); - actual_fd++; - } - return; - } - - log_message(MSG_DEBUG,"Unicast : We close the connection\n"); - //We delete the client - unicast_del_client(unicast_vars, unicast_vars->fd_info[actual_fd].client, channels); - //We move the last fd to the actual/deleted one, and decrease the number of fds by one - fds->pfds[actual_fd].fd = fds->pfds[fds->pfdsnum-1].fd; - fds->pfds[actual_fd].events = fds->pfds[fds->pfdsnum-1].events; - fds->pfds[actual_fd].revents = fds->pfds[fds->pfdsnum-1].revents; - //we move the file descriptor information - unicast_vars->fd_info[actual_fd] = unicast_vars->fd_info[fds->pfdsnum-1]; - //last one set to 0 for poll() - fds->pfds[fds->pfdsnum-1].fd=0; - fds->pfds[fds->pfdsnum-1].events=POLLIN|POLLPRI; - fds->pfds[fds->pfdsnum-1].revents=0; //We clear it to avoid nasty bugs ... - fds->pfdsnum--; - fds->pfds=realloc(fds->pfds,(fds->pfdsnum+1)*sizeof(struct pollfd)); - if (fds->pfds==NULL) - { - log_message(MSG_ERROR,"Problem with realloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); - Interrupted=ERROR_MEMORY<<8; - } - unicast_vars->fd_info=realloc(unicast_vars->fd_info,(fds->pfdsnum)*sizeof(unicast_fd_info_t)); - if (unicast_vars->fd_info==NULL) - { - log_message(MSG_ERROR,"Problem with realloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); - Interrupted=ERROR_MEMORY<<8; - } - log_message(MSG_DEBUG,"Unicast : Number of clients : %d\n", unicast_vars->client_number); - -} @@ -485,7 +270,7 @@ void unicast_close_connection(unicast_parameters_t *unicast_vars, fds_t *fds, in * @param channels the channel array * @param number_of_channels quite explicit ... */ -int unicast_handle_message(unicast_parameters_t *unicast_vars, unicast_client_t *client, mumudvb_channel_t *channels, int number_of_channels, fds_t *fds) +int unicast_handle_http_message(unicast_parameters_t *unicast_vars, unicast_client_t *client, mumudvb_channel_t *channels, int number_of_channels, fds_t *fds) { int received_len; (void) unicast_vars; @@ -758,154 +543,6 @@ int unicast_handle_message(unicast_parameters_t *unicast_vars, unicast_client_t } -////////////////// -// HTTP Toolbox // -////////////////// - - - -/** @brief Init reply structure -* -*/ -unicast_reply_t* unicast_reply_init() -{ - unicast_reply_t* reply = malloc(sizeof (unicast_reply_t)); - if (NULL == reply) - { - log_message(MSG_ERROR,"Problem with malloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); - return NULL; - } - reply->buffer_header = malloc(REPLY_SIZE_STEP * sizeof (char)); - if (NULL == reply->buffer_header) - { - free(reply); - log_message(MSG_ERROR,"Problem with malloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); - return NULL; - } - reply->length_header = REPLY_SIZE_STEP; - reply->used_header = 0; - reply->buffer_body = malloc(REPLY_SIZE_STEP * sizeof (char)); - if (NULL == reply->buffer_body) - { - free(reply->buffer_header); - free(reply); - log_message(MSG_ERROR,"Problem with malloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); - return NULL; - } - reply->length_body = REPLY_SIZE_STEP; - reply->used_body = 0; - reply->type = REPLY_BODY; - return reply; -} - -/** @brief Release the reply structure -* -*/ -int unicast_reply_free(unicast_reply_t *reply) -{ - if (NULL == reply) - return 1; - if ((NULL == reply->buffer_header)&&(NULL == reply->buffer_body)) - return 1; - if(reply->buffer_header != NULL) - free(reply->buffer_header); - if(reply->buffer_body != NULL) - free(reply->buffer_body); - free(reply); - return 0; -} - -/** @brief Write data in a buffer using the same syntax that printf() -* -* auto-realloc buffer if needed -*/ -int unicast_reply_write(unicast_reply_t *reply, const char* msg, ...) -{ - char **buffer; - char *temp_buffer; - int *length; - int *used; - buffer=NULL; - va_list args; - if (NULL == msg) - return -1; - switch(reply->type) - { - case REPLY_HEADER: - buffer=&reply->buffer_header; - length=&reply->length_header; - used=&reply->used_header; - break; - case REPLY_BODY: - buffer=&reply->buffer_body; - length=&reply->length_body; - used=&reply->used_body; - break; - default: - log_message(MSG_WARN,"Unicast : unicast_reply_write with wrong type, please contact\n"); - return -1; - } - va_start(args, msg); - int estimated_len = vsnprintf(NULL, 0, msg, args); /* !! imply gcc -std=c99 */ - //Since vsnprintf put the mess we reinitiate the args - va_end(args); - va_start(args, msg); - while (*length - *used < estimated_len) { - temp_buffer = realloc(*buffer, *length + REPLY_SIZE_STEP); - if(temp_buffer == NULL) - { - log_message(MSG_ERROR,"Problem with realloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); - return -1; - } - *buffer=temp_buffer; - *length += REPLY_SIZE_STEP; - } - int real_len = vsnprintf(*buffer+*used, *length - *used, msg, args); - if (real_len != estimated_len) { - log_message(MSG_WARN,"Unicast : Error when writing the HTTP reply\n"); - } - *used += real_len; - va_end(args); - return 0; -} - -/** @brief Dump the filled buffer on the socket adding HTTP header informations -*/ -int unicast_reply_send(unicast_reply_t *reply, int socket, int code, const char* content_type) -{ - //we add the header information - reply->type = REPLY_HEADER; - unicast_reply_write(reply, "HTTP/1.0 "); - switch(code) - { - case 200: - unicast_reply_write(reply, "200 OK\r\n"); - break; - case 404: - unicast_reply_write(reply, "404 Not found\r\n"); - break; - default: - log_message(MSG_ERROR,"reply send with bad code please contact\n"); - return 0; - } - unicast_reply_write(reply, "Server: mumudvb/" VERSION "\r\n"); - unicast_reply_write(reply, "Content-type: %s\r\n", content_type); - unicast_reply_write(reply, "Content-length: %d\r\n", reply->used_body); - unicast_reply_write(reply, "\r\n"); /* end header */ - //we merge the header and the body - reply->buffer_header = realloc(reply->buffer_header, reply->used_header+reply->used_body); - memcpy(&reply->buffer_header[reply->used_header],reply->buffer_body,sizeof(char)*reply->used_body); - reply->used_header+=reply->used_body; - //now we write the data - int size = write(socket, reply->buffer_header, reply->used_header); - return size; -} - - -////////////////////// -// End HTTP Toolbox // -////////////////////// - /** @brief Send a basic html file containig the list of streamed channels @@ -1111,12 +748,12 @@ int unicast_send_streamed_channels_list_js (int number_of_channels, mumudvb_chan channels[curr_channel].service_id, service_type_to_str(channels[curr_channel].channel_type), channels[curr_channel].num_pids); - unicast_reply_write(reply, "\"pids\":["); - for(int i=0;iused_body -= 2; // dirty hack to erase the last comma - unicast_reply_write(reply, "]"); - unicast_reply_write(reply, "},\n"); + unicast_reply_write(reply, "\"pids\":["); + for(int i=0;iused_body -= 2; // dirty hack to erase the last comma + unicast_reply_write(reply, "]"); + unicast_reply_write(reply, "},\n"); } reply->used_body -= 2; // dirty hack to erase the last comma diff --git a/src/unicast_http.h b/src/unicast_http.h index e743665d..c75f5860 100644 --- a/src/unicast_http.h +++ b/src/unicast_http.h @@ -31,14 +31,10 @@ #include "mumudvb.h" #include "unicast_queue.h" +#include "unicast.h" -#define RECV_BUFFER_MULTIPLE 100 -/**@brief the timeout for disconnecting a client with only consecutive errors*/ -#define UNICAST_CONSECUTIVE_ERROR_TIMEOUT 5 - - #define HTTP_OK_REPLY "HTTP/1.0 200 OK\r\n"\ "Content-type: video/mpeg\r\n"\ "\r\n" @@ -80,93 +76,6 @@ "\r\n" -/** @brief A client connected to the unicast connection. - * - *There is two chained list of client : a global one wich contain all the clients. Another one in each channel wich contain the associated clients. - */ -typedef struct unicast_client_t{ - /**HTTP socket*/ - struct sockaddr_in SocketAddr; - /**HTTP socket*/ - int Socket; - /**Reception buffer*/ - char *buffer; - /**Size of the buffer*/ - int buffersize; - /**Position in the buffer*/ - int bufferpos; - /**Is there consecutive errors ?*/ - int consecutive_errors; - /**When the first consecutive error happeard*/ - long first_error_time; - /**Channel : -1 if not associated yet*/ - int channel; - /**Future channel : we will set the channel when we will receive the get*/ - int askedChannel; - /**Next client*/ - struct unicast_client_t *next; - /**Previous client*/ - struct unicast_client_t *prev; - /**Next client in the channel*/ - struct unicast_client_t *chan_next; - /**Previous client in the channel*/ - struct unicast_client_t *chan_prev; - /** The packets in queue*/ - unicast_queue_header_t queue; - /** The latest write error for this client*/ - int last_write_error; -}unicast_client_t; - - -/** @brief The information on the unicast file descriptors/sockets - * There is three kind of descriptors : - * The master connection : this connection will interpret the HTTP path asked, to give the channel, the channel list or debugging information - * Client connections : This is the connections for connected clients - * Channel listening connections : When a client connect to one of these sockets, the associated channel will be given directly without interpreting the PATH - * - * The numbering of this socket information is the same as the file descriptors numbering - */ -typedef struct unicast_fd_info_t{ - /**The fd/socket type*/ - int type; - /** The channel if it's a channel socket*/ - int channel; - /** The client if it's a client socket*/ - unicast_client_t *client; -}unicast_fd_info_t; - - -/** @brief The parameters for unicast -*/ -typedef struct unicast_parameters_t{ - /** Do we activate unicast ?*/ - int unicast; - /**The "HTTP" ip address*/ - char ipOut[20]; - /** The "HTTP" port*/ - int portOut; - /** The "HTTP" port string version before parsing*/ - char *portOut_str; - /** The HTTP input socket*/ - struct sockaddr_in sIn; - /** The HTTP input socket*/ - int socketIn; - /** The clients, contains all the clients, associated to a channel or not*/ - unicast_client_t *clients; - /** The number of connected clients*/ - int client_number; - /** The maximum number of simultaneous clients allowed*/ - int max_clients; - /** The timeout before disconnecting a client wich does only errors*/ - int consecutive_errors_timeout; - /** The information on the file descriptors : ie the type of FD, the client associated if it's a client fd, the channel if it's a channel fd */ - unicast_fd_info_t *fd_info; - /** The maximim size of the queue */ - int queue_max_size; -}unicast_parameters_t; - -int unicast_create_listening_socket(int socket_type, int socket_channel, char *ipOut, int port, struct sockaddr_in *sIn, int *socketIn, fds_t *fds, unicast_parameters_t *unicast_vars); - int unicast_handle_fd_event(unicast_parameters_t *unicast_vars, fds_t *fds, mumudvb_channel_t *channels, int number_of_channels); int unicast_del_client(unicast_parameters_t *unicast_vars, unicast_client_t *client, mumudvb_channel_t *channels); @@ -175,8 +84,6 @@ int channel_add_unicast_client(unicast_client_t *client,mumudvb_channel_t *chann void unicast_freeing(unicast_parameters_t *unicast_vars, mumudvb_channel_t *channels); -int read_unicast_configuration(unicast_parameters_t *unicast_vars, mumudvb_channel_t *current_channel, int ip_ok, char *substring); - void unicast_data_send(mumudvb_channel_t *actual_channel, mumudvb_channel_t *channels, fds_t *fds, unicast_parameters_t *unicast_vars); diff --git a/src/unicast_queue.c b/src/unicast_queue.c index 2673d414..c2d6ef90 100644 --- a/src/unicast_queue.c +++ b/src/unicast_queue.c @@ -39,6 +39,7 @@ #include "errors.h" #include "log.h" #include "unicast.h" +#include "unicast_common.h" int unicast_queue_remove_data(unicast_queue_header_t *header); diff --git a/src/unicast_rtsp.h b/src/unicast_rtsp.h new file mode 100644 index 00000000..4ae4ca5e --- /dev/null +++ b/src/unicast_rtsp.h @@ -0,0 +1,41 @@ +/* + * MuMuDVB - Stream a DVB transport stream. + * + * (C) 2010 Brice DUBOST + * + * The latest version can be found at http://mumudvb.braice.net + * + * Copyright notice: + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/**@file + * @brief RTSP unicast headers + */ + +#ifndef _UNICAST_RTSP_H +#define _UNICAST_RTSP_H + +#include "mumudvb.h" +#include "unicast_queue.h" +#include "unicast.h" + + + + + + +#endif From 627542e1316c916581b65e0784f5f08062bc0239 Mon Sep 17 00:00:00 2001 From: braice Date: Sat, 16 Jan 2010 19:54:11 +0100 Subject: [PATCH 03/28] Unicast : RTSP master socket --- src/Makefile.am | 3 +- src/autoconf.c | 2 +- src/autoconf.h | 2 +- src/config.h | 207 +++++++++++++++++++++++++++++++++++++++ src/mumudvb.c | 42 +++++--- src/unicast.h | 31 +++++- src/unicast_common.c | 226 +++++++++++++++++++++++++++++++++++++++++-- src/unicast_common.h | 7 +- src/unicast_http.c | 205 ++++----------------------------------- src/unicast_http.h | 6 +- src/unicast_queue.h | 9 -- src/unicast_rtsp.c | 77 +++++++++++++++ src/unicast_rtsp.h | 4 +- 13 files changed, 596 insertions(+), 225 deletions(-) create mode 100644 src/config.h create mode 100644 src/unicast_rtsp.c diff --git a/src/Makefile.am b/src/Makefile.am index a1978819..0a40b13b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -7,7 +7,8 @@ mumudvb_SOURCES = autoconf.c crc32.c dvb.h log.c log.h multicast.c mumudvb.h net rtp.h sap.h ts.h tune.h unicast_http.h autoconf.h dvb.c errors.h unicast_common.h \ mumudvb.c mumudvb_common.c network.c pat_rewrite.c rewrite.c sdt_rewrite.c \ rtp.c sap.c ts.c tune.c unicast_http.c unicast_queue.c autoconf_sdt.c autoconf_atsc.c \ - autoconf_pmt.c autoconf_nit.c unicast_clients.c unicast_common.c unicast_common.h + autoconf_pmt.c autoconf_nit.c unicast_clients.c unicast_common.c unicast_common.h \ + unicast_rtsp.c unicast_rtsp.h unicast.h if BUILD_CAMSUPPORT mumudvb_SOURCES += $(SOURCES_camsupport) diff --git a/src/autoconf.c b/src/autoconf.c index 2ce4cc57..f8dd6e21 100644 --- a/src/autoconf.c +++ b/src/autoconf.c @@ -848,7 +848,7 @@ void autoconf_definite_end(int card, mumudvb_chan_and_pids_t *chan_and_pids, int { log_message(MSG_INFO,"Autoconfiguration done\n"); - log_streamed_channels(chan_and_pids->number_of_channels, chan_and_pids->channels, multicast, unicast_vars->unicast, unicast_vars->portOut, unicast_vars->ipOut); + log_streamed_channels(chan_and_pids->number_of_channels, chan_and_pids->channels, multicast, unicast_vars->unicast, unicast_vars->http_portOut, unicast_vars->ipOut); /**@todo : make an option to generate it or not ?*/ char filename_gen_conf[256]; diff --git a/src/autoconf.h b/src/autoconf.h index 3a44cd42..68df60ef 100644 --- a/src/autoconf.h +++ b/src/autoconf.h @@ -30,7 +30,7 @@ #define _AUTOCONF_H #include "mumudvb.h" -#include "unicast_http.h" +#include "unicast.h" #include "ts.h" #include "tune.h" diff --git a/src/config.h b/src/config.h new file mode 100644 index 00000000..af9ac98d --- /dev/null +++ b/src/config.h @@ -0,0 +1,207 @@ +/* src/config.h. Generated from config.h.in by configure. */ +/* src/config.h.in. Generated from configure.ac by autoheader. */ + +/* Define if you want the CAM support */ +/* #undef ENABLE_CAM_SUPPORT */ + +/* Define if you want the transcoding support */ +/* #undef ENABLE_TRANSCODING */ + +/* Define to 1 if you have the `alarm' function. */ +#define HAVE_ALARM 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ARPA_INET_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ARPA_NAMESER_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_FFMPEG_AVCODEC_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_FFMPEG_AVFORMAT_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_FFMPEG_SWSCALE_H */ + +/* Define to 1 if you have the `gettimeofday' function. */ +#define HAVE_GETTIMEOFDAY 1 + +/* Define if you have the iconv() function and it works. */ +#define HAVE_ICONV 1 + +/* Define to 1 if you have the `inet_ntoa' function. */ +#define HAVE_INET_NTOA 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the `avcodec' library (-lavcodec). */ +/* #undef HAVE_LIBAVCODEC */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LIBAVCODEC_AVCODEC_H */ + +/* Define to 1 if you have the `avformat' library (-lavformat). */ +/* #undef HAVE_LIBAVFORMAT */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LIBAVFORMAT_AVFORMAT_H */ + +/* Define to 1 if you have the `duma' library (-lduma). */ +/* #undef HAVE_LIBDUMA */ + +/* Define to 1 if you have the `dvbapi' library (-ldvbapi). */ +/* #undef HAVE_LIBDVBAPI */ + +/* Define to 1 if you have the `dvben50221' library (-ldvben50221). */ +/* #undef HAVE_LIBDVBEN50221 */ + +/* Define to 1 if you have the `pthread' library (-lpthread). */ +#define HAVE_LIBPTHREAD 1 + +/* Define to 1 if you have the `swscale' library (-lswscale). */ +/* #undef HAVE_LIBSWSCALE */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LIBSWSCALE_SWSCALE_H */ + +/* Define to 1 if you have the `ucsi' library (-lucsi). */ +/* #undef HAVE_LIBUCSI */ + +/* Define to 1 if your system has a GNU libc compatible `malloc' function, and + to 0 otherwise. */ +#define HAVE_MALLOC 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `memset' function. */ +#define HAVE_MEMSET 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETDB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETINET_IN_H 1 + +/* Define to 1 if your system has a GNU libc compatible `realloc' function, + and to 0 otherwise. */ +#define HAVE_REALLOC 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_RESOLV_H 1 + +/* Define to 1 if you have the `socket' function. */ +#define HAVE_SOCKET 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the `strerror' function. */ +#define HAVE_STRERROR 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `strstr' function. */ +#define HAVE_STRSTR 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYSLOG_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_IOCTL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_VALUES_H 1 + +/* Define as const if the declaration of iconv() needs const. */ +#define ICONV_CONST + +/* Name of package */ +#define PACKAGE "mumudvb" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "mumudvb@braice.net" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "MuMuDVB" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "MuMuDVB 1.6.1b_20100101" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "mumudvb" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "1.6.1b_20100101" + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Version number of package */ +#define VERSION "1.6.1b_20100101" + +/* Define for Solaris 2.5.1 so the uint32_t typedef from , + , or is not used. If the typedef were allowed, the + #define below would cause a syntax error. */ +/* #undef _UINT32_T */ + +/* Define for Solaris 2.5.1 so the uint8_t typedef from , + , or is not used. If the typedef were allowed, the + #define below would cause a syntax error. */ +/* #undef _UINT8_T */ + +/* Define to the type of a signed integer type of width exactly 32 bits if + such a type exists and the standard includes do not define it. */ +/* #undef int32_t */ + +/* Define to rpl_malloc if the replacement function should be used. */ +/* #undef malloc */ + +/* Define to rpl_realloc if the replacement function should be used. */ +/* #undef realloc */ + +/* Define to `unsigned int' if does not define. */ +/* #undef size_t */ + +/* Define to the type of an unsigned integer type of width exactly 16 bits if + such a type exists and the standard includes do not define it. */ +/* #undef uint16_t */ + +/* Define to the type of an unsigned integer type of width exactly 32 bits if + such a type exists and the standard includes do not define it. */ +/* #undef uint32_t */ + +/* Define to the type of an unsigned integer type of width exactly 8 bits if + such a type exists and the standard includes do not define it. */ +/* #undef uint8_t */ diff --git a/src/mumudvb.c b/src/mumudvb.c index 9e76150f..1b13d117 100644 --- a/src/mumudvb.c +++ b/src/mumudvb.c @@ -294,8 +294,11 @@ rewrite_parameters_t rewrite_vars={ unicast_parameters_t unicast_vars={ .unicast=0, .ipOut="0.0.0.0", - .portOut=4242, - .portOut_str=NULL, + .http_portOut=4242, + .http_portOut_str=NULL, + .unicast_rtsp_enable=0, + .rtsp_portOut=554, + .rtsp_portOut_str=NULL, .consecutive_errors_timeout=UNICAST_CONSECUTIVE_ERROR_TIMEOUT, .max_clients=-1, .queue_max_size=UNICAST_DEFAULT_QUEUE_MAX, @@ -768,17 +771,29 @@ int //If we specified a string for the unicast port out, we parse it - if(unicast_vars.portOut_str!=NULL) + if(unicast_vars.http_portOut_str!=NULL) { int len; - len=strlen(unicast_vars.portOut_str)+1; + len=strlen(unicast_vars.http_portOut_str)+1; char number[10]; sprintf(number,"%d",tuneparams.card); - unicast_vars.portOut_str=mumu_string_replace(unicast_vars.portOut_str,&len,1,"%card",number); + unicast_vars.http_portOut_str=mumu_string_replace(unicast_vars.http_portOut_str,&len,1,"%card",number); sprintf(number,"%d",server_id); - unicast_vars.portOut_str=mumu_string_replace(unicast_vars.portOut_str,&len,1,"%server",number); - unicast_vars.portOut=string_comput(unicast_vars.portOut_str); - log_message( MSG_DEBUG, "Unicast: computed unicast master port : %d\n",unicast_vars.portOut); + unicast_vars.http_portOut_str=mumu_string_replace(unicast_vars.http_portOut_str,&len,1,"%server",number); + unicast_vars.http_portOut=string_comput(unicast_vars.http_portOut_str); + log_message( MSG_DEBUG, "Unicast: computed unicast master port : %d\n",unicast_vars.http_portOut); + } + if(unicast_vars.unicast_rtsp_enable && unicast_vars.rtsp_portOut_str!=NULL) + { + int len; + len=strlen(unicast_vars.rtsp_portOut_str)+1; + char number[10]; + sprintf(number,"%d",tuneparams.card); + unicast_vars.rtsp_portOut_str=mumu_string_replace(unicast_vars.rtsp_portOut_str,&len,1,"%card",number); + sprintf(number,"%d",server_id); + unicast_vars.rtsp_portOut_str=mumu_string_replace(unicast_vars.rtsp_portOut_str,&len,1,"%server",number); + unicast_vars.rtsp_portOut=string_comput(unicast_vars.rtsp_portOut_str); + log_message( MSG_DEBUG, "Unicast: computed unicast RTSP port : %d\n",unicast_vars.rtsp_portOut); } /******************************************************/ //end of config file reading @@ -1206,8 +1221,8 @@ int //We open the socket for the http unicast if needed and we update the poll structure if(unicast_vars.unicast) { - log_message(MSG_INFO,"Unicast : We open the Master http socket for address %s:%d\n",unicast_vars.ipOut, unicast_vars.portOut); - unicast_create_listening_socket(UNICAST_MASTER_HTTP, -1, unicast_vars.ipOut, unicast_vars.portOut, &unicast_vars.sIn, &unicast_vars.socketIn, &fds, &unicast_vars); + log_message(MSG_INFO,"Unicast : We open the Master HTTP socket for address %s:%d\n",unicast_vars.ipOut, unicast_vars.http_portOut); + unicast_create_listening_socket(UNICAST_MASTER_HTTP, -1, unicast_vars.ipOut, unicast_vars.http_portOut, &unicast_vars.http_sIn, &unicast_vars.http_socketIn, &fds, &unicast_vars); /** open the unicast listening connections fo the channels */ for (curr_channel = 0; curr_channel < chan_and_pids.number_of_channels; curr_channel++) if(chan_and_pids.channels[curr_channel].unicast_port) @@ -1215,6 +1230,11 @@ int log_message(MSG_INFO,"Unicast : We open the channel %d http socket address %s:%d\n",curr_channel, unicast_vars.ipOut, chan_and_pids.channels[curr_channel].unicast_port); unicast_create_listening_socket(UNICAST_LISTEN_CHANNEL, curr_channel, unicast_vars.ipOut,chan_and_pids.channels[curr_channel].unicast_port , &chan_and_pids.channels[curr_channel].sIn, &chan_and_pids.channels[curr_channel].socketIn, &fds, &unicast_vars); } + if(unicast_vars.unicast_rtsp_enable) + { + log_message(MSG_INFO,"Unicast : We open the Master RTSP socket for address %s:%d\n",unicast_vars.ipOut, unicast_vars.rtsp_portOut); + unicast_create_listening_socket(UNICAST_MASTER_RTSP, -1, unicast_vars.ipOut, unicast_vars.rtsp_portOut, &unicast_vars.rtsp_sIn, &unicast_vars.rtsp_socketIn, &fds, &unicast_vars); + } } @@ -1231,7 +1251,7 @@ int /*****************************************************/ if(autoconf_vars.autoconfiguration!=AUTOCONF_MODE_FULL) - log_streamed_channels(chan_and_pids.number_of_channels, chan_and_pids.channels, multicast_vars.multicast, unicast_vars.unicast, unicast_vars.portOut, unicast_vars.ipOut); + log_streamed_channels(chan_and_pids.number_of_channels, chan_and_pids.channels, multicast_vars.multicast, unicast_vars.unicast, unicast_vars.http_portOut, unicast_vars.ipOut); if(autoconf_vars.autoconfiguration) log_message(MSG_INFO,"Autoconfiguration Start\n"); diff --git a/src/unicast.h b/src/unicast.h index 1b2c1ee5..1bd15d1e 100644 --- a/src/unicast.h +++ b/src/unicast.h @@ -33,13 +33,16 @@ #include "unicast_queue.h" #define RTSP_PORT 554 +#define CLOSE_CONNECTION -2 /** @brief The different fd/socket types */ enum { UNICAST_MASTER_HTTP=1, + UNICAST_MASTER_RTSP, UNICAST_LISTEN_CHANNEL, - UNICAST_CLIENT, + UNICAST_CLIENT_HTTP, + UNICAST_CLIENT_RTSP, }; /** @brief The different client types */ @@ -67,6 +70,8 @@ typedef struct unicast_client_t{ struct sockaddr_in SocketAddr; /**HTTP/Contol socket*/ int Socket; + /** Socket closed (RTSP no keep alive)*/ + int Control_socket_closed; /**Reception buffer*/ char *buffer; /**Size of the buffer*/ @@ -122,13 +127,23 @@ typedef struct unicast_parameters_t{ /**The "HTTP" ip address*/ char ipOut[20]; /** The "HTTP" port*/ - int portOut; + int http_portOut; /** The "HTTP" port string version before parsing*/ - char *portOut_str; + char *http_portOut_str; /** The HTTP input socket*/ - struct sockaddr_in sIn; + struct sockaddr_in http_sIn; /** The HTTP input socket*/ - int socketIn; + int http_socketIn; + /** RTSP enable */ + int unicast_rtsp_enable; + /** The "RTSP" port*/ + int rtsp_portOut; + /** The "RTSP" port string version before parsing*/ + char *rtsp_portOut_str; + /** The RTSP input socket*/ + struct sockaddr_in rtsp_sIn; + /** The RTSP input socket*/ + int rtsp_socketIn; /** The clients, contains all the clients, associated to a channel or not*/ unicast_client_t *clients; /** The number of connected clients*/ @@ -148,4 +163,10 @@ int read_unicast_configuration(unicast_parameters_t *unicast_vars, mumudvb_chann int unicast_create_listening_socket(int socket_type, int socket_channel, char *ipOut, int port, struct sockaddr_in *sIn, int *socketIn, fds_t *fds, unicast_parameters_t *unicast_vars); +int unicast_handle_fd_event(unicast_parameters_t *unicast_vars, fds_t *fds, mumudvb_channel_t *channels, int number_of_channels); + +void unicast_freeing(unicast_parameters_t *unicast_vars, mumudvb_channel_t *channels); + +void unicast_data_send(mumudvb_channel_t *actual_channel, mumudvb_channel_t *channels, fds_t *fds, unicast_parameters_t *unicast_vars); + #endif diff --git a/src/unicast_common.c b/src/unicast_common.c index 6b78edf4..34be8a3f 100644 --- a/src/unicast_common.c +++ b/src/unicast_common.c @@ -49,15 +49,16 @@ #include #include -#include "unicast_http.h" #include "unicast_queue.h" #include "mumudvb.h" #include "errors.h" #include "log.h" #include "unicast.h" #include "unicast_common.h" +#include "unicast_http.h" +#include "unicast_rtsp.h" - +extern int Interrupted; /** @brief Read a line of the configuration file to check if there is a unicast parameter @@ -123,11 +124,29 @@ int read_unicast_configuration(unicast_parameters_t *unicast_vars, mumudvb_chann substring = strtok (NULL, ""); if((strchr(substring,'*')!=NULL)||(strchr(substring,'+')!=NULL)||(strchr(substring,'%')!=NULL)) { - unicast_vars->portOut_str=malloc(sizeof(char)*(strlen(substring)+1)); - strcpy(unicast_vars->portOut_str,substring); + unicast_vars->http_portOut_str=malloc(sizeof(char)*(strlen(substring)+1)); + strcpy(unicast_vars->http_portOut_str,substring); } else - unicast_vars->portOut = atoi (substring); + unicast_vars->http_portOut = atoi (substring); + } + else if (!strcmp (substring, "port_rtsp")) + { + substring = strtok (NULL, ""); + if((strchr(substring,'*')!=NULL)||(strchr(substring,'+')!=NULL)||(strchr(substring,'%')!=NULL)) + { + unicast_vars->rtsp_portOut_str=malloc(sizeof(char)*(strlen(substring)+1)); + strcpy(unicast_vars->rtsp_portOut_str,substring); + } + else + unicast_vars->rtsp_portOut = atoi (substring); + } + else if (!strcmp (substring, "unicast_rtsp")) + { + substring = strtok (NULL, delimiteurs); + unicast_vars->unicast_rtsp_enable = atoi (substring); + if(unicast_vars->unicast_rtsp_enable) + log_message(MSG_DETAIL, "RTSP enabled\n"); } else if (!strcmp (substring, "unicast_port")) { @@ -205,7 +224,7 @@ int unicast_create_listening_socket(int socket_type, int socket_channel, char *i */ void unicast_close_connection(unicast_parameters_t *unicast_vars, fds_t *fds, int Socket, mumudvb_channel_t *channels) { - + int delete_client=1; int actual_fd; actual_fd=0; //We find the FD correspondig to this client @@ -227,7 +246,9 @@ void unicast_close_connection(unicast_parameters_t *unicast_vars, fds_t *fds, in log_message(MSG_DEBUG,"Unicast : We close the connection\n"); //We delete the client - unicast_del_client(unicast_vars, unicast_vars->fd_info[actual_fd].client, channels); + if(delete_client) + unicast_del_client(unicast_vars, unicast_vars->fd_info[actual_fd].client, channels); + /** @todo : deal with the keep alive, we can close the control connection but keep the client*/ //We move the last fd to the actual/deleted one, and decrease the number of fds by one fds->pfds[actual_fd].fd = fds->pfds[fds->pfdsnum-1].fd; fds->pfds[actual_fd].events = fds->pfds[fds->pfdsnum-1].events; @@ -259,6 +280,197 @@ void unicast_close_connection(unicast_parameters_t *unicast_vars, fds_t *fds, in +/** @brief Handle an "event" on the unicast file descriptors +* If the event is on an already open client connection, it handle the message +* If the event is on the master connection, it accepts the new connection +* If the event is on a channel specific socket, it accepts the new connection and starts streaming +* +*/ +int unicast_handle_fd_event(unicast_parameters_t *unicast_vars, fds_t *fds, mumudvb_channel_t *channels, int number_of_channels) +{ + int iRet; + //We look what happened for which connection + int actual_fd; + + + for(actual_fd=1;actual_fdpfdsnum;actual_fd++) + { + iRet=0; + if((fds->pfds[actual_fd].revents&POLLHUP)&&((unicast_vars->fd_info[actual_fd].type==UNICAST_CLIENT_HTTP)||(unicast_vars->fd_info[actual_fd].type==UNICAST_CLIENT_RTSP))) + { + /** @todo RTSP : no keep alive */ + log_message(MSG_DEBUG,"Unicast : We've got a POLLHUP. Actual_fd %d socket %d we close the connection \n", actual_fd, fds->pfds[actual_fd].fd ); + unicast_close_connection(unicast_vars,fds,fds->pfds[actual_fd].fd,channels); + //We check if we hage to parse fds->pfds[actual_fd].revents (the last fd moved to the actual one) + if(fds->pfds[actual_fd].revents) + actual_fd--;//Yes, we force the loop to see it + } + if((fds->pfds[actual_fd].revents&POLLIN)||(fds->pfds[actual_fd].revents&POLLPRI)) + { + if((unicast_vars->fd_info[actual_fd].type==UNICAST_MASTER_HTTP)|| + (unicast_vars->fd_info[actual_fd].type==UNICAST_LISTEN_CHANNEL)|| + (unicast_vars->fd_info[actual_fd].type==UNICAST_MASTER_RTSP)) + { + //Event on the master connection or listenin channel + //New connection, we accept the connection + if(unicast_vars->fd_info[actual_fd].type==UNICAST_MASTER_RTSP) + log_message(MSG_DEBUG,"Unicast : New RTSP client\n"); + else + log_message(MSG_DEBUG,"Unicast : New HTTP client\n"); + int tempSocket; + unicast_client_t *tempClient; + //we accept the incoming connection + if(unicast_vars->fd_info[actual_fd].type==UNICAST_MASTER_RTSP) + tempClient=unicast_accept_connection(unicast_vars, fds->pfds[actual_fd].fd,CLIENT_HTTP); + else + tempClient=unicast_accept_connection(unicast_vars, fds->pfds[actual_fd].fd,CLIENT_RTSP); + + if(tempClient!=NULL) + { + tempSocket=tempClient->Socket; + fds->pfdsnum++; + fds->pfds=realloc(fds->pfds,(fds->pfdsnum+1)*sizeof(struct pollfd)); + if (fds->pfds==NULL) + { + log_message(MSG_ERROR,"Problem with realloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); + Interrupted=ERROR_MEMORY<<8; + return -1; + } + //We poll the new socket + fds->pfds[fds->pfdsnum-1].fd = tempSocket; + fds->pfds[fds->pfdsnum-1].events = POLLIN | POLLPRI | POLLHUP; //We also poll the deconnections + fds->pfds[fds->pfdsnum-1].revents = 0; + fds->pfds[fds->pfdsnum].fd = 0; + fds->pfds[fds->pfdsnum].events = POLLIN | POLLPRI; + fds->pfds[fds->pfdsnum].revents = 0; + + //Information about the descriptor + unicast_vars->fd_info=realloc(unicast_vars->fd_info,(fds->pfdsnum)*sizeof(unicast_fd_info_t)); + if (unicast_vars->fd_info==NULL) + { + log_message(MSG_ERROR,"Problem with realloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); + Interrupted=ERROR_MEMORY<<8; + return -1; + } + //client connection + if(unicast_vars->fd_info[actual_fd].type==UNICAST_MASTER_RTSP) + unicast_vars->fd_info[fds->pfdsnum-1].type=UNICAST_CLIENT_RTSP; + else + unicast_vars->fd_info[fds->pfdsnum-1].type=UNICAST_CLIENT_HTTP; + unicast_vars->fd_info[fds->pfdsnum-1].channel=-1; + unicast_vars->fd_info[fds->pfdsnum-1].client=tempClient; + + + log_message(MSG_DEBUG,"Unicast : Number of clients : %d\n", unicast_vars->client_number); + + if(unicast_vars->fd_info[actual_fd].type==UNICAST_LISTEN_CHANNEL) + { + //Event on a channel connection, we open a new socket for this client and + //we store the wanted channel for when we will get the GET + log_message(MSG_DEBUG,"Unicast : Connection on a channel socket the client will get the channel %d\n", unicast_vars->fd_info[actual_fd].channel); + tempClient->askedChannel=unicast_vars->fd_info[actual_fd].channel; + } + } + } + else if(unicast_vars->fd_info[actual_fd].type==UNICAST_CLIENT_HTTP) + { + //Event on a client connectio i.e. the client asked something + log_message(MSG_FLOOD,"Unicast : New HTTP message for socket %d\n", fds->pfds[actual_fd].fd); + iRet=unicast_handle_http_message(unicast_vars,unicast_vars->fd_info[actual_fd].client, channels, number_of_channels, fds); + if (iRet==CLOSE_CONNECTION ) //iRet==-2 --> 0 received data or error, we close the connection + { + unicast_close_connection(unicast_vars,fds,fds->pfds[actual_fd].fd,channels); + //We check if we hage to parse fds->pfds[actual_fd].revents (the last fd moved to the actual one) + if(fds->pfds[actual_fd].revents) + actual_fd--;//Yes, we force the loop to see it again + } + } + else if(unicast_vars->fd_info[actual_fd].type==UNICAST_CLIENT_RTSP) + { + //Event on a client connectio i.e. the client asked something + log_message(MSG_FLOOD,"Unicast : New RTSP message for socket %d\n", fds->pfds[actual_fd].fd); + iRet=unicast_handle_rtsp_message(unicast_vars,unicast_vars->fd_info[actual_fd].client, channels, number_of_channels, fds); + if (iRet==CLOSE_CONNECTION ) //iRet==CLOSE_CONNECTION --> 0 received data or error, we close the connection + { + unicast_close_connection(unicast_vars,fds,fds->pfds[actual_fd].fd,channels); + //We check if we hage to parse fds->pfds[actual_fd].revents (the last fd moved to the actual one) + if(fds->pfds[actual_fd].revents) + actual_fd--;//Yes, we force the loop to see it again + } + } + else + { + log_message(MSG_WARN,"Unicast : File descriptor with bad type, please contact\n Debug information : actual_fd %d unicast_vars->fd_info[actual_fd].type %d\n", + actual_fd, unicast_vars->fd_info[actual_fd].type); + } + } + } + return 0; + +} + +/** @brief Accept an incoming connection +* +* +* @param unicast_vars the unicast parameters +* @param socketIn the socket on wich the connection was made +*/ +unicast_client_t *unicast_accept_connection(unicast_parameters_t *unicast_vars, int socketIn, int client_type) +{ + + unsigned int l; + int tempSocket; + unicast_client_t *tempClient; + struct sockaddr_in tempSocketAddrIn; + + l = sizeof(struct sockaddr); + tempSocket = accept(socketIn, (struct sockaddr *) &tempSocketAddrIn, &l); + if (tempSocket < 0 ) + { + log_message(MSG_WARN,"Unicast : Error when accepting the incoming connection : %s\n", strerror(errno)); + return NULL; + } + struct sockaddr_in tempSocketAddr; + l = sizeof(struct sockaddr); + getsockname(tempSocket, (struct sockaddr *) &tempSocketAddr, &l); + log_message(MSG_DETAIL,"Unicast : New connection from %s:%d to %s:%d \n",inet_ntoa(tempSocketAddrIn.sin_addr), tempSocketAddrIn.sin_port,inet_ntoa(tempSocketAddr.sin_addr), tempSocketAddr.sin_port); + + //Now we set this socket to be non blocking because we poll it + int flags; + flags = fcntl(tempSocket, F_GETFL, 0); + flags |= O_NONBLOCK; + if (fcntl(tempSocket, F_SETFL, flags) < 0) + { + log_message(MSG_ERROR,"Set non blocking failed : %s\n",strerror(errno)); + return NULL; + } + + /* if the maximum number of clients is reached, raise a temporary error*/ + if((unicast_vars->max_clients>0)&&(unicast_vars->client_number>=unicast_vars->max_clients)) + { + int iRet; + log_message(MSG_INFO,"Unicast : Too many clients connected, we raise an error to %s\n", inet_ntoa(tempSocketAddrIn.sin_addr)); + if(client_type==CLIENT_HTTP) + iRet=write(tempSocket,HTTP_503_REPLY, strlen(HTTP_503_REPLY)); //iRet is to make the copiler happy we will close the connection anyways + else + iRet=write(tempSocket,RTSP_503_REPLY, strlen(RTSP_503_REPLY)); + close(tempSocket); + return NULL; + } + + tempClient=unicast_add_client(unicast_vars, tempSocketAddrIn, tempSocket, client_type); + if( tempClient == NULL) + { + //We cannot create the client, we close the socket cleanly + close(tempSocket); + return NULL; + } + + return tempClient; + +} + + //////////////////////// // HTTP/RTSP Toolbox // diff --git a/src/unicast_common.h b/src/unicast_common.h index 00ac292c..457ac42f 100644 --- a/src/unicast_common.h +++ b/src/unicast_common.h @@ -31,7 +31,7 @@ #include "mumudvb.h" #include "unicast_queue.h" - +#include "unicast.h" #define REPLY_HEADER 0 #define REPLY_BODY 1 @@ -53,5 +53,10 @@ int unicast_reply_write(unicast_reply_t *reply, const char* msg, ...); int unicast_reply_send(unicast_reply_t *reply, int socket, int code, const char* content_type); void unicast_close_connection(unicast_parameters_t *unicast_vars, fds_t *fds, int Socket, mumudvb_channel_t *channels); +unicast_client_t *unicast_accept_connection(unicast_parameters_t *unicast_vars, int socketIn, int client_type); +unicast_client_t *unicast_add_client(unicast_parameters_t *unicast_vars, struct sockaddr_in SocketAddr, int Socket, int client_type); + + + #endif diff --git a/src/unicast_http.c b/src/unicast_http.c index 806aa496..1dbe57b7 100644 --- a/src/unicast_http.c +++ b/src/unicast_http.c @@ -68,10 +68,9 @@ Todo list extern int Interrupted; //from unicast_client.c -unicast_client_t *unicast_add_client(unicast_parameters_t *unicast_vars, struct sockaddr_in SocketAddr, int Socket, int client_type); int channel_add_unicast_client(unicast_client_t *client,mumudvb_channel_t *channel); -unicast_client_t *unicast_accept_http_connection(unicast_parameters_t *unicast_vars, int socketIn); + int @@ -87,174 +86,10 @@ unicast_send_signal_power_js (int Socket, fds_t *fds); int unicast_send_channel_traffic_js (int number_of_channels, mumudvb_channel_t *channels, int Socket); -int unicast_handle_http_message(unicast_parameters_t *unicast_vars, unicast_client_t *client, mumudvb_channel_t *channels, int num_of_channels, fds_t *fds); - - -/** @brief Handle an "event" on the unicast file descriptors -* If the event is on an already open client connection, it handle the message -* If the event is on the master connection, it accepts the new connection -* If the event is on a channel specific socket, it accepts the new connection and starts streaming -* -*/ -int unicast_handle_fd_event(unicast_parameters_t *unicast_vars, fds_t *fds, mumudvb_channel_t *channels, int number_of_channels) -{ - int iRet; - //We look what happened for which connection - int actual_fd; - for(actual_fd=1;actual_fdpfdsnum;actual_fd++) - { - iRet=0; - if((fds->pfds[actual_fd].revents&POLLHUP)&&(unicast_vars->fd_info[actual_fd].type==UNICAST_CLIENT)) - { - log_message(MSG_DEBUG,"Unicast : We've got a POLLHUP. Actual_fd %d socket %d we close the connection \n", actual_fd, fds->pfds[actual_fd].fd ); - unicast_close_connection(unicast_vars,fds,fds->pfds[actual_fd].fd,channels); - //We check if we hage to parse fds->pfds[actual_fd].revents (the last fd moved to the actual one) - if(fds->pfds[actual_fd].revents) - actual_fd--;//Yes, we force the loop to see it - } - if((fds->pfds[actual_fd].revents&POLLIN)||(fds->pfds[actual_fd].revents&POLLPRI)) - { - if((unicast_vars->fd_info[actual_fd].type==UNICAST_MASTER_HTTP)|| - (unicast_vars->fd_info[actual_fd].type==UNICAST_LISTEN_CHANNEL)) - { - //Event on the master connection or listenin channel - //New connection, we accept the connection - log_message(MSG_DEBUG,"Unicast : New client\n"); - int tempSocket; - unicast_client_t *tempClient; - //we accept the incoming connection - tempClient=unicast_accept_http_connection(unicast_vars, fds->pfds[actual_fd].fd); - - if(tempClient!=NULL) - { - tempSocket=tempClient->Socket; - fds->pfdsnum++; - fds->pfds=realloc(fds->pfds,(fds->pfdsnum+1)*sizeof(struct pollfd)); - if (fds->pfds==NULL) - { - log_message(MSG_ERROR,"Problem with realloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); - Interrupted=ERROR_MEMORY<<8; - return -1; - } - //We poll the new socket - fds->pfds[fds->pfdsnum-1].fd = tempSocket; - fds->pfds[fds->pfdsnum-1].events = POLLIN | POLLPRI | POLLHUP; //We also poll the deconnections - fds->pfds[fds->pfdsnum-1].revents = 0; - fds->pfds[fds->pfdsnum].fd = 0; - fds->pfds[fds->pfdsnum].events = POLLIN | POLLPRI; - fds->pfds[fds->pfdsnum].revents = 0; - - //Information about the descriptor - unicast_vars->fd_info=realloc(unicast_vars->fd_info,(fds->pfdsnum)*sizeof(unicast_fd_info_t)); - if (unicast_vars->fd_info==NULL) - { - log_message(MSG_ERROR,"Problem with realloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); - Interrupted=ERROR_MEMORY<<8; - return -1; - } - //client connection - unicast_vars->fd_info[fds->pfdsnum-1].type=UNICAST_CLIENT; - unicast_vars->fd_info[fds->pfdsnum-1].channel=-1; - unicast_vars->fd_info[fds->pfdsnum-1].client=tempClient; - log_message(MSG_DEBUG,"Unicast : Number of clients : %d\n", unicast_vars->client_number); - - if(unicast_vars->fd_info[actual_fd].type==UNICAST_LISTEN_CHANNEL) - { - //Event on a channel connection, we open a new socket for this client and - //we store the wanted channel for when we will get the GET - log_message(MSG_DEBUG,"Unicast : Connection on a channel socket the client will get the channel %d\n", unicast_vars->fd_info[actual_fd].channel); - tempClient->askedChannel=unicast_vars->fd_info[actual_fd].channel; - } - } - } - else if(unicast_vars->fd_info[actual_fd].type==UNICAST_CLIENT) - { - //Event on a client connectio i.e. the client asked something - log_message(MSG_FLOOD,"Unicast : New message for socket %d\n", fds->pfds[actual_fd].fd); - iRet=unicast_handle_http_message(unicast_vars,unicast_vars->fd_info[actual_fd].client, channels, number_of_channels, fds); - if (iRet==-2 ) //iRet==-2 --> 0 received data or error, we close the connection - { - unicast_close_connection(unicast_vars,fds,fds->pfds[actual_fd].fd,channels); - //We check if we hage to parse fds->pfds[actual_fd].revents (the last fd moved to the actual one) - if(fds->pfds[actual_fd].revents) - actual_fd--;//Yes, we force the loop to see it again - } - } - else - { - log_message(MSG_WARN,"Unicast : File descriptor with bad type, please contact\n Debug information : actual_fd %d unicast_vars->fd_info[actual_fd].type %d\n", - actual_fd, unicast_vars->fd_info[actual_fd].type); - } - } - } - return 0; - -} - - - - -/** @brief Accept an incoming connection -* -* -* @param unicast_vars the unicast parameters -* @param socketIn the socket on wich the connection was made -*/ -unicast_client_t *unicast_accept_http_connection(unicast_parameters_t *unicast_vars, int socketIn) -{ - - unsigned int l; - int tempSocket; - unicast_client_t *tempClient; - struct sockaddr_in tempSocketAddrIn; - - l = sizeof(struct sockaddr); - tempSocket = accept(socketIn, (struct sockaddr *) &tempSocketAddrIn, &l); - if (tempSocket < 0 ) - { - log_message(MSG_WARN,"Unicast : Error when accepting the incoming connection : %s\n", strerror(errno)); - return NULL; - } - struct sockaddr_in tempSocketAddr; - l = sizeof(struct sockaddr); - getsockname(tempSocket, (struct sockaddr *) &tempSocketAddr, &l); - log_message(MSG_DETAIL,"Unicast : New connection from %s:%d to %s:%d \n",inet_ntoa(tempSocketAddrIn.sin_addr), tempSocketAddrIn.sin_port,inet_ntoa(tempSocketAddr.sin_addr), tempSocketAddr.sin_port); - - //Now we set this socket to be non blocking because we poll it - int flags; - flags = fcntl(tempSocket, F_GETFL, 0); - flags |= O_NONBLOCK; - if (fcntl(tempSocket, F_SETFL, flags) < 0) - { - log_message(MSG_ERROR,"Set non blocking failed : %s\n",strerror(errno)); - return NULL; - } - - /* if the maximum number of clients is reached, raise a temporary error*/ - if((unicast_vars->max_clients>0)&&(unicast_vars->client_number>=unicast_vars->max_clients)) - { - int iRet; - log_message(MSG_INFO,"Unicast : Too many clients connected, we raise an error to %s\n", inet_ntoa(tempSocketAddrIn.sin_addr)); - iRet=write(tempSocket,HTTP_503_REPLY, strlen(HTTP_503_REPLY)); //iRet is to make the copiler happy we will close the connection anyways - close(tempSocket); - return NULL; - } - - tempClient=unicast_add_client(unicast_vars, tempSocketAddrIn, tempSocket, CLIENT_HTTP); - if( tempClient == NULL) - { - //We cannot create the client, we close the socket cleanly - close(tempSocket); - return NULL; - } - - return tempClient; - -} @@ -306,7 +141,7 @@ int unicast_handle_http_message(unicast_parameters_t *unicast_vars, unicast_clie return -1; } if(received_len==0) - return -2; //To say to the main program to close the connection + return CLOSE_CONNECTION; //To say to the main program to close the connection /***************** Now we parse the message to see if something was asked *****************/ client->buffer[client->buffersize]='\0'; //For avoiding strlen to look too far (other option is to use the gnu extension strnlen) @@ -348,7 +183,7 @@ int unicast_handle_http_message(unicast_parameters_t *unicast_vars, unicast_clie { log_message(MSG_INFO,"Unicast : A channel (%d) is already streamed to this client, it shouldn't ask for a new one without closing the connection, error 501\n",client->channel); iRet=write(client->Socket,HTTP_501_REPLY, strlen(HTTP_501_REPLY)); //iRet is to make the copiler happy we will close the connection anyways - return -2; //to delete the client + return CLOSE_CONNECTION; //to delete the client } pos+=strlen("/bynumber/"); @@ -376,7 +211,7 @@ int unicast_handle_http_message(unicast_parameters_t *unicast_vars, unicast_clie { log_message(MSG_INFO,"Unicast : A channel (%d) is already streamed to this client, it shouldn't ask for a new one without closing the connection, error 501\n",client->channel); iRet=write(client->Socket,HTTP_501_REPLY, strlen(HTTP_501_REPLY)); //iRet is to make the copiler happy we will close the connection anyways - return -2; //to delete the client + return CLOSE_CONNECTION; //to delete the client } pos+=strlen("/bytsid/"); substring = strtok (client->buffer+pos, " "); @@ -409,7 +244,7 @@ int unicast_handle_http_message(unicast_parameters_t *unicast_vars, unicast_clie { log_message(MSG_INFO,"Unicast : A channel is already streamed to this client, it shouldn't ask for a new one without closing the connection, error 501\n"); iRet=write(client->Socket,HTTP_501_REPLY, strlen(HTTP_501_REPLY));//iRet is to make the copiler happy we will close the connection anyways - return -2; //to delete the client + return CLOSE_CONNECTION; //to delete the client } pos+=strlen("/byname/"); log_message(MSG_DEBUG,"Unicast : Channel by number\n"); @@ -438,52 +273,52 @@ int unicast_handle_http_message(unicast_parameters_t *unicast_vars, unicast_clie substring=NULL; log_message(MSG_DETAIL,"Channel list\n"); unicast_send_streamed_channels_list (number_of_channels, channels, client->Socket, substring); - return -2; //We close the connection afterwards + return CLOSE_CONNECTION; //We close the connection afterwards } //playlist, m3u else if(strstr(client->buffer +pos ,"/playlist.m3u ")==(client->buffer +pos)) { log_message(MSG_DETAIL,"play list\n"); - unicast_send_play_list_unicast (number_of_channels, channels, client->Socket, unicast_vars->portOut, 0 ); - return -2; //We close the connection afterwards + unicast_send_play_list_unicast (number_of_channels, channels, client->Socket, unicast_vars->http_portOut, 0 ); + return CLOSE_CONNECTION; //We close the connection afterwards } //playlist, m3u else if(strstr(client->buffer +pos ,"/playlist_port.m3u ")==(client->buffer +pos)) { log_message(MSG_DETAIL,"play list\n"); - unicast_send_play_list_unicast (number_of_channels, channels, client->Socket, unicast_vars->portOut, 1 ); - return -2; //We close the connection afterwards + unicast_send_play_list_unicast (number_of_channels, channels, client->Socket, unicast_vars->http_portOut, 1 ); + return CLOSE_CONNECTION; //We close the connection afterwards } else if(strstr(client->buffer +pos ,"/playlist_multicast.m3u ")==(client->buffer +pos)) { log_message(MSG_DETAIL,"play list\n"); unicast_send_play_list_multicast (number_of_channels, channels, client->Socket, 0 ); - return -2; //We close the connection afterwards + return CLOSE_CONNECTION; //We close the connection afterwards } else if(strstr(client->buffer +pos ,"/playlist_multicast_vlc.m3u ")==(client->buffer +pos)) { log_message(MSG_DETAIL,"play list\n"); unicast_send_play_list_multicast (number_of_channels, channels, client->Socket, 1 ); - return -2; //We close the connection afterwards + return CLOSE_CONNECTION; //We close the connection afterwards } //statistics, text version else if(strstr(client->buffer +pos ,"/channels_list.json ")==(client->buffer +pos)) { log_message(MSG_DETAIL,"Channel list Json\n"); unicast_send_streamed_channels_list_js (number_of_channels, channels, client->Socket); - return -2; //We close the connection afterwards + return CLOSE_CONNECTION; //We close the connection afterwards } else if(strstr(client->buffer +pos ,"/monitor/signal_power.json ")==(client->buffer +pos)) { log_message(MSG_DETAIL,"Signal power json\n"); unicast_send_signal_power_js(client->Socket, fds); - return -2; //We close the connection afterwards + return CLOSE_CONNECTION; //We close the connection afterwards } else if(strstr(client->buffer +pos ,"/monitor/channels_traffic.json ")==(client->buffer +pos)) { log_message(MSG_DETAIL,"Channel traffic json\n"); unicast_send_channel_traffic_js(number_of_channels, channels, client->Socket); - return -2; //We close the connection afterwards + return CLOSE_CONNECTION; //We close the connection afterwards } //Not implemented path --> 404 else @@ -496,15 +331,15 @@ int unicast_handle_http_message(unicast_parameters_t *unicast_vars, unicast_clie reply = unicast_reply_init(); if (NULL == reply) { log_message(MSG_INFO,"Unicast : Error when creating the HTTP reply\n"); - return -2; + return CLOSE_CONNECTION; } unicast_reply_write(reply, HTTP_404_REPLY_HTML, VERSION); unicast_reply_send(reply, client->Socket, 404, "text/html"); if (0 != unicast_reply_free(reply)) { log_message(MSG_INFO,"Unicast : Error when releasing the HTTP reply after sendinf it\n"); - return -2; + return CLOSE_CONNECTION; } - return -2; //to delete the client + return CLOSE_CONNECTION; //to delete the client } //We have found a channel, we add the client if(requested_channel) @@ -512,7 +347,7 @@ int unicast_handle_http_message(unicast_parameters_t *unicast_vars, unicast_clie if(!channel_add_unicast_client(client,&channels[requested_channel-1])) client->channel=requested_channel-1; else - return -2; + return CLOSE_CONNECTION; } } @@ -523,7 +358,7 @@ int unicast_handle_http_message(unicast_parameters_t *unicast_vars, unicast_clie { log_message(MSG_INFO,"Unicast : Unhandled HTTP method : \"%s\", error 501\n", strtok (client->buffer+pos, " ")); iRet=write(client->Socket,HTTP_501_REPLY, strlen(HTTP_501_REPLY));//iRet is to make the copiler happy we will close the connection anyways - return -2; //to delete the client + return CLOSE_CONNECTION; //to delete the client } else { diff --git a/src/unicast_http.h b/src/unicast_http.h index c75f5860..7f6953b4 100644 --- a/src/unicast_http.h +++ b/src/unicast_http.h @@ -76,15 +76,15 @@ "\r\n" -int unicast_handle_fd_event(unicast_parameters_t *unicast_vars, fds_t *fds, mumudvb_channel_t *channels, int number_of_channels); + int unicast_del_client(unicast_parameters_t *unicast_vars, unicast_client_t *client, mumudvb_channel_t *channels); int channel_add_unicast_client(unicast_client_t *client,mumudvb_channel_t *channel); -void unicast_freeing(unicast_parameters_t *unicast_vars, mumudvb_channel_t *channels); -void unicast_data_send(mumudvb_channel_t *actual_channel, mumudvb_channel_t *channels, fds_t *fds, unicast_parameters_t *unicast_vars); + +int unicast_handle_http_message(unicast_parameters_t *unicast_vars, unicast_client_t *client, mumudvb_channel_t *channels, int num_of_channels, fds_t *fds); diff --git a/src/unicast_queue.h b/src/unicast_queue.h index 21f8005e..803ee3be 100644 --- a/src/unicast_queue.h +++ b/src/unicast_queue.h @@ -60,13 +60,4 @@ void unicast_queue_clear(unicast_queue_header_t *header); - - - - - - - - - #endif \ No newline at end of file diff --git a/src/unicast_rtsp.c b/src/unicast_rtsp.c new file mode 100644 index 00000000..84bddbf1 --- /dev/null +++ b/src/unicast_rtsp.c @@ -0,0 +1,77 @@ +/* +* MuMuDVB - Stream a DVB transport stream. +* +* (C) 2010 Brice DUBOST +* +* The latest version can be found at http://mumudvb.braice.net +* +* Copyright notice: +* +* 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/** @file +* @brief File for RTSP unicast +* @author Brice DUBOST +* @date 2010 +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "unicast_http.h" +#include "unicast_queue.h" +#include "mumudvb.h" +#include "errors.h" +#include "log.h" +#include "unicast.h" +#include "unicast_common.h" + +extern int Interrupted; + + +/** @todo handle non keepalive clients, and auto disconnect to old clients without streaming */ + + + +/** @brief Deal with an incoming message on the unicast client connection +* This function will store and answer the RTSP requests +* +* +* @param unicast_vars the unicast parameters +* @param client The client from which the message was received +* @param channels the channel array +* @param number_of_channels quite explicit ... +*/ +int unicast_handle_rtsp_message(unicast_parameters_t *unicast_vars, unicast_client_t *client, mumudvb_channel_t *channels, int number_of_channels, fds_t *fds) +{ + +} diff --git a/src/unicast_rtsp.h b/src/unicast_rtsp.h index 4ae4ca5e..4ae667e4 100644 --- a/src/unicast_rtsp.h +++ b/src/unicast_rtsp.h @@ -34,8 +34,10 @@ #include "unicast.h" +#define RTSP_503_REPLY "RTSP/1.0 503 Too many clients\r\n"\ + "\r\n" - +int unicast_handle_rtsp_message(unicast_parameters_t *unicast_vars, unicast_client_t *client, mumudvb_channel_t *channels, int number_of_channels, fds_t *fds); #endif From 38af806cca83f8ec326221e2848782e5fed55d78 Mon Sep 17 00:00:00 2001 From: MuMuDVB Date: Sun, 17 Jan 2010 11:28:33 +0100 Subject: [PATCH 04/28] Unicast: other RTSP standard responses --- src/unicast_rtsp.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/unicast_rtsp.h b/src/unicast_rtsp.h index 4ae667e4..6bdf71c0 100644 --- a/src/unicast_rtsp.h +++ b/src/unicast_rtsp.h @@ -37,6 +37,12 @@ #define RTSP_503_REPLY "RTSP/1.0 503 Too many clients\r\n"\ "\r\n" +#define RTSP_454_REPLY "RTSP/1.0 454 Session Not Found\r\n"\ + "\r\n" + +#define RTSP_461_REPLY "RTSP/1.0 461 Unsupported transport\r\n"\ + "\r\n" + int unicast_handle_rtsp_message(unicast_parameters_t *unicast_vars, unicast_client_t *client, mumudvb_channel_t *channels, int number_of_channels, fds_t *fds); From f7c61bc28f9f6e500a97ada146f72da47dd5e10d Mon Sep 17 00:00:00 2001 From: Brice DUBOST Date: Wed, 20 Jan 2010 23:31:45 +0100 Subject: [PATCH 05/28] Unicast : merge of the RTSP code To be tested ... --- src/mumudvb.c | 15 +- src/network.c | 40 +++++ src/network.h | 2 + src/unicast.h | 12 ++ src/unicast_clients.c | 23 ++- src/unicast_common.c | 55 ++++++ src/unicast_common.h | 2 + src/unicast_http.c | 38 +--- src/unicast_http.h | 6 - src/unicast_queue.c | 55 ++++-- src/unicast_queue.h | 4 - src/unicast_rtsp.c | 404 +++++++++++++++++++++++++++++++++++++++++- src/unicast_rtsp.h | 7 + 13 files changed, 587 insertions(+), 76 deletions(-) diff --git a/src/mumudvb.c b/src/mumudvb.c index 1b13d117..90c865bf 100644 --- a/src/mumudvb.c +++ b/src/mumudvb.c @@ -858,10 +858,10 @@ int } } #endif - if(multicast_vars.rtp_header) + if(multicast_vars.rtp_header && !unicast_vars.unicast_rtsp_enable) { multicast_vars.rtp_header=0; - log_message( MSG_INFO, "NO Multicast, RTP Header is desactivated.\n"); + log_message( MSG_INFO, "NO Multicast, NO RTSP, RTP Header is desactivated.\n"); } if(sap_vars.sap==OPTION_ON) { @@ -1084,7 +1084,7 @@ int /*****************************************************/ //Initialisation of the channels for RTP - if(multicast_vars.rtp_header) + if(multicast_vars.rtp_header || unicast_vars.unicast_rtsp_enable) for (curr_channel = 0; curr_channel < chan_and_pids.number_of_channels; curr_channel++) init_rtp_header(&chan_and_pids.channels[curr_channel]); @@ -1533,8 +1533,8 @@ int chan_and_pids.channels[curr_channel].nb_bytes += TS_PACKET_SIZE; //The buffer is full, we send it - if ((!multicast_vars.rtp_header && ((chan_and_pids.channels[curr_channel].nb_bytes + TS_PACKET_SIZE) > MAX_UDP_SIZE)) - ||(multicast_vars.rtp_header && ((chan_and_pids.channels[curr_channel].nb_bytes + RTP_HEADER_LEN + TS_PACKET_SIZE) > MAX_UDP_SIZE))) + if ((!(multicast_vars.rtp_header ||unicast_vars.unicast_rtsp_enable) && ((chan_and_pids.channels[curr_channel].nb_bytes + TS_PACKET_SIZE) > MAX_UDP_SIZE)) + ||((multicast_vars.rtp_header ||unicast_vars.unicast_rtsp_enable) && ((chan_and_pids.channels[curr_channel].nb_bytes + RTP_HEADER_LEN + TS_PACKET_SIZE) > MAX_UDP_SIZE))) { //For bandwith measurement (traffic) chan_and_pids.channels[curr_channel].sent_data+=chan_and_pids.channels[curr_channel].nb_bytes; @@ -1566,14 +1566,15 @@ int (NULL != chan_and_pids.channels[curr_channel].transcode_options.streaming_type && STREAMING_TYPE_MPEGTS != *chan_and_pids.channels[curr_channel].transcode_options.streaming_type)) #endif + if( multicast_vars.rtp_header || unicast_vars.unicast_rtsp_enable) + rtp_update_sequence_number(&chan_and_pids.channels[curr_channel]); /********** MULTICAST *************/ - //if the multicast TTL is set to 0 we don't send the multicast packets + //if the multicast TTL is set to 0 we don't send the multicast packets if(multicast_vars.multicast) { if(multicast_vars.rtp_header) { /****** RTP *******/ - rtp_update_sequence_number(&chan_and_pids.channels[curr_channel]); sendudp (chan_and_pids.channels[curr_channel].socketOut, &chan_and_pids.channels[curr_channel].sOut, chan_and_pids.channels[curr_channel].buf_with_rtp_header, diff --git a/src/network.c b/src/network.c index f04aa0c1..a29c7455 100644 --- a/src/network.c +++ b/src/network.c @@ -106,6 +106,46 @@ makesocket (char *szAddr, unsigned short port, int TTL, return iSocket; } + +/** @brief create a sender socket. + * + * Create a socket for sending data, the socket is udp, with the option REUSE_ADDR set to 1 + */ +int +makeUDPsocket (char *szAddr, unsigned short port, + struct sockaddr_in *sSockAddr) +{ + int iRet, iLoop = 1; + struct sockaddr_in sin; + + int iSocket = socket (AF_INET, SOCK_DGRAM, 0); + + if (iSocket < 0) + { + log_message( MSG_WARN, "socket() failed : %s\n",strerror(errno)); + Interrupted=ERROR_NETWORK<<8; + } + + sSockAddr->sin_family = sin.sin_family = AF_INET; + sSockAddr->sin_port = sin.sin_port = htons (port); + iRet=inet_aton (szAddr,&sSockAddr->sin_addr); + if (iRet == 0) + { + log_message( MSG_ERROR,"inet_aton failed : %s\n", strerror(errno)); + Interrupted=ERROR_NETWORK<<8; + } + + iRet = setsockopt (iSocket, SOL_SOCKET, SO_REUSEADDR, &iLoop, sizeof (int)); + if (iRet < 0) + { + log_message( MSG_ERROR,"setsockopt SO_REUSEADDR failed : %s\n",strerror(errno)); + Interrupted=ERROR_NETWORK<<8; + } + + return iSocket; +} + + /** @brief create a receiver socket, i.e. join the multicast group. *@todo document */ diff --git a/src/network.h b/src/network.h index 9c7bdf11..68102705 100644 --- a/src/network.h +++ b/src/network.h @@ -48,6 +48,8 @@ int makeclientsocket (char *szAddr, unsigned short port, int TTL, struct sockadd int sendudp (int fd, struct sockaddr_in *sSockAddr, unsigned char *data, int len); int makesocket (char *szAddr, unsigned short port, int TTL, struct sockaddr_in *sSockAddr); int makeTCPclientsocket (char *szAddr, unsigned short port, struct sockaddr_in *sSockAddr); +int makeUDPsocket (char *szAddr, unsigned short port, struct sockaddr_in *sSockAddr); + #endif diff --git a/src/unicast.h b/src/unicast.h index 1bd15d1e..6d567106 100644 --- a/src/unicast.h +++ b/src/unicast.h @@ -70,8 +70,20 @@ typedef struct unicast_client_t{ struct sockaddr_in SocketAddr; /**HTTP/Contol socket*/ int Socket; + /** Socket closed (RTSP no keep alive)*/ int Control_socket_closed; + /**RTSP ports*/ + int rtsp_client_port; + int rtsp_server_port; + char rtsp_client_ip[20]; + /**RTSP socket*/ + int rtsp_Socket; + /**RTSP socket*/ + struct sockaddr_in rtsp_SocketAddr; + /**Session number*/ + char session[16]; + /**Reception buffer*/ char *buffer; /**Size of the buffer*/ diff --git a/src/unicast_clients.c b/src/unicast_clients.c index bde4fd30..e4084ac0 100644 --- a/src/unicast_clients.c +++ b/src/unicast_clients.c @@ -111,7 +111,7 @@ unicast_client_t *unicast_add_client(unicast_parameters_t *unicast_vars, struct client->queue.first=NULL; client->queue.last=NULL; client->client_type=client_type; - + client->rtsp_Socket=0; unicast_vars->client_number++; return client; @@ -133,11 +133,17 @@ int unicast_del_client(unicast_parameters_t *unicast_vars, unicast_client_t *cli unicast_client_t *prev_client,*next_client; log_message(MSG_DETAIL,"Unicast : We delete the client %s:%d, socket %d\n",inet_ntoa(client->SocketAddr.sin_addr), client->SocketAddr.sin_port, client->Socket); + if(client->client_type==CLIENT_RTSP && client->rtsp_Socket) + log_message(MSG_DETAIL,"Unicast : RTSP %s:%d, Unicast socket %d\n",inet_ntoa(client->rtsp_SocketAddr.sin_addr), client->rtsp_SocketAddr.sin_port, client->rtsp_Socket); if (client->Socket >= 0) { close(client->Socket); } + if (client->rtsp_Socket >= 0) + { + close(client->rtsp_Socket); + } prev_client=client->prev; next_client=client->next; @@ -197,11 +203,18 @@ int channel_add_unicast_client(unicast_client_t *client,mumudvb_channel_t *chann log_message(MSG_INFO,"Unicast : We add the client %s:%d to the channel \"%s\"\n",inet_ntoa(client->SocketAddr.sin_addr), client->SocketAddr.sin_port,channel->name); - iRet=write(client->Socket,HTTP_OK_REPLY, strlen(HTTP_OK_REPLY)); - if(iRet!=strlen(HTTP_OK_REPLY)) + if(client->client_type==CLIENT_HTTP) + { + iRet=write(client->Socket,HTTP_OK_REPLY, strlen(HTTP_OK_REPLY)); + if(iRet!=strlen(HTTP_OK_REPLY)) + { + log_message(MSG_INFO,"Unicast : Error when sending the HTTP reply\n"); + return -1; + } + } + if(client->client_type==CLIENT_RTSP) { - log_message(MSG_INFO,"Unicast : Error when sending the HTTP reply\n"); - return -1; + log_message(MSG_INFO,"Unicast : We add the client (RTP) sin_addr : %s: client->rtsp_SocketAddr.sin_port %d to the channel \"%s\"\n",inet_ntoa(client->rtsp_SocketAddr.sin_addr), client->rtsp_SocketAddr.sin_port,channel->name); } client->chan_next=NULL; diff --git a/src/unicast_common.c b/src/unicast_common.c index 34be8a3f..576b0c1c 100644 --- a/src/unicast_common.c +++ b/src/unicast_common.c @@ -470,8 +470,63 @@ unicast_client_t *unicast_accept_connection(unicast_parameters_t *unicast_vars, } +/** @brief Store the new message on the socket +* +*/ +int unicast_new_message(unicast_client_t *client) +{ + int received_len; + /************ auto increasing buffer to receive the message **************/ + if((client->buffersize-client->bufferpos)buffer=realloc(client->buffer,(client->buffersize + RECV_BUFFER_MULTIPLE+1)*sizeof(char)); //the +1 if for the \0 at the end + if(client->buffer==NULL) + { + log_message(MSG_ERROR,"Unicast : Problem with realloc for the client buffer : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); + client->buffersize=0; + client->bufferpos=0; + return -1; + } + memset (client->buffer+client->buffersize, 0, RECV_BUFFER_MULTIPLE*sizeof(char)); //We fill the buffer with zeros to be sure + client->buffersize += RECV_BUFFER_MULTIPLE; + } + + received_len=recv(client->Socket, client->buffer+client->bufferpos, RECV_BUFFER_MULTIPLE, 0); + if(received_len>0) + { + if(client->bufferpos==0) + log_message(MSG_DEBUG,"Unicast : beginning of buffer %c%c%c%c%c\n",client->buffer[0],client->buffer[1],client->buffer[2],client->buffer[3],client->buffer[4]); + client->bufferpos+=received_len; + log_message(MSG_FLOOD,"Unicast : We received %d, buffer len %d new buffer pos %d\n",received_len,client->buffersize, client->bufferpos); + } + if(received_len==-1) + { + log_message(MSG_ERROR,"Unicast : Problem with recv : %s\n",strerror(errno)); + return -1; + } + if(received_len==0) + return CLOSE_CONNECTION; //To say to the main program to close the connection + + /***************** Now we parse the message to see if something was asked *****************/ + client->buffer[client->buffersize]='\0'; //For avoiding strlen to look too far (other option is to use the gnu extension strnlen) + + return 0; +} + +void unicast_flush_client(unicast_client_t *client) +{ + + if(client->buffer) + { + free(client->buffer); + client->buffersize=0; + client->bufferpos=0; + } + client->buffer=NULL; + +} //////////////////////// // HTTP/RTSP Toolbox // //////////////////////// diff --git a/src/unicast_common.h b/src/unicast_common.h index 457ac42f..841ac332 100644 --- a/src/unicast_common.h +++ b/src/unicast_common.h @@ -55,6 +55,8 @@ int unicast_reply_send(unicast_reply_t *reply, int socket, int code, const char* void unicast_close_connection(unicast_parameters_t *unicast_vars, fds_t *fds, int Socket, mumudvb_channel_t *channels); unicast_client_t *unicast_accept_connection(unicast_parameters_t *unicast_vars, int socketIn, int client_type); unicast_client_t *unicast_add_client(unicast_parameters_t *unicast_vars, struct sockaddr_in SocketAddr, int Socket, int client_type); +int unicast_new_message(unicast_client_t *client); +void unicast_flush_client(unicast_client_t *client); diff --git a/src/unicast_http.c b/src/unicast_http.c index 1dbe57b7..e632bf27 100644 --- a/src/unicast_http.c +++ b/src/unicast_http.c @@ -107,44 +107,14 @@ unicast_send_channel_traffic_js (int number_of_channels, mumudvb_channel_t *chan */ int unicast_handle_http_message(unicast_parameters_t *unicast_vars, unicast_client_t *client, mumudvb_channel_t *channels, int number_of_channels, fds_t *fds) { - int received_len; (void) unicast_vars; - /************ auto increasing buffer to receive the message **************/ - if((client->buffersize-client->bufferpos)buffer=realloc(client->buffer,(client->buffersize + RECV_BUFFER_MULTIPLE+1)*sizeof(char)); //the +1 if for the \0 at the end - if(client->buffer==NULL) - { - log_message(MSG_ERROR,"Unicast : Problem with realloc for the client buffer : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); - client->buffersize=0; - client->bufferpos=0; - return -1; - } - memset (client->buffer+client->buffersize, 0, RECV_BUFFER_MULTIPLE*sizeof(char)); //We fill the buffer with zeros to be sure - client->buffersize += RECV_BUFFER_MULTIPLE; - } + int iRet; - received_len=recv(client->Socket, client->buffer+client->bufferpos, RECV_BUFFER_MULTIPLE, 0); - - if(received_len>0) - { - if(client->bufferpos==0) - log_message(MSG_DEBUG,"Unicast : beginning of buffer %c%c%c%c%c\n",client->buffer[0],client->buffer[1],client->buffer[2],client->buffer[3],client->buffer[4]); - client->bufferpos+=received_len; - log_message(MSG_FLOOD,"Unicast : We received %d, buffer len %d new buffer pos %d\n",received_len,client->buffersize, client->bufferpos); - } - - if(received_len==-1) - { - log_message(MSG_ERROR,"Unicast : Problem with recv : %s\n",strerror(errno)); - return -1; - } - if(received_len==0) - return CLOSE_CONNECTION; //To say to the main program to close the connection + iRet=unicast_new_message(client); + if(iRet) + return iRet; - /***************** Now we parse the message to see if something was asked *****************/ - client->buffer[client->buffersize]='\0'; //For avoiding strlen to look too far (other option is to use the gnu extension strnlen) //We search for the end of the HTTP request if(strlen(client->buffer)>5 && strstr(client->buffer, "\n\r\n\0")) { diff --git a/src/unicast_http.h b/src/unicast_http.h index 7f6953b4..08f7c3e4 100644 --- a/src/unicast_http.h +++ b/src/unicast_http.h @@ -76,14 +76,8 @@ "\r\n" - - int unicast_del_client(unicast_parameters_t *unicast_vars, unicast_client_t *client, mumudvb_channel_t *channels); -int channel_add_unicast_client(unicast_client_t *client,mumudvb_channel_t *channel); - - - int unicast_handle_http_message(unicast_parameters_t *unicast_vars, unicast_client_t *client, mumudvb_channel_t *channels, int num_of_channels, fds_t *fds); diff --git a/src/unicast_queue.c b/src/unicast_queue.c index c2d6ef90..b44f6c28 100644 --- a/src/unicast_queue.c +++ b/src/unicast_queue.c @@ -64,12 +64,31 @@ void unicast_data_send(mumudvb_channel_t *actual_channel, mumudvb_channel_t *cha int data_from_queue; int packets_left; struct timeval tv; + int clientsocket; + struct sockaddr_in clientsocketaddr; actual_client=actual_channel->clients; while(actual_client!=NULL) { - buffer=actual_channel->buf; - buffer_len=actual_channel->nb_bytes; + if(actual_client->client_type==CLIENT_HTTP) + { + buffer=actual_channel->buf; + buffer_len=actual_channel->nb_bytes; + clientsocket=actual_client->Socket; + clientsocketaddr=actual_client->SocketAddr; + } + else if(actual_client->client_type==CLIENT_RTSP) + { + buffer=actual_channel->buf_with_rtp_header; + buffer_len=actual_channel->nb_bytes+RTP_HEADER_LEN; + clientsocket=actual_client->rtsp_Socket; + clientsocketaddr=actual_client->rtsp_SocketAddr; + } + else + { + log_message(MSG_ERROR,"bug in the program please contact line %d file %s \n",__LINE__, __FILE__); + return; + } data_from_queue=0; if(actual_client->queue.packets_in_queue!=0) { @@ -84,8 +103,8 @@ void unicast_data_send(mumudvb_channel_t *actual_channel, mumudvb_channel_t *cha { actual_client->queue.full=1; log_message(MSG_DETAIL,"Unicast: The queue is full, we now throw away new packets for client %s:%d\n", - inet_ntoa(actual_client->SocketAddr.sin_addr), - actual_client->SocketAddr.sin_port); + inet_ntoa(clientsocketaddr.sin_addr), + clientsocketaddr.sin_port); } } buffer=unicast_queue_get_data(&actual_client->queue, &buffer_len); @@ -96,7 +115,7 @@ void unicast_data_send(mumudvb_channel_t *actual_channel, mumudvb_channel_t *cha while(packets_left>0) { //we send the data - written_len=write(actual_client->Socket,buffer, buffer_len); + written_len=write(clientsocket,buffer, buffer_len); //We check if all the data was successfully written if(written_lenlast_write_error) { log_message(MSG_DEBUG,"Unicast: New error when writing to client %s:%d : %s\n", - inet_ntoa(actual_client->SocketAddr.sin_addr), - actual_client->SocketAddr.sin_port, + inet_ntoa(clientsocketaddr.sin_addr), + clientsocketaddr.sin_port, strerror(errno)); actual_client->last_write_error=errno; written_len=0; @@ -117,8 +136,8 @@ void unicast_data_send(mumudvb_channel_t *actual_channel, mumudvb_channel_t *cha else { log_message(MSG_DEBUG,"Unicast: Not all the data was written to %s:%d. Asked len : %d, written len %d\n", - inet_ntoa(actual_client->SocketAddr.sin_addr), - actual_client->SocketAddr.sin_port, + inet_ntoa(clientsocketaddr.sin_addr), + clientsocketaddr.sin_port, actual_channel->nb_bytes, written_len); } @@ -135,8 +154,8 @@ void unicast_data_send(mumudvb_channel_t *actual_channel, mumudvb_channel_t *cha if(!actual_client->consecutive_errors) { log_message(MSG_DETAIL,"Unicast: Error when writing to client %s:%d : %s\n", - inet_ntoa(actual_client->SocketAddr.sin_addr), - actual_client->SocketAddr.sin_port, + inet_ntoa(clientsocketaddr.sin_addr), + clientsocketaddr.sin_port, strerror(errno)); gettimeofday (&tv, (struct timezone *) NULL); actual_client->first_error_time = tv.tv_sec; @@ -149,10 +168,10 @@ void unicast_data_send(mumudvb_channel_t *actual_channel, mumudvb_channel_t *cha if((unicast_vars->consecutive_errors_timeout > 0) && (tv.tv_sec - actual_client->first_error_time) > unicast_vars->consecutive_errors_timeout) { log_message(MSG_INFO,"Unicast: Consecutive errors when writing to client %s:%d during too much time, we disconnect\n", - inet_ntoa(actual_client->SocketAddr.sin_addr), - actual_client->SocketAddr.sin_port); + inet_ntoa(clientsocketaddr.sin_addr), + clientsocketaddr.sin_port); temp_client=actual_client->chan_next; - unicast_close_connection(unicast_vars,fds,actual_client->Socket,channels); + unicast_close_connection(unicast_vars,fds,clientsocket,channels); actual_client=temp_client; } } @@ -163,8 +182,8 @@ void unicast_data_send(mumudvb_channel_t *actual_channel, mumudvb_channel_t *cha if (actual_client->consecutive_errors) { log_message(MSG_DETAIL,"Unicast: We can write again to client %s:%d\n", - inet_ntoa(actual_client->SocketAddr.sin_addr), - actual_client->SocketAddr.sin_port); + inet_ntoa(clientsocketaddr.sin_addr), + clientsocketaddr.sin_port); actual_client->consecutive_errors=0; actual_client->last_write_error=0; if(data_from_queue) @@ -188,8 +207,8 @@ void unicast_data_send(mumudvb_channel_t *actual_channel, mumudvb_channel_t *cha { packets_left=0; log_message(MSG_DEBUG,"Unicast: The queue is now empty :) client %s:%d \n", - inet_ntoa(actual_client->SocketAddr.sin_addr), - actual_client->SocketAddr.sin_port); + inet_ntoa(clientsocketaddr.sin_addr), + clientsocketaddr.sin_port); } } } diff --git a/src/unicast_queue.h b/src/unicast_queue.h index 803ee3be..7d1b4be0 100644 --- a/src/unicast_queue.h +++ b/src/unicast_queue.h @@ -53,11 +53,7 @@ typedef struct unicast_queue_header_t{ }unicast_queue_header_t; - void unicast_queue_clear(unicast_queue_header_t *header); - - - #endif \ No newline at end of file diff --git a/src/unicast_rtsp.c b/src/unicast_rtsp.c index 84bddbf1..b5085231 100644 --- a/src/unicast_rtsp.c +++ b/src/unicast_rtsp.c @@ -47,7 +47,7 @@ #include #include -#include "unicast_http.h" +#include "unicast_rtsp.h" #include "unicast_queue.h" #include "mumudvb.h" #include "errors.h" @@ -60,7 +60,12 @@ extern int Interrupted; /** @todo handle non keepalive clients, and auto disconnect to old clients without streaming */ - +int unicast_send_rtsp_describe (int Socket, int CSeq); +int unicast_send_rtsp_options (int Socket, int CSeq); +int unicast_send_rtsp_setup (unicast_client_t *client, int CSeq, int Tsprt_type); +int unicast_send_rtsp_play (int Socket, int CSeq, unicast_client_t *client, mumudvb_channel_t *channels); +int unicast_send_rtsp_setup (unicast_client_t *client, int CSeq, int Tsprt_type); +int unicast_send_rtsp_teardown (int Socket, int CSeq, unicast_client_t *client , mumudvb_channel_t *channels, unicast_parameters_t *unicast_vars, fds_t *fds); /** @brief Deal with an incoming message on the unicast client connection * This function will store and answer the RTSP requests @@ -73,5 +78,400 @@ extern int Interrupted; */ int unicast_handle_rtsp_message(unicast_parameters_t *unicast_vars, unicast_client_t *client, mumudvb_channel_t *channels, int number_of_channels, fds_t *fds) { + (void) unicast_vars; + (void) number_of_channels; + int iRet; + + iRet=unicast_new_message(client); + if(iRet) + return iRet; + + //We search for the end of the HTTP request + if(!(strlen(client->buffer)>5 && strstr(client->buffer, "\n\r\n\0"))) + return 0; + + // char *substring=NULL; + //char *substringcseq=NULL; + //char *urlPreSuffix=NULL; + //char *urlSuffix=NULL; + int requested_channel; + //int iRet; + requested_channel=0; + //unicast_reply_t* reply=NULL; + + log_message(MSG_DEBUG,"Unicast : End of HTTP request, we parse it\n"); + // We implement RTSP protocol + /* The client is initially supplied with an RTSP URL, on the form: + rtsp://server.address:port/object.sdp + */ + + char *poscseq; + int CSeq=0; + int pos; + pos=0; + poscseq=strstr(client->buffer ,"CSeq:"); + log_message(MSG_FLOOD,"Buffer : %s\n",client->buffer); + if(poscseq==NULL) + { + log_message(MSG_DEBUG,"CSeq not found\n"); + /** @todo Implement an error following the RTSP protocol*/ + return CLOSE_CONNECTION; //tu n'est pas content ... + } + log_message(MSG_DEBUG,"CSeq a la position %d\n", (int)(poscseq-(client->buffer))); + pos=(int)(poscseq-(client->buffer)); + pos+=strlen("Cseq: "); + CSeq = atoi(client->buffer+pos); //replace by CSeq = atoi(poscseq+strlen("Cseq: ")); + log_message(MSG_INFO,"Cseq: %d\n", CSeq); + + if(strstr(client->buffer,"DESCRIBE")==client->buffer) + { + unicast_send_rtsp_describe(client->Socket, CSeq); + unicast_flush_client(client); + return 0; + } + else if(strstr(client->buffer,"OPTIONS")==client->buffer) + { + unicast_send_rtsp_options(client->Socket, CSeq); + unicast_flush_client(client); + return 0; + } + else if(strstr(client->buffer,"SETUP")==client->buffer) + { + pos=0; + char *pos_search; + /** @todo put this in a function */ + char session[16]; + for (int i=0;i<15;i++) + { + float randomnum; + randomnum = rand(); + randomnum/=RAND_MAX; + session[i]='a'+(int)(randomnum*25); + } + session[15]='\0'; + strcpy(client->session, session); + log_message(MSG_DEBUG,"Session : %s\n", session ); + // Parse le type de transport + int TransportType=TRANSPORT_UNDEFINED; // RTP/AVP | RTP/AVP/UDP = 0 , RTP/AVP/TCP=1 + // Transport: RTP/AVP + /* transport-protocol = "RTP" + profile = "AVP" + lower-transport = "TCP" | "UDP" */ + // Parse le type de transport + pos_search=strstr(client->buffer ,"Transport:"); + if(pos_search==NULL) + { + log_message(MSG_DEBUG,"Type de transport non trouve\n"); + return CLOSE_CONNECTION; //tu n'est pas content ... + } + log_message(MSG_DEBUG,"Type de transport a la position %d\n", (int)(pos_search-(client->buffer))); + pos=(int)(pos_search-(client->buffer)); + pos+=strlen("Transport: "); + if (!strncmp (client->buffer+pos, "RTP/AVP/TCP", strlen("RTP/AVP/TCP"))) { + TransportType=RTP_AVP_TCP; + log_message(MSG_INFO,"Transport: RTP/AVP/TCP\n"); + } + else if (!strncmp (client->buffer+pos, "RTP/AVP/UDP", strlen("RTP/AVP/UDP"))) + { + TransportType=RTP_AVP_UDP; + log_message(MSG_INFO,"Transport: RTP/AVP/UDP\n"); + } + else if (!strncmp (client->buffer+pos, "RTP/AVP", strlen("RTP/AVP"))) + { + TransportType=RTP_AVP_UDP; + log_message(MSG_INFO,"Transport: RTP/AVP\n"); + } + else + { + log_message(MSG_INFO,"Transport unknown"); + return CLOSE_CONNECTION; /** @todo implement a RTSP error*/ + } + + // Parse le port client + pos_search=strstr(client->buffer ,"client_port="); + log_message(MSG_FLOOD,"Buffer : %s\n",client->buffer); + if(pos_search==NULL) + { + log_message(MSG_DEBUG,"Port client non trouve\n"); + /** @todo implement RTSP error */ + return CLOSE_CONNECTION; //tu n'est pas content ... + } + pos=(int)(pos_search-(client->buffer)); + pos+=strlen("client_port="); + client->rtsp_client_port = atoi(client->buffer+pos); + log_message(MSG_INFO,"client_port= %d\n", client->rtsp_client_port); + + struct sockaddr_in tempSocketAddr; + unsigned int l; + l = sizeof(struct sockaddr); + getsockname(client->Socket, (struct sockaddr *) &tempSocketAddr, &l); + strcpy(client->rtsp_client_ip,inet_ntoa(tempSocketAddr.sin_addr)); + log_message(MSG_DETAIL,"Unicast : Client ip %s \n",client->rtsp_client_ip); + + client->rtsp_Socket=makeUDPsocket (client->rtsp_client_ip, client->rtsp_client_port,&client->rtsp_SocketAddr); + log_message(MSG_DETAIL,"Unicast : New RTSP socket d_IP %s, d_port:%d n°%d\n",inet_ntoa(client->rtsp_SocketAddr.sin_addr), client->rtsp_SocketAddr.sin_port, client->rtsp_Socket); + l = sizeof(struct sockaddr); + connect(client->rtsp_Socket, &client->rtsp_SocketAddr, l); + client->rtsp_SocketAddr.sin_port=4242; + bind(client->rtsp_Socket,&client->rtsp_SocketAddr,l); + //l = sizeof(struct sockaddr); + //getsockname(client->rtsp_Socket, (struct sockaddr *) &tempSocketAddr, &l); + //log_message(MSG_DETAIL,"Unicast : after getsockname RTSP socket d_IP %s, d_port:%d n°%d\n",inet_ntoa(client->rtsp_SocketAddr.sin_addr), client->rtsp_SocketAddr.sin_port, client->rtsp_Socket); + //client->rtsp_server_port=client->rtsp_SocketAddr.sin_port; + client->rtsp_server_port=4242; + unicast_send_rtsp_setup(client, CSeq, TransportType); + unicast_flush_client(client); + return 0; + } + else if(strstr(client->buffer,"PLAY")==client->buffer) + { + //char *inPort=NULL; + unicast_send_rtsp_play(client->Socket, CSeq, client, channels); + unicast_flush_client(client); + return 0; + } + else if(strstr(client->buffer,"TEARDOWN")==client->buffer) + { + unicast_send_rtsp_teardown(client->Socket, CSeq, client, channels, unicast_vars, fds); + return CLOSE_CONNECTION; + } + else + { + log_message(MSG_WARN,"rate ... \n"); + unicast_flush_client(client); + } + + return 0; +} + + +/** @brief Dump the filled buffer on the socket adding RTSP header informations +*/ +int rtsp_reply_prepare_headers(unicast_reply_t *reply, int code, int CSeq) +{ + //we add the header information + reply->type = REPLY_HEADER; + unicast_reply_write(reply, "RTSP/1.0 "); + switch(code) + { + case 200: + unicast_reply_write(reply, "200 OK\r\n"); + break; + case 404: + unicast_reply_write(reply, "404 Not found\r\n"); + break; + case 503: + unicast_reply_write(reply, "503 Too many clients\r\n"); + break; + default: + log_message(MSG_ERROR,"reply send with bad code please contact\n"); + return 0; + } + unicast_reply_write(reply, "CSeq: %d\r\n",CSeq); + unicast_reply_write(reply, "Server: mumudvb/" VERSION "\r\n"); + unicast_reply_write(reply, "Public: DESCRIBE, OPTIONS, SETUP, TEARDOWN, PLAY\r\n"); + reply->type = REPLY_BODY; + return 0; +} + + +int rtsp_reply_send(unicast_reply_t *reply, int socket, const char* content_type) +{ + //we add the header information + reply->type = REPLY_HEADER; + if(reply->used_body) + { + unicast_reply_write(reply, "Content-type: %s\r\n", content_type); + unicast_reply_write(reply, "Content-length: %d\r\n", reply->used_body); + } + unicast_reply_write(reply, "\r\n"); /* end header */ + //we merge the header and the body + reply->buffer_header = realloc(reply->buffer_header, reply->used_header+reply->used_body); + memcpy(&reply->buffer_header[reply->used_header],reply->buffer_body,sizeof(char)*reply->used_body); + reply->used_header+=reply->used_body; + //now we write the data + int size = write(socket, reply->buffer_header, reply->used_header); + return size; +} + + +/** @brief Send RTSP_DESCRIBE_REPLY + * The DESCRIBE method retrieves the description of a presentation or + * media object identified by the request URL from a server. It may use + * the Accept header to specify the description formats that the client + * understands. The server responds with a description of the requested + * resource. The DESCRIBE reply-response pair constitutes the media + * initialization phase of RTSP. + * @param Socket the socket on wich the information have to be sent + */ +int unicast_send_rtsp_describe (int Socket, int CSeq) + { + unicast_reply_t* reply = unicast_reply_init(); + if (NULL == reply) + { + log_message(MSG_INFO,"Unicast : Error when creating the RTSP reply\n"); + return -1; + } + log_message(MSG_INFO,"Requete DESCRIBE RTSP\n"); + + char *TransportType="RTP/AVP"; + //if (TransportType) TransportType="RTP/AVP/TCP"; // =0:UDP, =1:TCP + char *source_host = "MuMuDVB-server"; + unicast_reply_write(reply, "\r\n"); + unicast_reply_write(reply, "v=0\r\n"); + unicast_reply_write(reply, "o=- 14904518995472011776 14904518995472011776 IN IP4 %s\r\n", source_host); + unicast_reply_write(reply, "s=unknown\r\n"); + unicast_reply_write(reply, "i=unknown\r\n"); + unicast_reply_write(reply, "c=IN IP4 0.0.0.0\r\n"); + //unicast_reply_write(reply, "c=IN IP4 239.100.1.0/2\r\n"); Pour le multicast RTSP + unicast_reply_write(reply, "t=0 0\r\n"); + unicast_reply_write(reply, "m=video 0 %s 33\r\n", TransportType); + // unicast_reply_write(reply, "a=control:rtsp://192.168.15.151:4242/rtsp/stream?namespace=1&service=201&flavour=ld\r\n"); + + rtsp_reply_prepare_headers(reply, 200, CSeq); + rtsp_reply_send(reply, Socket,"application/sdp"); + + if (0 != unicast_reply_free(reply)) + { + log_message(MSG_INFO,"Unicast : Error when releasing the HTTP reply after sendinf it\n"); + return -1; + } + + return 0; } + + +/** @brief Send RTSP_OPTIONS_REPLY + * + * @param Socket the socket on wich the information have to be sent + */ +int unicast_send_rtsp_options (int Socket, int CSeq) +{ + unicast_reply_t* reply = unicast_reply_init(); + if (NULL == reply) + { + log_message(MSG_INFO,"Unicast : Error when creating the RTSP reply\n"); + return -1; + } + + log_message(MSG_INFO,"Requete OPTIONS RTSP\n"); ; + + rtsp_reply_prepare_headers(reply, 200, CSeq); + rtsp_reply_send(reply, Socket,"text/plain"); + + if (0 != unicast_reply_free(reply)) + { + log_message(MSG_INFO,"Unicast : Error when releasing the HTTP reply after sendinf it\n"); + return -1; + } + + return 0; +} + + +/** @brief Send RTSP_SETUP_REPLY + * + * @param Socket the socket on wich the information have to be sent + */ +int unicast_send_rtsp_setup (unicast_client_t *client, int CSeq, int Tsprt_type) +{ + int Socket=client->Socket; + char TransportType[20], broadcast_type; + unicast_reply_t* reply = unicast_reply_init(); + if (NULL == reply) + { + log_message(MSG_INFO,"Unicast : Error when creating the RTSP reply\n"); + return -1; + } + + log_message(MSG_INFO,"Requete SETUP RTSP\n"); + //unicast_reply_write(reply, RTSP_SETUP_REPLY); + + rtsp_reply_prepare_headers(reply, 200, CSeq); + reply->type = REPLY_HEADER; + unicast_reply_write(reply, "Session: %s\r\n", client->session); + + if (Tsprt_type==RTP_AVP_TCP) + strcpy(TransportType,"RTP/AVP/TCP"); + else + strcpy(TransportType,"RTP/AVP"); + + //TODO Get the broadcast_type from the DESCRIBE request + //if (Tsprt_type==2) broadcast_type="multicast"; + // else broadcast_type="unicast"; + + log_message(MSG_DEBUG, "Transport: %s;%s;mode=play;destination=%s;client_port=%d-%d;server_port=%d\r\n", TransportType, broadcast_type, client->rtsp_client_ip, client->rtsp_client_port, client->rtsp_client_port+1, client->rtsp_server_port); + unicast_reply_write(reply, "Transport: %s;%s;mode=play;destination=%s;client_port=%d-%d;server_port=%d\r\n", TransportType, broadcast_type, client->rtsp_client_ip, client->rtsp_client_port, client->rtsp_client_port+1, client->rtsp_server_port); + rtsp_reply_send(reply, Socket,"text/plain"); + + if (0 != unicast_reply_free(reply)) + { + log_message(MSG_INFO,"Unicast : Error when releasing the HTTP reply after sendinf it\n"); + return -1; + } + + return 0; +} + +/** @brief Send RTSP_PLAY_REPLY + * + * @param Socket the socket on wich the information have to be sent + */ +int unicast_send_rtsp_play (int Socket, int CSeq, unicast_client_t *client, mumudvb_channel_t *channels) +{ + unicast_reply_t* reply = unicast_reply_init(); + if (NULL == reply) + { + log_message(MSG_INFO,"Unicast : Error when creating the RTSP reply\n"); + return -1; + } + + log_message(MSG_INFO,"Requete PLAY RTSP\n"); + unicast_reply_write(reply, "Session: %s\r\n", client->session); + rtsp_reply_prepare_headers(reply, 200, CSeq); + rtsp_reply_send(reply, Socket, "text/plain"); + + // TODO Ajouter l'IP du client dans la liste des IP unicast. + client->channel=0; + //channel_add_unicast_client(client, &channels[0]); //plop ca ne va pas marcher, il faut le modifier pour prendre en compte le type de client + + + if (0 != unicast_reply_free(reply)) + { + log_message(MSG_INFO,"Unicast : Error when releasing the HTTP reply after sendinf it\n"); + return -1; + } + + return 0; +} + +/** @brief Send RTSP_PLAY_TEARDOWN + * + * @param Socket the socket on wich the information have to be sent + */ +int unicast_send_rtsp_teardown (int Socket, int CSeq, unicast_client_t *client , mumudvb_channel_t *channels, unicast_parameters_t *unicast_vars, fds_t *fds) +{ + unicast_reply_t* reply = unicast_reply_init(); + if (NULL == reply) + { + log_message(MSG_INFO,"Unicast : Error when creating the RTSP reply\n"); + return -1; + } + + log_message(MSG_INFO,"Requete TEARDOWN RTSP\n"); + + rtsp_reply_prepare_headers(reply, 200, CSeq); + rtsp_reply_send(reply, Socket, "text/plain"); + + //unicast_close_connection(unicast_vars, fds, Socket, channels); + + if (0 != unicast_reply_free(reply)) + { + log_message(MSG_INFO,"Unicast : Error when releasing the HTTP reply after sendinf it\n"); + return -1; + } + + return 0; +} + diff --git a/src/unicast_rtsp.h b/src/unicast_rtsp.h index 6bdf71c0..782de834 100644 --- a/src/unicast_rtsp.h +++ b/src/unicast_rtsp.h @@ -43,6 +43,13 @@ #define RTSP_461_REPLY "RTSP/1.0 461 Unsupported transport\r\n"\ "\r\n" +enum +{ + TRANSPORT_UNDEFINED=0, + RTP_AVP_UDP, + RTP_AVP_TCP, +}; + int unicast_handle_rtsp_message(unicast_parameters_t *unicast_vars, unicast_client_t *client, mumudvb_channel_t *channels, int number_of_channels, fds_t *fds); From 0f296431898d23fbb81148231927049eff8448ae Mon Sep 17 00:00:00 2001 From: braice Date: Fri, 22 Jan 2010 16:39:55 +0100 Subject: [PATCH 06/28] Unicast RTSP small bugs --- src/unicast_rtsp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/unicast_rtsp.c b/src/unicast_rtsp.c index b5085231..e01a59fa 100644 --- a/src/unicast_rtsp.c +++ b/src/unicast_rtsp.c @@ -99,7 +99,7 @@ int unicast_handle_rtsp_message(unicast_parameters_t *unicast_vars, unicast_clie requested_channel=0; //unicast_reply_t* reply=NULL; - log_message(MSG_DEBUG,"Unicast : End of HTTP request, we parse it\n"); + log_message(MSG_DEBUG,"Unicast : End of RTSP request, we parse it\n"); // We implement RTSP protocol /* The client is initially supplied with an RTSP URL, on the form: rtsp://server.address:port/object.sdp @@ -377,7 +377,7 @@ int unicast_send_rtsp_options (int Socket, int CSeq) int unicast_send_rtsp_setup (unicast_client_t *client, int CSeq, int Tsprt_type) { int Socket=client->Socket; - char TransportType[20], broadcast_type; + char TransportType[20], broadcast_type[20]; unicast_reply_t* reply = unicast_reply_init(); if (NULL == reply) { @@ -400,7 +400,7 @@ int unicast_send_rtsp_setup (unicast_client_t *client, int CSeq, int Tsprt_type) //TODO Get the broadcast_type from the DESCRIBE request //if (Tsprt_type==2) broadcast_type="multicast"; // else broadcast_type="unicast"; - + strcpy( broadcast_type,"unicast"); log_message(MSG_DEBUG, "Transport: %s;%s;mode=play;destination=%s;client_port=%d-%d;server_port=%d\r\n", TransportType, broadcast_type, client->rtsp_client_ip, client->rtsp_client_port, client->rtsp_client_port+1, client->rtsp_server_port); unicast_reply_write(reply, "Transport: %s;%s;mode=play;destination=%s;client_port=%d-%d;server_port=%d\r\n", TransportType, broadcast_type, client->rtsp_client_ip, client->rtsp_client_port, client->rtsp_client_port+1, client->rtsp_server_port); rtsp_reply_send(reply, Socket,"text/plain"); From 1b69d04a3fea3ddf38d59998a8ebe6c36191bc06 Mon Sep 17 00:00:00 2001 From: braice Date: Fri, 22 Jan 2010 17:47:09 +0100 Subject: [PATCH 07/28] Unicast: RTSP : Bug : the RSTP and HTTP clients were mixed --- src/unicast_common.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/unicast_common.c b/src/unicast_common.c index 576b0c1c..18b23174 100644 --- a/src/unicast_common.c +++ b/src/unicast_common.c @@ -321,9 +321,9 @@ int unicast_handle_fd_event(unicast_parameters_t *unicast_vars, fds_t *fds, mumu unicast_client_t *tempClient; //we accept the incoming connection if(unicast_vars->fd_info[actual_fd].type==UNICAST_MASTER_RTSP) - tempClient=unicast_accept_connection(unicast_vars, fds->pfds[actual_fd].fd,CLIENT_HTTP); - else tempClient=unicast_accept_connection(unicast_vars, fds->pfds[actual_fd].fd,CLIENT_RTSP); + else + tempClient=unicast_accept_connection(unicast_vars, fds->pfds[actual_fd].fd,CLIENT_HTTP); if(tempClient!=NULL) { From 570196a8644eacec68595ec41014d04fdc5be1be Mon Sep 17 00:00:00 2001 From: braice Date: Fri, 22 Jan 2010 20:46:26 +0100 Subject: [PATCH 08/28] Unicast : some errors about the sockets (RTSP and logging) --- src/network.c | 11 ++++++++++- src/unicast_clients.c | 8 ++++---- src/unicast_common.c | 2 +- src/unicast_queue.c | 14 +++++++------- src/unicast_rtsp.c | 20 +++++++++++++------- 5 files changed, 35 insertions(+), 20 deletions(-) diff --git a/src/network.c b/src/network.c index a29c7455..ad3dc7b9 100644 --- a/src/network.c +++ b/src/network.c @@ -134,14 +134,23 @@ makeUDPsocket (char *szAddr, unsigned short port, log_message( MSG_ERROR,"inet_aton failed : %s\n", strerror(errno)); Interrupted=ERROR_NETWORK<<8; } + //We connect the socket + connect(iSocket,(struct sockaddr *) sSockAddr, sizeof(struct sockaddr_in)); + if (iRet == 0) + { + log_message( MSG_ERROR,"connect failed : %s\n", strerror(errno)); + Interrupted=ERROR_NETWORK<<8; + } + + /* iRet = setsockopt (iSocket, SOL_SOCKET, SO_REUSEADDR, &iLoop, sizeof (int)); if (iRet < 0) { log_message( MSG_ERROR,"setsockopt SO_REUSEADDR failed : %s\n",strerror(errno)); Interrupted=ERROR_NETWORK<<8; } - + */ return iSocket; } diff --git a/src/unicast_clients.c b/src/unicast_clients.c index e4084ac0..00fa97d0 100644 --- a/src/unicast_clients.c +++ b/src/unicast_clients.c @@ -132,9 +132,9 @@ int unicast_del_client(unicast_parameters_t *unicast_vars, unicast_client_t *cli { unicast_client_t *prev_client,*next_client; - log_message(MSG_DETAIL,"Unicast : We delete the client %s:%d, socket %d\n",inet_ntoa(client->SocketAddr.sin_addr), client->SocketAddr.sin_port, client->Socket); + log_message(MSG_DETAIL,"Unicast : We delete the client %s:%d, socket %d\n",inet_ntoa(client->SocketAddr.sin_addr), ntohs(client->SocketAddr.sin_port), client->Socket); if(client->client_type==CLIENT_RTSP && client->rtsp_Socket) - log_message(MSG_DETAIL,"Unicast : RTSP %s:%d, Unicast socket %d\n",inet_ntoa(client->rtsp_SocketAddr.sin_addr), client->rtsp_SocketAddr.sin_port, client->rtsp_Socket); + log_message(MSG_DETAIL,"Unicast : RTSP %s:%d, Unicast socket %d\n",inet_ntoa(client->rtsp_SocketAddr.sin_addr), ntohs(client->rtsp_SocketAddr.sin_port), client->rtsp_Socket); if (client->Socket >= 0) { @@ -201,7 +201,7 @@ int channel_add_unicast_client(unicast_client_t *client,mumudvb_channel_t *chann unicast_client_t *last_client; int iRet; - log_message(MSG_INFO,"Unicast : We add the client %s:%d to the channel \"%s\"\n",inet_ntoa(client->SocketAddr.sin_addr), client->SocketAddr.sin_port,channel->name); + log_message(MSG_INFO,"Unicast : We add the client %s:%d to the channel \"%s\"\n",inet_ntoa(client->SocketAddr.sin_addr), ntohs(client->SocketAddr.sin_port),channel->name); if(client->client_type==CLIENT_HTTP) { @@ -214,7 +214,7 @@ int channel_add_unicast_client(unicast_client_t *client,mumudvb_channel_t *chann } if(client->client_type==CLIENT_RTSP) { - log_message(MSG_INFO,"Unicast : We add the client (RTP) sin_addr : %s: client->rtsp_SocketAddr.sin_port %d to the channel \"%s\"\n",inet_ntoa(client->rtsp_SocketAddr.sin_addr), client->rtsp_SocketAddr.sin_port,channel->name); + log_message(MSG_INFO,"Unicast : We add the client (RTP) sin_addr : %s: ntohs(client->rtsp_SocketAddr.sin_port) %d to the channel \"%s\"\n",inet_ntoa(client->rtsp_SocketAddr.sin_addr), ntohs(client->rtsp_SocketAddr.sin_port),channel->name); } client->chan_next=NULL; diff --git a/src/unicast_common.c b/src/unicast_common.c index 18b23174..b91aa0d8 100644 --- a/src/unicast_common.c +++ b/src/unicast_common.c @@ -433,7 +433,7 @@ unicast_client_t *unicast_accept_connection(unicast_parameters_t *unicast_vars, struct sockaddr_in tempSocketAddr; l = sizeof(struct sockaddr); getsockname(tempSocket, (struct sockaddr *) &tempSocketAddr, &l); - log_message(MSG_DETAIL,"Unicast : New connection from %s:%d to %s:%d \n",inet_ntoa(tempSocketAddrIn.sin_addr), tempSocketAddrIn.sin_port,inet_ntoa(tempSocketAddr.sin_addr), tempSocketAddr.sin_port); + log_message(MSG_DETAIL,"Unicast : New connection from %s:%d to %s:%d \n",inet_ntoa(tempSocketAddrIn.sin_addr), ntohs(tempSocketAddrIn.sin_port),inet_ntoa(tempSocketAddr.sin_addr), ntohs(tempSocketAddr.sin_port)); //Now we set this socket to be non blocking because we poll it int flags; diff --git a/src/unicast_queue.c b/src/unicast_queue.c index b44f6c28..8309ae99 100644 --- a/src/unicast_queue.c +++ b/src/unicast_queue.c @@ -104,7 +104,7 @@ void unicast_data_send(mumudvb_channel_t *actual_channel, mumudvb_channel_t *cha actual_client->queue.full=1; log_message(MSG_DETAIL,"Unicast: The queue is full, we now throw away new packets for client %s:%d\n", inet_ntoa(clientsocketaddr.sin_addr), - clientsocketaddr.sin_port); + ntohs(clientsocketaddr.sin_port)); } } buffer=unicast_queue_get_data(&actual_client->queue, &buffer_len); @@ -127,7 +127,7 @@ void unicast_data_send(mumudvb_channel_t *actual_channel, mumudvb_channel_t *cha { log_message(MSG_DEBUG,"Unicast: New error when writing to client %s:%d : %s\n", inet_ntoa(clientsocketaddr.sin_addr), - clientsocketaddr.sin_port, + ntohs(clientsocketaddr.sin_port), strerror(errno)); actual_client->last_write_error=errno; written_len=0; @@ -137,7 +137,7 @@ void unicast_data_send(mumudvb_channel_t *actual_channel, mumudvb_channel_t *cha { log_message(MSG_DEBUG,"Unicast: Not all the data was written to %s:%d. Asked len : %d, written len %d\n", inet_ntoa(clientsocketaddr.sin_addr), - clientsocketaddr.sin_port, + ntohs(clientsocketaddr.sin_port), actual_channel->nb_bytes, written_len); } @@ -155,7 +155,7 @@ void unicast_data_send(mumudvb_channel_t *actual_channel, mumudvb_channel_t *cha { log_message(MSG_DETAIL,"Unicast: Error when writing to client %s:%d : %s\n", inet_ntoa(clientsocketaddr.sin_addr), - clientsocketaddr.sin_port, + ntohs(clientsocketaddr.sin_port), strerror(errno)); gettimeofday (&tv, (struct timezone *) NULL); actual_client->first_error_time = tv.tv_sec; @@ -169,7 +169,7 @@ void unicast_data_send(mumudvb_channel_t *actual_channel, mumudvb_channel_t *cha { log_message(MSG_INFO,"Unicast: Consecutive errors when writing to client %s:%d during too much time, we disconnect\n", inet_ntoa(clientsocketaddr.sin_addr), - clientsocketaddr.sin_port); + ntohs(clientsocketaddr.sin_port)); temp_client=actual_client->chan_next; unicast_close_connection(unicast_vars,fds,clientsocket,channels); actual_client=temp_client; @@ -183,7 +183,7 @@ void unicast_data_send(mumudvb_channel_t *actual_channel, mumudvb_channel_t *cha { log_message(MSG_DETAIL,"Unicast: We can write again to client %s:%d\n", inet_ntoa(clientsocketaddr.sin_addr), - clientsocketaddr.sin_port); + ntohs(clientsocketaddr.sin_port)); actual_client->consecutive_errors=0; actual_client->last_write_error=0; if(data_from_queue) @@ -208,7 +208,7 @@ void unicast_data_send(mumudvb_channel_t *actual_channel, mumudvb_channel_t *cha packets_left=0; log_message(MSG_DEBUG,"Unicast: The queue is now empty :) client %s:%d \n", inet_ntoa(clientsocketaddr.sin_addr), - clientsocketaddr.sin_port); + ntohs(clientsocketaddr.sin_port)); } } } diff --git a/src/unicast_rtsp.c b/src/unicast_rtsp.c index e01a59fa..7035b90e 100644 --- a/src/unicast_rtsp.c +++ b/src/unicast_rtsp.c @@ -57,6 +57,9 @@ extern int Interrupted; +//from unicast_client.c +int channel_add_unicast_client(unicast_client_t *client,mumudvb_channel_t *channel); + /** @todo handle non keepalive clients, and auto disconnect to old clients without streaming */ @@ -206,14 +209,17 @@ int unicast_handle_rtsp_message(unicast_parameters_t *unicast_vars, unicast_clie l = sizeof(struct sockaddr); getsockname(client->Socket, (struct sockaddr *) &tempSocketAddr, &l); strcpy(client->rtsp_client_ip,inet_ntoa(tempSocketAddr.sin_addr)); - log_message(MSG_DETAIL,"Unicast : Client ip %s \n",client->rtsp_client_ip); + log_message(MSG_DETAIL,"Unicast : Client ip %s port %d \n",client->rtsp_client_ip,(unsigned short) client->rtsp_client_port); client->rtsp_Socket=makeUDPsocket (client->rtsp_client_ip, client->rtsp_client_port,&client->rtsp_SocketAddr); - log_message(MSG_DETAIL,"Unicast : New RTSP socket d_IP %s, d_port:%d n°%d\n",inet_ntoa(client->rtsp_SocketAddr.sin_addr), client->rtsp_SocketAddr.sin_port, client->rtsp_Socket); - l = sizeof(struct sockaddr); - connect(client->rtsp_Socket, &client->rtsp_SocketAddr, l); - client->rtsp_SocketAddr.sin_port=4242; - bind(client->rtsp_Socket,&client->rtsp_SocketAddr,l); + log_message(MSG_DETAIL,"Unicast : New RTSP socket d_IP %s, d_port:%d n°%d\n",inet_ntoa(client->rtsp_SocketAddr.sin_addr), ntohs(client->rtsp_SocketAddr.sin_port), client->rtsp_Socket); + l = sizeof(struct sockaddr_in); + struct sockaddr_in tempsin; + //memcpy(&tempsin, &client->rtsp_SocketAddr,l); + //connect(client->rtsp_Socket,(struct sockaddr *) &tempsin, l); + memcpy(&tempsin, &client->rtsp_SocketAddr,l); + tempsin.sin_port=htons(4242); + bind(client->rtsp_Socket,(struct sockaddr *) &tempsin,l); //l = sizeof(struct sockaddr); //getsockname(client->rtsp_Socket, (struct sockaddr *) &tempSocketAddr, &l); //log_message(MSG_DETAIL,"Unicast : after getsockname RTSP socket d_IP %s, d_port:%d n°%d\n",inet_ntoa(client->rtsp_SocketAddr.sin_addr), client->rtsp_SocketAddr.sin_port, client->rtsp_Socket); @@ -434,7 +440,7 @@ int unicast_send_rtsp_play (int Socket, int CSeq, unicast_client_t *client, mumu // TODO Ajouter l'IP du client dans la liste des IP unicast. client->channel=0; - //channel_add_unicast_client(client, &channels[0]); //plop ca ne va pas marcher, il faut le modifier pour prendre en compte le type de client + channel_add_unicast_client(client, &channels[0]); if (0 != unicast_reply_free(reply)) From 91c551526a6cc4742700acced927a1102e323235 Mon Sep 17 00:00:00 2001 From: braice Date: Sat, 23 Jan 2010 19:38:52 +0100 Subject: [PATCH 09/28] Unicast First working RTSP Todo : * search if a client already exist with the same session when a new one connects * parse the path * the server port is wrong * store the satus of the RTSP negociation * clean dead clients --- src/unicast.h | 2 +- src/unicast_clients.c | 1 + src/unicast_common.c | 31 +++++++++++++++++------- src/unicast_common.h | 2 +- src/unicast_queue.c | 46 ++++++++++++++++++++--------------- src/unicast_rtsp.c | 56 ++++++++++++++++++++++++++----------------- 6 files changed, 87 insertions(+), 51 deletions(-) diff --git a/src/unicast.h b/src/unicast.h index 6d567106..16af6507 100644 --- a/src/unicast.h +++ b/src/unicast.h @@ -76,7 +76,7 @@ typedef struct unicast_client_t{ /**RTSP ports*/ int rtsp_client_port; int rtsp_server_port; - char rtsp_client_ip[20]; + char client_ip[20]; /**RTSP socket*/ int rtsp_Socket; /**RTSP socket*/ diff --git a/src/unicast_clients.c b/src/unicast_clients.c index 00fa97d0..7b7c6a48 100644 --- a/src/unicast_clients.c +++ b/src/unicast_clients.c @@ -112,6 +112,7 @@ unicast_client_t *unicast_add_client(unicast_parameters_t *unicast_vars, struct client->queue.last=NULL; client->client_type=client_type; client->rtsp_Socket=0; + client->Control_socket_closed=0; unicast_vars->client_number++; return client; diff --git a/src/unicast_common.c b/src/unicast_common.c index b91aa0d8..b1959072 100644 --- a/src/unicast_common.c +++ b/src/unicast_common.c @@ -215,16 +215,15 @@ int unicast_create_listening_socket(int socket_type, int socket_channel, char *i } -/** @brief Close an unicast connection and delete the client +/** @brief Close an unicast connection and delete the client if asked * * @param unicast_vars the unicast parameters * @param fds The polling file descriptors * @param Socket The socket of the client we want to disconnect * @param channels The channel list */ -void unicast_close_connection(unicast_parameters_t *unicast_vars, fds_t *fds, int Socket, mumudvb_channel_t *channels) +void unicast_close_connection(unicast_parameters_t *unicast_vars, fds_t *fds, int Socket, mumudvb_channel_t *channels, int delete_client) { - int delete_client=1; int actual_fd; actual_fd=0; //We find the FD correspondig to this client @@ -244,10 +243,20 @@ void unicast_close_connection(unicast_parameters_t *unicast_vars, fds_t *fds, in return; } - log_message(MSG_DEBUG,"Unicast : We close the connection\n"); + //We delete the client if(delete_client) + { + log_message(MSG_DEBUG,"Unicast : We close the connection and delete the client\n"); unicast_del_client(unicast_vars, unicast_vars->fd_info[actual_fd].client, channels); + } + else + { + log_message(MSG_DEBUG,"Unicast : We ONLY close the connection\n"); + close(Socket); + unicast_vars->fd_info[actual_fd].client->Socket=0; + } + /** @todo : deal with the keep alive, we can close the control connection but keep the client*/ //We move the last fd to the actual/deleted one, and decrease the number of fds by one fds->pfds[actual_fd].fd = fds->pfds[fds->pfdsnum-1].fd; @@ -300,7 +309,7 @@ int unicast_handle_fd_event(unicast_parameters_t *unicast_vars, fds_t *fds, mumu { /** @todo RTSP : no keep alive */ log_message(MSG_DEBUG,"Unicast : We've got a POLLHUP. Actual_fd %d socket %d we close the connection \n", actual_fd, fds->pfds[actual_fd].fd ); - unicast_close_connection(unicast_vars,fds,fds->pfds[actual_fd].fd,channels); + unicast_close_connection(unicast_vars,fds,fds->pfds[actual_fd].fd,channels,1); // !!!!!!!!!!!!! here dont delete the client if RTSP //We check if we hage to parse fds->pfds[actual_fd].revents (the last fd moved to the actual one) if(fds->pfds[actual_fd].revents) actual_fd--;//Yes, we force the loop to see it @@ -379,7 +388,8 @@ int unicast_handle_fd_event(unicast_parameters_t *unicast_vars, fds_t *fds, mumu iRet=unicast_handle_http_message(unicast_vars,unicast_vars->fd_info[actual_fd].client, channels, number_of_channels, fds); if (iRet==CLOSE_CONNECTION ) //iRet==-2 --> 0 received data or error, we close the connection { - unicast_close_connection(unicast_vars,fds,fds->pfds[actual_fd].fd,channels); + log_message(MSG_FLOOD,"Unicast : handle_http_message told us to close the socket %d\n", fds->pfds[actual_fd].fd); + unicast_close_connection(unicast_vars,fds,fds->pfds[actual_fd].fd,channels,1); //We check if we hage to parse fds->pfds[actual_fd].revents (the last fd moved to the actual one) if(fds->pfds[actual_fd].revents) actual_fd--;//Yes, we force the loop to see it again @@ -392,7 +402,8 @@ int unicast_handle_fd_event(unicast_parameters_t *unicast_vars, fds_t *fds, mumu iRet=unicast_handle_rtsp_message(unicast_vars,unicast_vars->fd_info[actual_fd].client, channels, number_of_channels, fds); if (iRet==CLOSE_CONNECTION ) //iRet==CLOSE_CONNECTION --> 0 received data or error, we close the connection { - unicast_close_connection(unicast_vars,fds,fds->pfds[actual_fd].fd,channels); + log_message(MSG_FLOOD,"Unicast : handle_rtsp_message told us to close the socket %d\n", fds->pfds[actual_fd].fd); + unicast_close_connection(unicast_vars,fds,fds->pfds[actual_fd].fd,channels,1); //We check if we hage to parse fds->pfds[actual_fd].revents (the last fd moved to the actual one) if(fds->pfds[actual_fd].revents) actual_fd--;//Yes, we force the loop to see it again @@ -434,7 +445,6 @@ unicast_client_t *unicast_accept_connection(unicast_parameters_t *unicast_vars, l = sizeof(struct sockaddr); getsockname(tempSocket, (struct sockaddr *) &tempSocketAddr, &l); log_message(MSG_DETAIL,"Unicast : New connection from %s:%d to %s:%d \n",inet_ntoa(tempSocketAddrIn.sin_addr), ntohs(tempSocketAddrIn.sin_port),inet_ntoa(tempSocketAddr.sin_addr), ntohs(tempSocketAddr.sin_port)); - //Now we set this socket to be non blocking because we poll it int flags; flags = fcntl(tempSocket, F_GETFL, 0); @@ -465,6 +475,8 @@ unicast_client_t *unicast_accept_connection(unicast_parameters_t *unicast_vars, close(tempSocket); return NULL; } + strncpy(tempClient->client_ip,inet_ntoa(tempSocketAddrIn.sin_addr),20); + tempClient->client_ip[19]='\0'; return tempClient; @@ -507,7 +519,10 @@ int unicast_new_message(unicast_client_t *client) return -1; } if(received_len==0) + { + log_message(MSG_DEBUG,"Unicast : Empty message\n"); return CLOSE_CONNECTION; //To say to the main program to close the connection + } /***************** Now we parse the message to see if something was asked *****************/ client->buffer[client->buffersize]='\0'; //For avoiding strlen to look too far (other option is to use the gnu extension strnlen) diff --git a/src/unicast_common.h b/src/unicast_common.h index 841ac332..c608655b 100644 --- a/src/unicast_common.h +++ b/src/unicast_common.h @@ -52,7 +52,7 @@ int unicast_reply_free(unicast_reply_t *reply); int unicast_reply_write(unicast_reply_t *reply, const char* msg, ...); int unicast_reply_send(unicast_reply_t *reply, int socket, int code, const char* content_type); -void unicast_close_connection(unicast_parameters_t *unicast_vars, fds_t *fds, int Socket, mumudvb_channel_t *channels); +void unicast_close_connection(unicast_parameters_t *unicast_vars, fds_t *fds, int Socket, mumudvb_channel_t *channels, int delete_client); unicast_client_t *unicast_accept_connection(unicast_parameters_t *unicast_vars, int socketIn, int client_type); unicast_client_t *unicast_add_client(unicast_parameters_t *unicast_vars, struct sockaddr_in SocketAddr, int Socket, int client_type); int unicast_new_message(unicast_client_t *client); diff --git a/src/unicast_queue.c b/src/unicast_queue.c index 8309ae99..315de9fc 100644 --- a/src/unicast_queue.c +++ b/src/unicast_queue.c @@ -1,7 +1,7 @@ /* - * MuMuDVB - UDP-ize a DVB transport stream. + * MuMuDVB - Stream a DVB transport stream. * - * (C) 2009 Brice DUBOST + * (C) 2009-2010 Brice DUBOST * * The latest version can be found at http://mumudvb.braice.net * @@ -25,7 +25,7 @@ /** @file * @brief File for HTTP unicast Queue and data sending * @author Brice DUBOST - * @date 2009 + * @date 2009-2010 */ #include @@ -45,7 +45,7 @@ int unicast_queue_remove_data(unicast_queue_header_t *header); int unicast_queue_add_data(unicast_queue_header_t *header, unsigned char *data, int data_len); unsigned char *unicast_queue_get_data(unicast_queue_header_t* , int* ); -void unicast_close_connection(unicast_parameters_t *unicast_vars, fds_t *fds, int Socket, mumudvb_channel_t *channels); + /** @brief Send the buffer for the channel * @@ -141,15 +141,23 @@ void unicast_data_send(mumudvb_channel_t *actual_channel, mumudvb_channel_t *cha actual_channel->nb_bytes, written_len); } - if(!data_from_queue) - { - //We store the non sent data in the queue - if((actual_client->queue.data_bytes_in_queue+buffer_len-written_len)< unicast_vars->queue_max_size) - { - unicast_queue_add_data(&actual_client->queue, buffer+written_len, buffer_len-written_len); - log_message(MSG_DEBUG,"Unicast: We start queuing packets ... \n"); - } - } + if(actual_client->client_type==CLIENT_RTSP) + { + log_message(MSG_DEBUG,"RTSP client, we close the connection\n"); + temp_client=actual_client->chan_next; + unicast_del_client(unicast_vars,actual_client, channels); + actual_client=temp_client; + continue; + } + if(!data_from_queue) + { + //We store the non sent data in the queue + if((actual_client->queue.data_bytes_in_queue+buffer_len-written_len)< unicast_vars->queue_max_size) + { + unicast_queue_add_data(&actual_client->queue, buffer+written_len, buffer_len-written_len); + log_message(MSG_DEBUG,"Unicast: We start queuing packets ... \n"); + } + } if(!actual_client->consecutive_errors) { @@ -157,9 +165,9 @@ void unicast_data_send(mumudvb_channel_t *actual_channel, mumudvb_channel_t *cha inet_ntoa(clientsocketaddr.sin_addr), ntohs(clientsocketaddr.sin_port), strerror(errno)); - gettimeofday (&tv, (struct timezone *) NULL); - actual_client->first_error_time = tv.tv_sec; - actual_client->consecutive_errors=1; + gettimeofday (&tv, (struct timezone *) NULL); + actual_client->first_error_time = tv.tv_sec; + actual_client->consecutive_errors=1; } else { @@ -170,9 +178,9 @@ void unicast_data_send(mumudvb_channel_t *actual_channel, mumudvb_channel_t *cha log_message(MSG_INFO,"Unicast: Consecutive errors when writing to client %s:%d during too much time, we disconnect\n", inet_ntoa(clientsocketaddr.sin_addr), ntohs(clientsocketaddr.sin_port)); - temp_client=actual_client->chan_next; - unicast_close_connection(unicast_vars,fds,clientsocket,channels); - actual_client=temp_client; + temp_client=actual_client->chan_next; + unicast_close_connection(unicast_vars,fds,clientsocket,channels,1); + actual_client=temp_client; } } } diff --git a/src/unicast_rtsp.c b/src/unicast_rtsp.c index 7035b90e..8cd3842e 100644 --- a/src/unicast_rtsp.c +++ b/src/unicast_rtsp.c @@ -87,7 +87,10 @@ int unicast_handle_rtsp_message(unicast_parameters_t *unicast_vars, unicast_clie iRet=unicast_new_message(client); if(iRet) + { + log_message(MSG_DEBUG,"Unicast : problem with unicast_new_message iRet %d\n",iRet); return iRet; + } //We search for the end of the HTTP request if(!(strlen(client->buffer)>5 && strstr(client->buffer, "\n\r\n\0"))) @@ -107,7 +110,7 @@ int unicast_handle_rtsp_message(unicast_parameters_t *unicast_vars, unicast_clie /* The client is initially supplied with an RTSP URL, on the form: rtsp://server.address:port/object.sdp */ - + /** @todo important : test if the client already exist using the session number*/ char *poscseq; int CSeq=0; int pos; @@ -116,7 +119,7 @@ int unicast_handle_rtsp_message(unicast_parameters_t *unicast_vars, unicast_clie log_message(MSG_FLOOD,"Buffer : %s\n",client->buffer); if(poscseq==NULL) { - log_message(MSG_DEBUG,"CSeq not found\n"); + log_message(MSG_DEBUG," !!!!!!!!!!!!!!!! CSeq not found\n"); /** @todo Implement an error following the RTSP protocol*/ return CLOSE_CONNECTION; //tu n'est pas content ... } @@ -164,7 +167,7 @@ int unicast_handle_rtsp_message(unicast_parameters_t *unicast_vars, unicast_clie pos_search=strstr(client->buffer ,"Transport:"); if(pos_search==NULL) { - log_message(MSG_DEBUG,"Type de transport non trouve\n"); + log_message(MSG_DEBUG,"!!!!!!!!!!!!!!!!!!!!!!!!Type de transport non trouve\n"); return CLOSE_CONNECTION; //tu n'est pas content ... } log_message(MSG_DEBUG,"Type de transport a la position %d\n", (int)(pos_search-(client->buffer))); @@ -186,7 +189,7 @@ int unicast_handle_rtsp_message(unicast_parameters_t *unicast_vars, unicast_clie } else { - log_message(MSG_INFO,"Transport unknown"); + log_message(MSG_INFO,"!!!!!!!!!!!!!!!!!!!!!!!!!Transport unknown"); return CLOSE_CONNECTION; /** @todo implement a RTSP error*/ } @@ -195,7 +198,7 @@ int unicast_handle_rtsp_message(unicast_parameters_t *unicast_vars, unicast_clie log_message(MSG_FLOOD,"Buffer : %s\n",client->buffer); if(pos_search==NULL) { - log_message(MSG_DEBUG,"Port client non trouve\n"); + log_message(MSG_DEBUG,"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!Port client non trouve\n"); /** @todo implement RTSP error */ return CLOSE_CONNECTION; //tu n'est pas content ... } @@ -204,26 +207,29 @@ int unicast_handle_rtsp_message(unicast_parameters_t *unicast_vars, unicast_clie client->rtsp_client_port = atoi(client->buffer+pos); log_message(MSG_INFO,"client_port= %d\n", client->rtsp_client_port); + + + log_message(MSG_DETAIL,"Unicast : Client ip %s port %d \n",client->client_ip,(unsigned short) client->rtsp_client_port); + + client->rtsp_Socket=makeUDPsocket (client->client_ip, client->rtsp_client_port,&client->rtsp_SocketAddr); + log_message(MSG_DETAIL,"Unicast : New RTSP socket d_IP %s, d_port:%d n°%d\n",inet_ntoa(client->rtsp_SocketAddr.sin_addr), ntohs(client->rtsp_SocketAddr.sin_port), client->rtsp_Socket); + struct sockaddr_in tempSocketAddr; unsigned int l; l = sizeof(struct sockaddr); getsockname(client->Socket, (struct sockaddr *) &tempSocketAddr, &l); - strcpy(client->rtsp_client_ip,inet_ntoa(tempSocketAddr.sin_addr)); - log_message(MSG_DETAIL,"Unicast : Client ip %s port %d \n",client->rtsp_client_ip,(unsigned short) client->rtsp_client_port); - - client->rtsp_Socket=makeUDPsocket (client->rtsp_client_ip, client->rtsp_client_port,&client->rtsp_SocketAddr); - log_message(MSG_DETAIL,"Unicast : New RTSP socket d_IP %s, d_port:%d n°%d\n",inet_ntoa(client->rtsp_SocketAddr.sin_addr), ntohs(client->rtsp_SocketAddr.sin_port), client->rtsp_Socket); l = sizeof(struct sockaddr_in); struct sockaddr_in tempsin; - //memcpy(&tempsin, &client->rtsp_SocketAddr,l); - //connect(client->rtsp_Socket,(struct sockaddr *) &tempsin, l); - memcpy(&tempsin, &client->rtsp_SocketAddr,l); + tempsin.sin_family = AF_INET; tempsin.sin_port=htons(4242); - bind(client->rtsp_Socket,(struct sockaddr *) &tempsin,l); - //l = sizeof(struct sockaddr); - //getsockname(client->rtsp_Socket, (struct sockaddr *) &tempSocketAddr, &l); - //log_message(MSG_DETAIL,"Unicast : after getsockname RTSP socket d_IP %s, d_port:%d n°%d\n",inet_ntoa(client->rtsp_SocketAddr.sin_addr), client->rtsp_SocketAddr.sin_port, client->rtsp_Socket); - //client->rtsp_server_port=client->rtsp_SocketAddr.sin_port; + tempsin.sin_addr=tempSocketAddr.sin_addr; + int iRet; + iRet=bind(client->rtsp_Socket,(struct sockaddr *) &tempsin,l); + if (iRet == 0) + { + log_message( MSG_ERROR,"bind failed : %s\n", strerror(errno)); + } + //client->rtsp_server_port=ntohs(client->rtsp_SocketAddr.sin_port); client->rtsp_server_port=4242; unicast_send_rtsp_setup(client, CSeq, TransportType); unicast_flush_client(client); @@ -234,6 +240,14 @@ int unicast_handle_rtsp_message(unicast_parameters_t *unicast_vars, unicast_clie //char *inPort=NULL; unicast_send_rtsp_play(client->Socket, CSeq, client, channels); unicast_flush_client(client); + if (client->Socket >= 0) + { + log_message(MSG_DEBUG,"Unicast: RTSP We close the control connection\n"); + unicast_close_connection(unicast_vars, fds, client->Socket, channels, 0); + client->Socket=0; + client->Control_socket_closed=1; + /** @todo important : test if the client already exist when a new client arrives, delete dead clients*/ + } return 0; } else if(strstr(client->buffer,"TEARDOWN")==client->buffer) @@ -407,8 +421,8 @@ int unicast_send_rtsp_setup (unicast_client_t *client, int CSeq, int Tsprt_type) //if (Tsprt_type==2) broadcast_type="multicast"; // else broadcast_type="unicast"; strcpy( broadcast_type,"unicast"); - log_message(MSG_DEBUG, "Transport: %s;%s;mode=play;destination=%s;client_port=%d-%d;server_port=%d\r\n", TransportType, broadcast_type, client->rtsp_client_ip, client->rtsp_client_port, client->rtsp_client_port+1, client->rtsp_server_port); - unicast_reply_write(reply, "Transport: %s;%s;mode=play;destination=%s;client_port=%d-%d;server_port=%d\r\n", TransportType, broadcast_type, client->rtsp_client_ip, client->rtsp_client_port, client->rtsp_client_port+1, client->rtsp_server_port); + log_message(MSG_DEBUG, "Transport: %s;%s;mode=play;destination=%s;client_port=%d-%d;server_port=%d\r\n", TransportType, broadcast_type, client->client_ip, client->rtsp_client_port, client->rtsp_client_port+1, client->rtsp_server_port); + unicast_reply_write(reply, "Transport: %s;%s;mode=play;destination=%s;client_port=%d-%d;server_port=%d\r\n", TransportType, broadcast_type, client->client_ip, client->rtsp_client_port, client->rtsp_client_port+1, client->rtsp_server_port); rtsp_reply_send(reply, Socket,"text/plain"); if (0 != unicast_reply_free(reply)) @@ -470,8 +484,6 @@ int unicast_send_rtsp_teardown (int Socket, int CSeq, unicast_client_t *client , rtsp_reply_prepare_headers(reply, 200, CSeq); rtsp_reply_send(reply, Socket, "text/plain"); - //unicast_close_connection(unicast_vars, fds, Socket, channels); - if (0 != unicast_reply_free(reply)) { log_message(MSG_INFO,"Unicast : Error when releasing the HTTP reply after sendinf it\n"); From 66805f44512c3ce1ae7c6bb60fd997aca045fdf4 Mon Sep 17 00:00:00 2001 From: braice Date: Sun, 24 Jan 2010 21:30:12 +0100 Subject: [PATCH 10/28] Not useful --- src/config.h | 207 --------------------------------------------------- 1 file changed, 207 deletions(-) delete mode 100644 src/config.h diff --git a/src/config.h b/src/config.h deleted file mode 100644 index af9ac98d..00000000 --- a/src/config.h +++ /dev/null @@ -1,207 +0,0 @@ -/* src/config.h. Generated from config.h.in by configure. */ -/* src/config.h.in. Generated from configure.ac by autoheader. */ - -/* Define if you want the CAM support */ -/* #undef ENABLE_CAM_SUPPORT */ - -/* Define if you want the transcoding support */ -/* #undef ENABLE_TRANSCODING */ - -/* Define to 1 if you have the `alarm' function. */ -#define HAVE_ALARM 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_ARPA_INET_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_ARPA_NAMESER_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_FCNTL_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_FFMPEG_AVCODEC_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_FFMPEG_AVFORMAT_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_FFMPEG_SWSCALE_H */ - -/* Define to 1 if you have the `gettimeofday' function. */ -#define HAVE_GETTIMEOFDAY 1 - -/* Define if you have the iconv() function and it works. */ -#define HAVE_ICONV 1 - -/* Define to 1 if you have the `inet_ntoa' function. */ -#define HAVE_INET_NTOA 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_INTTYPES_H 1 - -/* Define to 1 if you have the `avcodec' library (-lavcodec). */ -/* #undef HAVE_LIBAVCODEC */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_LIBAVCODEC_AVCODEC_H */ - -/* Define to 1 if you have the `avformat' library (-lavformat). */ -/* #undef HAVE_LIBAVFORMAT */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_LIBAVFORMAT_AVFORMAT_H */ - -/* Define to 1 if you have the `duma' library (-lduma). */ -/* #undef HAVE_LIBDUMA */ - -/* Define to 1 if you have the `dvbapi' library (-ldvbapi). */ -/* #undef HAVE_LIBDVBAPI */ - -/* Define to 1 if you have the `dvben50221' library (-ldvben50221). */ -/* #undef HAVE_LIBDVBEN50221 */ - -/* Define to 1 if you have the `pthread' library (-lpthread). */ -#define HAVE_LIBPTHREAD 1 - -/* Define to 1 if you have the `swscale' library (-lswscale). */ -/* #undef HAVE_LIBSWSCALE */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_LIBSWSCALE_SWSCALE_H */ - -/* Define to 1 if you have the `ucsi' library (-lucsi). */ -/* #undef HAVE_LIBUCSI */ - -/* Define to 1 if your system has a GNU libc compatible `malloc' function, and - to 0 otherwise. */ -#define HAVE_MALLOC 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_MEMORY_H 1 - -/* Define to 1 if you have the `memset' function. */ -#define HAVE_MEMSET 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_NETDB_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_NETINET_IN_H 1 - -/* Define to 1 if your system has a GNU libc compatible `realloc' function, - and to 0 otherwise. */ -#define HAVE_REALLOC 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_RESOLV_H 1 - -/* Define to 1 if you have the `socket' function. */ -#define HAVE_SOCKET 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STDINT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STDLIB_H 1 - -/* Define to 1 if you have the `strerror' function. */ -#define HAVE_STRERROR 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STRINGS_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STRING_H 1 - -/* Define to 1 if you have the `strstr' function. */ -#define HAVE_STRSTR 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYSLOG_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_IOCTL_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_SOCKET_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_STAT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_TIME_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_TYPES_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_UNISTD_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_VALUES_H 1 - -/* Define as const if the declaration of iconv() needs const. */ -#define ICONV_CONST - -/* Name of package */ -#define PACKAGE "mumudvb" - -/* Define to the address where bug reports for this package should be sent. */ -#define PACKAGE_BUGREPORT "mumudvb@braice.net" - -/* Define to the full name of this package. */ -#define PACKAGE_NAME "MuMuDVB" - -/* Define to the full name and version of this package. */ -#define PACKAGE_STRING "MuMuDVB 1.6.1b_20100101" - -/* Define to the one symbol short name of this package. */ -#define PACKAGE_TARNAME "mumudvb" - -/* Define to the home page for this package. */ -#define PACKAGE_URL "" - -/* Define to the version of this package. */ -#define PACKAGE_VERSION "1.6.1b_20100101" - -/* Define to 1 if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* Version number of package */ -#define VERSION "1.6.1b_20100101" - -/* Define for Solaris 2.5.1 so the uint32_t typedef from , - , or is not used. If the typedef were allowed, the - #define below would cause a syntax error. */ -/* #undef _UINT32_T */ - -/* Define for Solaris 2.5.1 so the uint8_t typedef from , - , or is not used. If the typedef were allowed, the - #define below would cause a syntax error. */ -/* #undef _UINT8_T */ - -/* Define to the type of a signed integer type of width exactly 32 bits if - such a type exists and the standard includes do not define it. */ -/* #undef int32_t */ - -/* Define to rpl_malloc if the replacement function should be used. */ -/* #undef malloc */ - -/* Define to rpl_realloc if the replacement function should be used. */ -/* #undef realloc */ - -/* Define to `unsigned int' if does not define. */ -/* #undef size_t */ - -/* Define to the type of an unsigned integer type of width exactly 16 bits if - such a type exists and the standard includes do not define it. */ -/* #undef uint16_t */ - -/* Define to the type of an unsigned integer type of width exactly 32 bits if - such a type exists and the standard includes do not define it. */ -/* #undef uint32_t */ - -/* Define to the type of an unsigned integer type of width exactly 8 bits if - such a type exists and the standard includes do not define it. */ -/* #undef uint8_t */ From c82393514004fdf35c53868e84217f6a23305ad3 Mon Sep 17 00:00:00 2001 From: braice Date: Tue, 26 Jan 2010 23:19:18 +0100 Subject: [PATCH 11/28] Unicast : possibility to choose the channel in RTSP (same path as HTTP) --- src/unicast_common.c | 84 +++++++++++++++++++++++++++++++++++++++++ src/unicast_common.h | 2 +- src/unicast_http.c | 89 ++++---------------------------------------- src/unicast_rtsp.c | 58 +++++++++++++++++++++-------- 4 files changed, 134 insertions(+), 99 deletions(-) diff --git a/src/unicast_common.c b/src/unicast_common.c index b1959072..8b1183bb 100644 --- a/src/unicast_common.c +++ b/src/unicast_common.c @@ -542,6 +542,90 @@ void unicast_flush_client(unicast_client_t *client) client->buffer=NULL; } + +/** @brief get the channel number from the asked path + +*/ +int parse_channel_path(char* buf, int *err404, int number_of_channels, mumudvb_channel_t *channels) +{ + int pos; + char *substring; + int requested_channel; + requested_channel=0; + pos=0; + + //Channel by number + //GET /bynumber/channelnumber + if(strstr(buf ,"/bynumber/")==(buf)) + { + pos+=strlen("/bynumber/"); + substring = strtok (buf+pos, " "); + if(substring == NULL) + *err404=1; + else + { + requested_channel=atoi(substring); + if(requested_channel && requested_channel<=number_of_channels) + log_message(MSG_DEBUG,"Unicast : Channel by number, number %d\n",requested_channel); + else + { + log_message(MSG_INFO,"Unicast : Channel by number, number %d out of range\n",requested_channel); + *err404=1; + requested_channel=0; + } + } + } + //Channel by autoconf_sid_list + //GET /bytsid/tsid + else if(strstr(buf ,"/bysid/")==(buf)) + { + pos+=strlen("/bytsid/"); + substring = strtok (buf+pos, " "); + if(substring == NULL) + *err404=1; + else + { + int requested_sid; + requested_sid=atoi(substring); + for(int current_channel=0; current_channelaskedChannel=-1; } - //Channel by number - //GET /bynumber/channelnumber - else if(strstr(client->buffer +pos ,"/bynumber/")==(client->buffer +pos)) - { - if(client->channel!=-1) - { - log_message(MSG_INFO,"Unicast : A channel (%d) is already streamed to this client, it shouldn't ask for a new one without closing the connection, error 501\n",client->channel); - iRet=write(client->Socket,HTTP_501_REPLY, strlen(HTTP_501_REPLY)); //iRet is to make the copiler happy we will close the connection anyways - return CLOSE_CONNECTION; //to delete the client - } - pos+=strlen("/bynumber/"); - substring = strtok (client->buffer+pos, " "); - if(substring == NULL) - err404=1; - else - { - requested_channel=atoi(substring); - if(requested_channel && requested_channel<=number_of_channels) - log_message(MSG_DEBUG,"Unicast : Channel by number, number %d\n",requested_channel); - else - { - log_message(MSG_INFO,"Unicast : Channel by number, number %d out of range\n",requested_channel); - err404=1; - requested_channel=0; - } - } - } - //Channel by autoconf_sid_list - //GET /bytsid/tsid - else if(strstr(client->buffer +pos ,"/bysid/")==(client->buffer +pos)) + requested_channel=parse_channel_path(client->buffer +pos,&err404, number_of_channels,channels); + if(requested_channel&& (client->channel!=-1)) { - if(client->channel!=-1) - { - log_message(MSG_INFO,"Unicast : A channel (%d) is already streamed to this client, it shouldn't ask for a new one without closing the connection, error 501\n",client->channel); - iRet=write(client->Socket,HTTP_501_REPLY, strlen(HTTP_501_REPLY)); //iRet is to make the copiler happy we will close the connection anyways - return CLOSE_CONNECTION; //to delete the client - } - pos+=strlen("/bytsid/"); - substring = strtok (client->buffer+pos, " "); - if(substring == NULL) - err404=1; - else - { - int requested_sid; - requested_sid=atoi(substring); - for(int current_channel=0; current_channelbuffer +pos ,"/byname/")==(client->buffer +pos)) - { - if(client->channel!=-1) - { - log_message(MSG_INFO,"Unicast : A channel is already streamed to this client, it shouldn't ask for a new one without closing the connection, error 501\n"); - iRet=write(client->Socket,HTTP_501_REPLY, strlen(HTTP_501_REPLY));//iRet is to make the copiler happy we will close the connection anyways - return CLOSE_CONNECTION; //to delete the client - } - pos+=strlen("/byname/"); - log_message(MSG_DEBUG,"Unicast : Channel by number\n"); - substring = strtok (client->buffer+pos, " "); - if(substring == NULL) - err404=1; - else - { - log_message(MSG_DEBUG,"Unicast : Channel by name, name %s\n",substring); - //search the channel - err404=1;//Temporary - /** @todo implement the search without the spaces*/ - } + log_message(MSG_INFO,"Unicast : A channel (%d) is already streamed to this client, it shouldn't ask for a new one without closing the connection, error 501\n",client->channel); + iRet=write(client->Socket,HTTP_501_REPLY, strlen(HTTP_501_REPLY)); //iRet is to make the copiler happy we will close the connection anyways + return CLOSE_CONNECTION; //to delete the client } + //Channels list - else if(strstr(client->buffer +pos ,"/channels_list.html ")==(client->buffer +pos)) + if(strstr(client->buffer +pos ,"/channels_list.html ")==(client->buffer +pos)) { //We get the host name if availaible char *hoststr; diff --git a/src/unicast_rtsp.c b/src/unicast_rtsp.c index 8cd3842e..5fe6d570 100644 --- a/src/unicast_rtsp.c +++ b/src/unicast_rtsp.c @@ -66,7 +66,7 @@ int channel_add_unicast_client(unicast_client_t *client,mumudvb_channel_t *chann int unicast_send_rtsp_describe (int Socket, int CSeq); int unicast_send_rtsp_options (int Socket, int CSeq); int unicast_send_rtsp_setup (unicast_client_t *client, int CSeq, int Tsprt_type); -int unicast_send_rtsp_play (int Socket, int CSeq, unicast_client_t *client, mumudvb_channel_t *channels); +int unicast_send_rtsp_play (int Socket, int CSeq, unicast_client_t *client, mumudvb_channel_t *channels, int number_of_channels); int unicast_send_rtsp_setup (unicast_client_t *client, int CSeq, int Tsprt_type); int unicast_send_rtsp_teardown (int Socket, int CSeq, unicast_client_t *client , mumudvb_channel_t *channels, unicast_parameters_t *unicast_vars, fds_t *fds); @@ -96,14 +96,6 @@ int unicast_handle_rtsp_message(unicast_parameters_t *unicast_vars, unicast_clie if(!(strlen(client->buffer)>5 && strstr(client->buffer, "\n\r\n\0"))) return 0; - // char *substring=NULL; - //char *substringcseq=NULL; - //char *urlPreSuffix=NULL; - //char *urlSuffix=NULL; - int requested_channel; - //int iRet; - requested_channel=0; - //unicast_reply_t* reply=NULL; log_message(MSG_DEBUG,"Unicast : End of RTSP request, we parse it\n"); // We implement RTSP protocol @@ -237,8 +229,9 @@ int unicast_handle_rtsp_message(unicast_parameters_t *unicast_vars, unicast_clie } else if(strstr(client->buffer,"PLAY")==client->buffer) { - //char *inPort=NULL; - unicast_send_rtsp_play(client->Socket, CSeq, client, channels); + iRet=unicast_send_rtsp_play(client->Socket, CSeq, client, channels, number_of_channels); + if(iRet) + return CLOSE_CONNECTION; unicast_flush_client(client); if (client->Socket >= 0) { @@ -438,8 +431,13 @@ int unicast_send_rtsp_setup (unicast_client_t *client, int CSeq, int Tsprt_type) * * @param Socket the socket on wich the information have to be sent */ -int unicast_send_rtsp_play (int Socket, int CSeq, unicast_client_t *client, mumudvb_channel_t *channels) +int unicast_send_rtsp_play (int Socket, int CSeq, unicast_client_t *client, mumudvb_channel_t *channels, int number_of_channels) { + int err404; + int requested_channel; + requested_channel=0; + char *tempstring; + err404=0; unicast_reply_t* reply = unicast_reply_init(); if (NULL == reply) { @@ -447,14 +445,42 @@ int unicast_send_rtsp_play (int Socket, int CSeq, unicast_client_t *client, mumu return -1; } - log_message(MSG_INFO,"Requete PLAY RTSP\n"); + log_message(MSG_INFO,"Unicast : Requete PLAY RTSP\n"); + + tempstring=strstr(client->buffer,"rtsp://"); + tempstring=strstr(tempstring+7,"/"); + if(tempstring) + requested_channel=parse_channel_path(tempstring,&err404, number_of_channels, channels); + else + { + log_message(MSG_INFO,"Unicast : Malformed PLAY request, we return 404\n"); + err404=1; + } + if(!requested_channel) + err404=1; + if(err404) + { + log_message(MSG_INFO,"Unicast : Path not found i.e. 404\n"); + unicast_reply_write(reply, "Session: %s\r\n", client->session); + rtsp_reply_prepare_headers(reply, 404, CSeq); + rtsp_reply_send(reply, Socket, "text/plain");; + if (0 != unicast_reply_free(reply)) { + log_message(MSG_INFO,"Unicast : Error when releasing the RTSP reply after sendinf it\n"); + } + return CLOSE_CONNECTION; //to delete the client + } + unicast_reply_write(reply, "Session: %s\r\n", client->session); rtsp_reply_prepare_headers(reply, 200, CSeq); rtsp_reply_send(reply, Socket, "text/plain"); - // TODO Ajouter l'IP du client dans la liste des IP unicast. - client->channel=0; - channel_add_unicast_client(client, &channels[0]); + if(requested_channel) + { + log_message(MSG_INFO,"Unicast : PLAY channel %d\n",requested_channel); + // TODO Ajouter l'IP du client dans la liste des IP unicast. + client->channel=requested_channel-1; + channel_add_unicast_client(client, &channels[requested_channel-1]); + } if (0 != unicast_reply_free(reply)) From 377983a5837de9eff91ef2019c983341d2155817 Mon Sep 17 00:00:00 2001 From: braice Date: Wed, 27 Jan 2010 22:14:34 +0100 Subject: [PATCH 12/28] RTSP playlist --- src/unicast_http.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/src/unicast_http.c b/src/unicast_http.c index 0c4b4062..a22ced81 100644 --- a/src/unicast_http.c +++ b/src/unicast_http.c @@ -78,6 +78,8 @@ unicast_send_streamed_channels_list (int number_of_channels, mumudvb_channel_t * int unicast_send_play_list_unicast (int number_of_channels, mumudvb_channel_t *channels, int Socket, int unicast_portOut, int perport); int +unicast_send_play_list_unicast_rtsp (int number_of_channels, mumudvb_channel_t *channels, int Socket, int unicast_portOut, int rtsp_portOut, int perport); +int unicast_send_play_list_multicast (int number_of_channels, mumudvb_channel_t* channels, int Socket, int vlc); int unicast_send_streamed_channels_list_js (int number_of_channels, mumudvb_channel_t *channels, int Socket); @@ -184,6 +186,13 @@ int unicast_handle_http_message(unicast_parameters_t *unicast_vars, unicast_clie unicast_send_play_list_unicast (number_of_channels, channels, client->Socket, unicast_vars->http_portOut, 1 ); return CLOSE_CONNECTION; //We close the connection afterwards } + //playlist RTSP, m3u + else if( (strstr(client->buffer +pos ,"/playlist_rtsp.m3u ")==(client->buffer +pos)) && unicast_vars->unicast_rtsp_enable ) + { + log_message(MSG_DETAIL,"play list\n"); + unicast_send_play_list_unicast_rtsp (number_of_channels, channels, client->Socket, unicast_vars->http_portOut, unicast_vars->rtsp_portOut, 0 ); + return CLOSE_CONNECTION; //We close the connection afterwards + } else if(strstr(client->buffer +pos ,"/playlist_multicast.m3u ")==(client->buffer +pos)) { log_message(MSG_DETAIL,"play list\n"); @@ -377,6 +386,63 @@ unicast_send_play_list_unicast (int number_of_channels, mumudvb_channel_t *chann return 0; } +/** @brief Send a basic text file containig the RTSP playlist +* +* @param number_of_channels the number of channels +* @param channels the channels array +* @param Socket the socket on wich the information have to be sent +* @param perport says if the channel have to be given by the url /bynumber or by their port +*/ +int +unicast_send_play_list_unicast_rtsp (int number_of_channels, mumudvb_channel_t *channels, int Socket, int unicast_portOut, int rtsp_portOut, int perport) +{ + int curr_channel; + + unicast_reply_t* reply = unicast_reply_init(); + if (NULL == reply) { + log_message(MSG_INFO,"Unicast : Error when creating the HTTP reply\n"); + return -1; + } + + //We get the ip address on which the client is connected + struct sockaddr_in tempSocketAddr; + unsigned int l; + l = sizeof(struct sockaddr); + getsockname(Socket, (struct sockaddr *) &tempSocketAddr, &l); + //we write the playlist + unicast_reply_write(reply, "#EXTM3U\r\n"); + + //"#EXTINF:0,title\r\nURL" + for (curr_channel = 0; curr_channel < number_of_channels; curr_channel++) + if (channels[curr_channel].streamed_channel_old) + { + if(!perport) + { + unicast_reply_write(reply, "#EXTINF:0,%s\r\nrtsp://%s:%d/bynumber/%d\r\n", + channels[curr_channel].name, + inet_ntoa(tempSocketAddr.sin_addr) , + rtsp_portOut , + curr_channel+1); + } + else if(channels[curr_channel].unicast_port) + { + unicast_reply_write(reply, "#EXTINF:0,%s\r\nrtsp://%s:%d/\r\n", + channels[curr_channel].name, + inet_ntoa(tempSocketAddr.sin_addr) , + channels[curr_channel].unicast_port); + } + } + unicast_reply_send(reply, Socket, 200, "audio/x-mpegurl"); + + if (0 != unicast_reply_free(reply)) { + log_message(MSG_INFO,"Unicast : Error when releasing the HTTP reply after sendinf it\n"); + return -1; + } + + return 0; +} + + /** @brief Send a basic text file containig the playlist * * @param number_of_channels the number of channels From 3d7a2e32a82d2429a5dd7fd1642389492544cb3f Mon Sep 17 00:00:00 2001 From: Brice DUBOST Date: Sun, 10 Apr 2011 12:20:50 +0200 Subject: [PATCH 13/28] Suffix to the version --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 2bb9081b..1d718212 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ([2.61]) -AC_INIT([MuMuDVB], [1.6.1b_20100101], [mumudvb@braice.net]) +AC_INIT([MuMuDVB], [1.6.1b_20100101_rtsp], [mumudvb@braice.net]) AC_CONFIG_SRCDIR([src/mumudvb.c]) AM_INIT_AUTOMAKE AC_CONFIG_HEADERS([src/config.h]) From 1da18b7dc5de9c4027d34f8e0043ab2b97107e45 Mon Sep 17 00:00:00 2001 From: Brice DUBOST Date: Sun, 10 Apr 2011 13:25:13 +0200 Subject: [PATCH 14/28] RTSP example --- doc/configuration_examples/rtsp.conf | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 doc/configuration_examples/rtsp.conf diff --git a/doc/configuration_examples/rtsp.conf b/doc/configuration_examples/rtsp.conf new file mode 100644 index 00000000..deda8746 --- /dev/null +++ b/doc/configuration_examples/rtsp.conf @@ -0,0 +1,9 @@ +freq=12168 +pol=v +srate=27500 +autoconfiguration=full +unicast=1 +unicast_rtsp=1 +port_rtsp=514 +multicast=0 +port_http=8090 From e09a10a144fff593f9fc98f8e43aabad7f47a8fb Mon Sep 17 00:00:00 2001 From: Brice DUBOST Date: Tue, 3 May 2011 22:09:29 +0200 Subject: [PATCH 15/28] Mistake in the example RTSP port --- doc/configuration_examples/rtsp.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/configuration_examples/rtsp.conf b/doc/configuration_examples/rtsp.conf index deda8746..edc631a4 100644 --- a/doc/configuration_examples/rtsp.conf +++ b/doc/configuration_examples/rtsp.conf @@ -4,6 +4,6 @@ srate=27500 autoconfiguration=full unicast=1 unicast_rtsp=1 -port_rtsp=514 +port_rtsp=554 multicast=0 port_http=8090 From 5118ebeb9752f8b0dfc3a73546c1c8ec60264d11 Mon Sep 17 00:00:00 2001 From: Brice DUBOST Date: Tue, 3 May 2011 22:09:57 +0200 Subject: [PATCH 16/28] VB --- configure.ac | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/configure.ac b/configure.ac index 1d718212..c67c1c7f 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ([2.61]) -AC_INIT([MuMuDVB], [1.6.1b_20100101_rtsp], [mumudvb@braice.net]) +AC_INIT([MuMuDVB], [1.6.1b_20110503_rtsp], [mumudvb@braice.net]) AC_CONFIG_SRCDIR([src/mumudvb.c]) AM_INIT_AUTOMAKE AC_CONFIG_HEADERS([src/config.h]) @@ -30,7 +30,7 @@ AM_ICONV AC_CHECK_LIB([dvbapi], [dvbdemux_set_section_filter]) AC_CHECK_LIB([ucsi], [atsc_text_segment_decode],[atsc_long_names="yes"], [atsc_long_names="no"]) #AC_CHECK_LIB([dvben50221], [en50221_stdcam_create],,,[ucsi,pthread]) -AC_CHECK_LIB([pthread], [pthread_create], [pthread="yes"], [pthread="no"]) +AC_CHECK_LIB([pthread], [pthread_create]) dnl @@ -41,15 +41,16 @@ AC_ARG_ENABLE(cam_support, if test "${enable_cam_support}" = "yes" then - AC_CHECK_LIB([pthread], [pthread_create],[], [enable_cam_support="no"]) AC_CHECK_LIB([ucsi], [atsc_text_segment_decode],[], [enable_cam_support="no"]) AC_CHECK_LIB([dvben50221], [en50221_tl_create],[], [enable_cam_support="no"]) if test "${enable_cam_support}" != "no" then AC_DEFINE(ENABLE_CAM_SUPPORT, 1, Define if you want the CAM support) else - AC_MSG_WARN([libpthread, libucsi and libdvben50221 are needed for CAM support]) + AC_MSG_WARN([libucsi and libdvben50221 are needed for CAM support]) fi +else + enable_cam_support="no" fi AM_CONDITIONAL(BUILD_CAMSUPPORT, [test "${enable_cam_support}" != "no"]) @@ -61,7 +62,8 @@ AC_ARG_ENABLE(transcoding, if test "${enable_transcoding}" = "yes" then - AC_CHECK_LIB([pthread], [pthread_create],[], [enable_transcoding="no"]) + AC_CHECK_LIB([avformat], [url_split],[AC_DEFINE(HAVE_URL_SPLIT, 1, Define if the function url_split exists)], []) + AC_CHECK_LIB([avformat], [ff_url_split],[AC_DEFINE(HAVE_FF_URL_SPLIT, 1, Define if the function ff_url_split exists)], []) AC_CHECK_HEADERS([libavcodec/avcodec.h ffmpeg/avcodec.h]) AC_CHECK_HEADERS([libavformat/avformat.h ffmpeg/avformat.h]) AC_CHECK_HEADERS([libswscale/swscale.h ffmpeg/swscale.h]) @@ -72,8 +74,10 @@ then then AC_DEFINE(ENABLE_TRANSCODING, 1, Define if you want the transcoding support) else - AC_MSG_WARN([libpthread, libavcodev, libavformat and libswscale are needed for transcoding support]) + AC_MSG_WARN([libavcodev, libavformat and libswscale are needed for transcoding support]) fi +else + enable_transcoding="no" fi AM_CONDITIONAL(BUILD_TRANSCODING, [test "${enable_transcoding}" != "no"]) @@ -157,12 +161,6 @@ else echo "Build with ATSC long names support: no" fi -if test "${pthread}" = "yes" ; then - echo "Builded with threads support: yes" -else - echo "Builded with threads support: no" -fi - echo "" echo "Debugging" echo "" From 310fa0b109bb4bea8b0ae1c743fe7f7028d9443c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludovic=20BOU=C3=89?= Date: Wed, 25 May 2011 00:08:58 +0200 Subject: [PATCH 17/28] Fix RTSP TEARDOWN reply Removing the client from the channel when TEARDOWN was receive was not working --- src/unicast_rtsp.c | 74 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 62 insertions(+), 12 deletions(-) diff --git a/src/unicast_rtsp.c b/src/unicast_rtsp.c index 5fe6d570..783b6ac2 100644 --- a/src/unicast_rtsp.c +++ b/src/unicast_rtsp.c @@ -59,6 +59,7 @@ extern int Interrupted; //from unicast_client.c int channel_add_unicast_client(unicast_client_t *client,mumudvb_channel_t *channel); +int unicast_del_client(unicast_parameters_t *unicast_vars, unicast_client_t *client, mumudvb_channel_t *channels); /** @todo handle non keepalive clients, and auto disconnect to old clients without streaming */ @@ -68,7 +69,7 @@ int unicast_send_rtsp_options (int Socket, int CSeq); int unicast_send_rtsp_setup (unicast_client_t *client, int CSeq, int Tsprt_type); int unicast_send_rtsp_play (int Socket, int CSeq, unicast_client_t *client, mumudvb_channel_t *channels, int number_of_channels); int unicast_send_rtsp_setup (unicast_client_t *client, int CSeq, int Tsprt_type); -int unicast_send_rtsp_teardown (int Socket, int CSeq, unicast_client_t *client , mumudvb_channel_t *channels, unicast_parameters_t *unicast_vars, fds_t *fds); +int unicast_send_rtsp_teardown (int Socket, int CSeq, unicast_client_t *client , mumudvb_channel_t *channels, unicast_parameters_t *unicast_vars, fds_t *fds, int number_of_channels); /** @brief Deal with an incoming message on the unicast client connection * This function will store and answer the RTSP requests @@ -123,13 +124,13 @@ int unicast_handle_rtsp_message(unicast_parameters_t *unicast_vars, unicast_clie if(strstr(client->buffer,"DESCRIBE")==client->buffer) { - unicast_send_rtsp_describe(client->Socket, CSeq); + unicast_send_rtsp_describe(client->Socket, CSeq); // send response trough RTSP Server socket unicast_flush_client(client); return 0; } else if(strstr(client->buffer,"OPTIONS")==client->buffer) { - unicast_send_rtsp_options(client->Socket, CSeq); + unicast_send_rtsp_options(client->Socket, CSeq); // send response trough RTSP Server socket unicast_flush_client(client); return 0; } @@ -223,34 +224,42 @@ int unicast_handle_rtsp_message(unicast_parameters_t *unicast_vars, unicast_clie } //client->rtsp_server_port=ntohs(client->rtsp_SocketAddr.sin_port); client->rtsp_server_port=4242; - unicast_send_rtsp_setup(client, CSeq, TransportType); + unicast_send_rtsp_setup(client, CSeq, TransportType); // send response trough RTSP Server socket unicast_flush_client(client); return 0; } else if(strstr(client->buffer,"PLAY")==client->buffer) { - iRet=unicast_send_rtsp_play(client->Socket, CSeq, client, channels, number_of_channels); + iRet=unicast_send_rtsp_play(client->Socket, CSeq, client, channels, number_of_channels); // send response trough RTSP Server socket if(iRet) return CLOSE_CONNECTION; unicast_flush_client(client); + +/** + log_message(MSG_DETAIL,"Unicast : We delete the client %s:%d, socket %d\n",inet_ntoa(client->Socket.sin_addr), ntohs(client->Socket.sin_port), client->Socket); if (client->Socket >= 0) { log_message(MSG_DEBUG,"Unicast: RTSP We close the control connection\n"); unicast_close_connection(unicast_vars, fds, client->Socket, channels, 0); client->Socket=0; client->Control_socket_closed=1; - /** @todo important : test if the client already exist when a new client arrives, delete dead clients*/ - } + + + + }*/ + +/** @todo important : test if the client already exist when a new client arrives, delete dead clients*/ + return 0; } else if(strstr(client->buffer,"TEARDOWN")==client->buffer) { - unicast_send_rtsp_teardown(client->Socket, CSeq, client, channels, unicast_vars, fds); + unicast_send_rtsp_teardown(client->Socket, CSeq, client, channels, unicast_vars, fds, number_of_channels); return CLOSE_CONNECTION; } else { - log_message(MSG_WARN,"rate ... \n"); + log_message(MSG_WARN,"La commande n'est pas comprise pas le serveur\n"); unicast_flush_client(client); } @@ -389,7 +398,7 @@ int unicast_send_rtsp_options (int Socket, int CSeq) */ int unicast_send_rtsp_setup (unicast_client_t *client, int CSeq, int Tsprt_type) { - int Socket=client->Socket; + int Socket=client->Socket; // On ne recupere pas la socket en parametre mais depuis la structure "client" char TransportType[20], broadcast_type[20]; unicast_reply_t* reply = unicast_reply_init(); if (NULL == reply) @@ -485,7 +494,7 @@ int unicast_send_rtsp_play (int Socket, int CSeq, unicast_client_t *client, mumu if (0 != unicast_reply_free(reply)) { - log_message(MSG_INFO,"Unicast : Error when releasing the HTTP reply after sendinf it\n"); + log_message(MSG_INFO,"Unicast : Error when releasing the RTSP reply after sendinf it\n"); return -1; } @@ -496,8 +505,14 @@ int unicast_send_rtsp_play (int Socket, int CSeq, unicast_client_t *client, mumu * * @param Socket the socket on wich the information have to be sent */ -int unicast_send_rtsp_teardown (int Socket, int CSeq, unicast_client_t *client , mumudvb_channel_t *channels, unicast_parameters_t *unicast_vars, fds_t *fds) +int unicast_send_rtsp_teardown (int Socket, int CSeq, unicast_client_t *client , mumudvb_channel_t *channels, unicast_parameters_t *unicast_vars, fds_t *fds, int number_of_channels) { + int err404=0; + int requested_channel; + requested_channel=0; + char *tempstring; + err404=0; + unicast_reply_t* reply = unicast_reply_init(); if (NULL == reply) { @@ -507,9 +522,44 @@ int unicast_send_rtsp_teardown (int Socket, int CSeq, unicast_client_t *client , log_message(MSG_INFO,"Requete TEARDOWN RTSP\n"); + tempstring=strstr(client->buffer,"rtsp://"); + tempstring=strstr(tempstring+7,"/"); + if(tempstring) + requested_channel=parse_channel_path(tempstring,&err404, number_of_channels, channels); + else + { + log_message(MSG_INFO,"Unicast : Malformed TEARDOWN request, we return 404\n"); + err404=1; + } + if(!requested_channel) + err404=1; + if(err404) + { + log_message(MSG_INFO,"Unicast : Path not found i.e. 404\n"); + unicast_reply_write(reply, "Session: %s\r\n", client->session); + rtsp_reply_prepare_headers(reply, 404, CSeq); + rtsp_reply_send(reply, Socket, "text/plain");; + if (0 != unicast_reply_free(reply)) { + log_message(MSG_INFO,"Unicast : Error when releasing the RTSP reply after sendinf it\n"); + } + return CLOSE_CONNECTION; //to delete the client + } + + unicast_reply_write(reply, "Session: %s\r\n", client->session); rtsp_reply_prepare_headers(reply, 200, CSeq); rtsp_reply_send(reply, Socket, "text/plain"); + if(requested_channel) + { + log_message(MSG_INFO,"Unicast : TEARDOWN channel %d\n",requested_channel); + // TODO Supprimer l'IP du client dans la liste des IP unicast. + //client->channel=requested_channel-1; + log_message(MSG_INFO,"Unicast : On supprime la chaine %d de la liste de diffusion de la socket\n", requested_channel-1); + + log_message(MSG_INFO,"Unicast : Valeur dans le tableau channels de la socket %d\n", &channels[requested_channel-1]); + //unicast_del_client(unicast_vars, client, &channels[requested_channel-1]); + } + if (0 != unicast_reply_free(reply)) { log_message(MSG_INFO,"Unicast : Error when releasing the HTTP reply after sendinf it\n"); From 9847391bac4b5edfc1634cc94cff110543f9c8dd Mon Sep 17 00:00:00 2001 From: Brice DUBOST Date: Sun, 5 Jun 2011 13:50:22 +0200 Subject: [PATCH 18/28] VB --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index c67c1c7f..e8eb294e 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ([2.61]) -AC_INIT([MuMuDVB], [1.6.1b_20110503_rtsp], [mumudvb@braice.net]) +AC_INIT([MuMuDVB], [1.6.1b_20110605_rtsp], [mumudvb@braice.net]) AC_CONFIG_SRCDIR([src/mumudvb.c]) AM_INIT_AUTOMAKE AC_CONFIG_HEADERS([src/config.h]) From 92982465ba64347b8d08f9174761331d1a12413f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludovic=20BOU=C3=89?= Date: Thu, 2 Jun 2011 17:27:09 +0200 Subject: [PATCH 19/28] Use rtsp_portOut instead of http_portOut get from the config file : port_rtsp=554 --- src/unicast_rtsp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/unicast_rtsp.c b/src/unicast_rtsp.c index 783b6ac2..4e839f5c 100644 --- a/src/unicast_rtsp.c +++ b/src/unicast_rtsp.c @@ -214,7 +214,7 @@ int unicast_handle_rtsp_message(unicast_parameters_t *unicast_vars, unicast_clie l = sizeof(struct sockaddr_in); struct sockaddr_in tempsin; tempsin.sin_family = AF_INET; - tempsin.sin_port=htons(4242); + tempsin.sin_port=htons(unicast_vars->rtsp_portOut); tempsin.sin_addr=tempSocketAddr.sin_addr; int iRet; iRet=bind(client->rtsp_Socket,(struct sockaddr *) &tempsin,l); @@ -223,7 +223,7 @@ int unicast_handle_rtsp_message(unicast_parameters_t *unicast_vars, unicast_clie log_message( MSG_ERROR,"bind failed : %s\n", strerror(errno)); } //client->rtsp_server_port=ntohs(client->rtsp_SocketAddr.sin_port); - client->rtsp_server_port=4242; + client->rtsp_server_port=unicast_vars->rtsp_portOut; unicast_send_rtsp_setup(client, CSeq, TransportType); // send response trough RTSP Server socket unicast_flush_client(client); return 0; From 43c1328e6a31b4f7b856391d7922726900c36c64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludovic=20BOU=C3=89?= Date: Thu, 2 Jun 2011 18:39:47 +0200 Subject: [PATCH 20/28] Prepare new error types --- src/unicast_rtsp.c | 129 +++++++++++++++++++++++---------------------- 1 file changed, 65 insertions(+), 64 deletions(-) diff --git a/src/unicast_rtsp.c b/src/unicast_rtsp.c index 4e839f5c..7ece1248 100644 --- a/src/unicast_rtsp.c +++ b/src/unicast_rtsp.c @@ -74,7 +74,6 @@ int unicast_send_rtsp_teardown (int Socket, int CSeq, unicast_client_t *client , /** @brief Deal with an incoming message on the unicast client connection * This function will store and answer the RTSP requests * -* * @param unicast_vars the unicast parameters * @param client The client from which the message was received * @param channels the channel array @@ -93,16 +92,15 @@ int unicast_handle_rtsp_message(unicast_parameters_t *unicast_vars, unicast_clie return iRet; } - //We search for the end of the HTTP request + //We search for the end of the RTSP request if(!(strlen(client->buffer)>5 && strstr(client->buffer, "\n\r\n\0"))) return 0; - log_message(MSG_DEBUG,"Unicast : End of RTSP request, we parse it\n"); - // We implement RTSP protocol + /* The client is initially supplied with an RTSP URL, on the form: - rtsp://server.address:port/object.sdp - */ + rtsp://server.address:port/object.sdp */ + /** @todo important : test if the client already exist using the session number*/ char *poscseq; int CSeq=0; @@ -112,11 +110,11 @@ int unicast_handle_rtsp_message(unicast_parameters_t *unicast_vars, unicast_clie log_message(MSG_FLOOD,"Buffer : %s\n",client->buffer); if(poscseq==NULL) { - log_message(MSG_DEBUG," !!!!!!!!!!!!!!!! CSeq not found\n"); + log_message(MSG_DEBUG,"Sequence number not found\n"); /** @todo Implement an error following the RTSP protocol*/ return CLOSE_CONNECTION; //tu n'est pas content ... } - log_message(MSG_DEBUG,"CSeq a la position %d\n", (int)(poscseq-(client->buffer))); + log_message(MSG_DEBUG,"CSeq found at position %d\n", (int)(poscseq-(client->buffer))); pos=(int)(poscseq-(client->buffer)); pos+=strlen("Cseq: "); CSeq = atoi(client->buffer+pos); //replace by CSeq = atoi(poscseq+strlen("Cseq: ")); @@ -150,20 +148,17 @@ int unicast_handle_rtsp_message(unicast_parameters_t *unicast_vars, unicast_clie session[15]='\0'; strcpy(client->session, session); log_message(MSG_DEBUG,"Session : %s\n", session ); - // Parse le type de transport - int TransportType=TRANSPORT_UNDEFINED; // RTP/AVP | RTP/AVP/UDP = 0 , RTP/AVP/TCP=1 - // Transport: RTP/AVP - /* transport-protocol = "RTP" - profile = "AVP" - lower-transport = "TCP" | "UDP" */ - // Parse le type de transport + + // We parse transport type + int TransportType=TRANSPORT_UNDEFINED; // RTP/AVP=0 | RTP/AVP/UDP = 0 , RTP/AVP/TCP=1 pos_search=strstr(client->buffer ,"Transport:"); if(pos_search==NULL) { - log_message(MSG_DEBUG,"!!!!!!!!!!!!!!!!!!!!!!!!Type de transport non trouve\n"); - return CLOSE_CONNECTION; //tu n'est pas content ... + log_message(MSG_DEBUG,"Transport type not found\n"); + return CLOSE_CONNECTION; } - log_message(MSG_DEBUG,"Type de transport a la position %d\n", (int)(pos_search-(client->buffer))); + + log_message(MSG_DEBUG,"Transport type at position %d\n", (int)(pos_search-(client->buffer))); pos=(int)(pos_search-(client->buffer)); pos+=strlen("Transport: "); if (!strncmp (client->buffer+pos, "RTP/AVP/TCP", strlen("RTP/AVP/TCP"))) { @@ -182,8 +177,17 @@ int unicast_handle_rtsp_message(unicast_parameters_t *unicast_vars, unicast_clie } else { - log_message(MSG_INFO,"!!!!!!!!!!!!!!!!!!!!!!!!!Transport unknown"); - return CLOSE_CONNECTION; /** @todo implement a RTSP error*/ + log_message(MSG_INFO,"Error 461 : Unsupported transport type"); +/* rtsp_reply_prepare_headers(reply, 461, CSeq); + rtsp_reply_send(reply, Socket,"text/plain"); + + if (0 != unicast_reply_free(reply)) + { + log_message(MSG_INFO,"Unicast : Error when releasing the RTSP reply after sendinf it\n"); + return -1; + } +*/ + return CLOSE_CONNECTION; } // Parse le port client @@ -191,9 +195,12 @@ int unicast_handle_rtsp_message(unicast_parameters_t *unicast_vars, unicast_clie log_message(MSG_FLOOD,"Buffer : %s\n",client->buffer); if(pos_search==NULL) { - log_message(MSG_DEBUG,"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!Port client non trouve\n"); - /** @todo implement RTSP error */ - return CLOSE_CONNECTION; //tu n'est pas content ... + log_message(MSG_DEBUG,"Client ports not found\n"); + /** @todo implement RTSP error + rtsp_reply_prepare_headers(reply, 451, CSeq); + rtsp_reply_send(reply, Socket, "text/plain"); */ + + return CLOSE_CONNECTION; } pos=(int)(pos_search-(client->buffer)); pos+=strlen("client_port="); @@ -235,19 +242,6 @@ int unicast_handle_rtsp_message(unicast_parameters_t *unicast_vars, unicast_clie return CLOSE_CONNECTION; unicast_flush_client(client); -/** - log_message(MSG_DETAIL,"Unicast : We delete the client %s:%d, socket %d\n",inet_ntoa(client->Socket.sin_addr), ntohs(client->Socket.sin_port), client->Socket); - if (client->Socket >= 0) - { - log_message(MSG_DEBUG,"Unicast: RTSP We close the control connection\n"); - unicast_close_connection(unicast_vars, fds, client->Socket, channels, 0); - client->Socket=0; - client->Control_socket_closed=1; - - - - }*/ - /** @todo important : test if the client already exist when a new client arrives, delete dead clients*/ return 0; @@ -259,7 +253,8 @@ int unicast_handle_rtsp_message(unicast_parameters_t *unicast_vars, unicast_clie } else { - log_message(MSG_WARN,"La commande n'est pas comprise pas le serveur\n"); + // @todo return a 400 error + log_message(MSG_WARN,"This is not understood by the server\n"); unicast_flush_client(client); } @@ -279,9 +274,18 @@ int rtsp_reply_prepare_headers(unicast_reply_t *reply, int code, int CSeq) case 200: unicast_reply_write(reply, "200 OK\r\n"); break; + case 400: + unicast_reply_write(reply, "400 Bad Request\r\n"); + break; case 404: unicast_reply_write(reply, "404 Not found\r\n"); break; + case 451: + unicast_reply_write(reply, "451 Invalid parameter\r\n"); + break; + case 454: + unicast_reply_write(reply, "454 Session Not Found\r\n"); + break; case 503: unicast_reply_write(reply, "503 Too many clients\r\n"); break; @@ -297,6 +301,9 @@ int rtsp_reply_prepare_headers(unicast_reply_t *reply, int code, int CSeq) } +/** @brief Send a RTSP message + * The method add headers the to a reply message + */ int rtsp_reply_send(unicast_reply_t *reply, int socket, const char* content_type) { //we add the header information @@ -334,7 +341,7 @@ int unicast_send_rtsp_describe (int Socket, int CSeq) log_message(MSG_INFO,"Unicast : Error when creating the RTSP reply\n"); return -1; } - log_message(MSG_INFO,"Requete DESCRIBE RTSP\n"); + log_message(MSG_INFO,"RTSP DESCRIBE request\n"); char *TransportType="RTP/AVP"; //if (TransportType) TransportType="RTP/AVP/TCP"; // =0:UDP, =1:TCP @@ -346,17 +353,15 @@ int unicast_send_rtsp_describe (int Socket, int CSeq) unicast_reply_write(reply, "s=unknown\r\n"); unicast_reply_write(reply, "i=unknown\r\n"); unicast_reply_write(reply, "c=IN IP4 0.0.0.0\r\n"); - //unicast_reply_write(reply, "c=IN IP4 239.100.1.0/2\r\n"); Pour le multicast RTSP unicast_reply_write(reply, "t=0 0\r\n"); unicast_reply_write(reply, "m=video 0 %s 33\r\n", TransportType); - // unicast_reply_write(reply, "a=control:rtsp://192.168.15.151:4242/rtsp/stream?namespace=1&service=201&flavour=ld\r\n"); rtsp_reply_prepare_headers(reply, 200, CSeq); rtsp_reply_send(reply, Socket,"application/sdp"); if (0 != unicast_reply_free(reply)) { - log_message(MSG_INFO,"Unicast : Error when releasing the HTTP reply after sendinf it\n"); + log_message(MSG_INFO,"Unicast : Error when releasing the RTSP reply after sendinf it\n"); return -1; } @@ -377,14 +382,14 @@ int unicast_send_rtsp_options (int Socket, int CSeq) return -1; } - log_message(MSG_INFO,"Requete OPTIONS RTSP\n"); ; + log_message(MSG_INFO,"RTSP OPTIONS request\n"); ; rtsp_reply_prepare_headers(reply, 200, CSeq); rtsp_reply_send(reply, Socket,"text/plain"); if (0 != unicast_reply_free(reply)) { - log_message(MSG_INFO,"Unicast : Error when releasing the HTTP reply after sendinf it\n"); + log_message(MSG_INFO,"Unicast : Error when releasing the RTSP reply after sendinf it\n"); return -1; } @@ -407,7 +412,7 @@ int unicast_send_rtsp_setup (unicast_client_t *client, int CSeq, int Tsprt_type) return -1; } - log_message(MSG_INFO,"Requete SETUP RTSP\n"); + log_message(MSG_INFO,"RTSP SETUP request\n"); //unicast_reply_write(reply, RTSP_SETUP_REPLY); rtsp_reply_prepare_headers(reply, 200, CSeq); @@ -419,9 +424,9 @@ int unicast_send_rtsp_setup (unicast_client_t *client, int CSeq, int Tsprt_type) else strcpy(TransportType,"RTP/AVP"); - //TODO Get the broadcast_type from the DESCRIBE request - //if (Tsprt_type==2) broadcast_type="multicast"; - // else broadcast_type="unicast"; + /* @todo Get the broadcast_type from the DESCRIBE request + if (Tsprt_type==2) broadcast_type="multicast"; + else broadcast_type="unicast"; */ strcpy( broadcast_type,"unicast"); log_message(MSG_DEBUG, "Transport: %s;%s;mode=play;destination=%s;client_port=%d-%d;server_port=%d\r\n", TransportType, broadcast_type, client->client_ip, client->rtsp_client_port, client->rtsp_client_port+1, client->rtsp_server_port); unicast_reply_write(reply, "Transport: %s;%s;mode=play;destination=%s;client_port=%d-%d;server_port=%d\r\n", TransportType, broadcast_type, client->client_ip, client->rtsp_client_port, client->rtsp_client_port+1, client->rtsp_server_port); @@ -429,7 +434,7 @@ int unicast_send_rtsp_setup (unicast_client_t *client, int CSeq, int Tsprt_type) if (0 != unicast_reply_free(reply)) { - log_message(MSG_INFO,"Unicast : Error when releasing the HTTP reply after sendinf it\n"); + log_message(MSG_INFO,"Unicast : Error when releasing the RTSP reply after sendinf it\n"); return -1; } @@ -486,7 +491,7 @@ int unicast_send_rtsp_play (int Socket, int CSeq, unicast_client_t *client, mumu if(requested_channel) { log_message(MSG_INFO,"Unicast : PLAY channel %d\n",requested_channel); - // TODO Ajouter l'IP du client dans la liste des IP unicast. + // @toto Add client IP into the unicast list. client->channel=requested_channel-1; channel_add_unicast_client(client, &channels[requested_channel-1]); } @@ -507,11 +512,10 @@ int unicast_send_rtsp_play (int Socket, int CSeq, unicast_client_t *client, mumu */ int unicast_send_rtsp_teardown (int Socket, int CSeq, unicast_client_t *client , mumudvb_channel_t *channels, unicast_parameters_t *unicast_vars, fds_t *fds, int number_of_channels) { - int err404=0; + int err=0; int requested_channel; requested_channel=0; char *tempstring; - err404=0; unicast_reply_t* reply = unicast_reply_init(); if (NULL == reply) @@ -525,19 +529,18 @@ int unicast_send_rtsp_teardown (int Socket, int CSeq, unicast_client_t *client , tempstring=strstr(client->buffer,"rtsp://"); tempstring=strstr(tempstring+7,"/"); if(tempstring) - requested_channel=parse_channel_path(tempstring,&err404, number_of_channels, channels); + requested_channel=parse_channel_path(tempstring,&err, number_of_channels, channels); else { - log_message(MSG_INFO,"Unicast : Malformed TEARDOWN request, we return 404\n"); - err404=1; + log_message(MSG_INFO,"Unicast : Malformed TEARDOWN request, we return 400\n"); } if(!requested_channel) - err404=1; - if(err404) + err=404; + if(err!=0) { log_message(MSG_INFO,"Unicast : Path not found i.e. 404\n"); unicast_reply_write(reply, "Session: %s\r\n", client->session); - rtsp_reply_prepare_headers(reply, 404, CSeq); + rtsp_reply_prepare_headers(reply, err, CSeq); rtsp_reply_send(reply, Socket, "text/plain");; if (0 != unicast_reply_free(reply)) { log_message(MSG_INFO,"Unicast : Error when releasing the RTSP reply after sendinf it\n"); @@ -551,18 +554,16 @@ int unicast_send_rtsp_teardown (int Socket, int CSeq, unicast_client_t *client , if(requested_channel) { - log_message(MSG_INFO,"Unicast : TEARDOWN channel %d\n",requested_channel); - // TODO Supprimer l'IP du client dans la liste des IP unicast. - //client->channel=requested_channel-1; - log_message(MSG_INFO,"Unicast : On supprime la chaine %d de la liste de diffusion de la socket\n", requested_channel-1); + log_message(MSG_INFO,"Unicast : TEARDOWN for channel n°%d\n",requested_channel); + /* @todo Delete client IP in the socket list. - log_message(MSG_INFO,"Unicast : Valeur dans le tableau channels de la socket %d\n", &channels[requested_channel-1]); - //unicast_del_client(unicast_vars, client, &channels[requested_channel-1]); + log_message(MSG_DEBUG,"Unicast : We delete channel n°%d from the socket list\n", requested_channel-1); + unicast_del_client(unicast_vars, client, &channels[requested_channel-1]); */ } if (0 != unicast_reply_free(reply)) { - log_message(MSG_INFO,"Unicast : Error when releasing the HTTP reply after sendinf it\n"); + log_message(MSG_INFO,"Unicast : Error when releasing the RTSP reply after sendinf it\n"); return -1; } From 455ba343cd497798d9520c8862ec68727b2ad6a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludovic=20BOU=C3=89?= Date: Thu, 2 Jun 2011 18:51:18 +0200 Subject: [PATCH 21/28] Better methods names --- src/unicast_rtsp.c | 59 ++++++++++++++++++++++------------------------ 1 file changed, 28 insertions(+), 31 deletions(-) diff --git a/src/unicast_rtsp.c b/src/unicast_rtsp.c index 7ece1248..f8c7e2a5 100644 --- a/src/unicast_rtsp.c +++ b/src/unicast_rtsp.c @@ -64,12 +64,11 @@ int unicast_del_client(unicast_parameters_t *unicast_vars, unicast_client_t *cli /** @todo handle non keepalive clients, and auto disconnect to old clients without streaming */ -int unicast_send_rtsp_describe (int Socket, int CSeq); -int unicast_send_rtsp_options (int Socket, int CSeq); -int unicast_send_rtsp_setup (unicast_client_t *client, int CSeq, int Tsprt_type); -int unicast_send_rtsp_play (int Socket, int CSeq, unicast_client_t *client, mumudvb_channel_t *channels, int number_of_channels); -int unicast_send_rtsp_setup (unicast_client_t *client, int CSeq, int Tsprt_type); -int unicast_send_rtsp_teardown (int Socket, int CSeq, unicast_client_t *client , mumudvb_channel_t *channels, unicast_parameters_t *unicast_vars, fds_t *fds, int number_of_channels); +int unicast_rtsp_describe_reply (int Socket, int CSeq); +int unicast_rtsp_options_reply (int Socket, int CSeq); +int unicast_rtsp_setup_reply (unicast_client_t *client, int CSeq, int Tsprt_type); +int unicast_rtsp_play_reply (int Socket, int CSeq, unicast_client_t *client, mumudvb_channel_t *channels, int number_of_channels); +int unicast_rtsp_teardown_reply (int Socket, int CSeq, unicast_client_t *client , mumudvb_channel_t *channels, unicast_parameters_t *unicast_vars, fds_t *fds, int number_of_channels); /** @brief Deal with an incoming message on the unicast client connection * This function will store and answer the RTSP requests @@ -122,13 +121,13 @@ int unicast_handle_rtsp_message(unicast_parameters_t *unicast_vars, unicast_clie if(strstr(client->buffer,"DESCRIBE")==client->buffer) { - unicast_send_rtsp_describe(client->Socket, CSeq); // send response trough RTSP Server socket + unicast_rtsp_describe_reply(client->Socket, CSeq); // send response trough RTSP Server socket unicast_flush_client(client); return 0; } else if(strstr(client->buffer,"OPTIONS")==client->buffer) { - unicast_send_rtsp_options(client->Socket, CSeq); // send response trough RTSP Server socket + unicast_rtsp_options_reply(client->Socket, CSeq); // send response trough RTSP Server socket unicast_flush_client(client); return 0; } @@ -179,7 +178,7 @@ int unicast_handle_rtsp_message(unicast_parameters_t *unicast_vars, unicast_clie { log_message(MSG_INFO,"Error 461 : Unsupported transport type"); /* rtsp_reply_prepare_headers(reply, 461, CSeq); - rtsp_reply_send(reply, Socket,"text/plain"); + rtsp_send_reply(reply, Socket,"text/plain"); if (0 != unicast_reply_free(reply)) { @@ -190,7 +189,7 @@ int unicast_handle_rtsp_message(unicast_parameters_t *unicast_vars, unicast_clie return CLOSE_CONNECTION; } - // Parse le port client + // Parse client ports pos_search=strstr(client->buffer ,"client_port="); log_message(MSG_FLOOD,"Buffer : %s\n",client->buffer); if(pos_search==NULL) @@ -198,7 +197,7 @@ int unicast_handle_rtsp_message(unicast_parameters_t *unicast_vars, unicast_clie log_message(MSG_DEBUG,"Client ports not found\n"); /** @todo implement RTSP error rtsp_reply_prepare_headers(reply, 451, CSeq); - rtsp_reply_send(reply, Socket, "text/plain"); */ + rtsp_send_reply(reply, Socket, "text/plain"); */ return CLOSE_CONNECTION; } @@ -231,13 +230,13 @@ int unicast_handle_rtsp_message(unicast_parameters_t *unicast_vars, unicast_clie } //client->rtsp_server_port=ntohs(client->rtsp_SocketAddr.sin_port); client->rtsp_server_port=unicast_vars->rtsp_portOut; - unicast_send_rtsp_setup(client, CSeq, TransportType); // send response trough RTSP Server socket + unicast_rtsp_setup_reply(client, CSeq, TransportType); // send response trough RTSP Server socket unicast_flush_client(client); return 0; } else if(strstr(client->buffer,"PLAY")==client->buffer) { - iRet=unicast_send_rtsp_play(client->Socket, CSeq, client, channels, number_of_channels); // send response trough RTSP Server socket + iRet=unicast_rtsp_play_reply(client->Socket, CSeq, client, channels, number_of_channels); // send response trough RTSP Server socket if(iRet) return CLOSE_CONNECTION; unicast_flush_client(client); @@ -248,7 +247,7 @@ int unicast_handle_rtsp_message(unicast_parameters_t *unicast_vars, unicast_clie } else if(strstr(client->buffer,"TEARDOWN")==client->buffer) { - unicast_send_rtsp_teardown(client->Socket, CSeq, client, channels, unicast_vars, fds, number_of_channels); + unicast_rtsp_teardown_reply(client->Socket, CSeq, client, channels, unicast_vars, fds, number_of_channels); return CLOSE_CONNECTION; } else @@ -304,7 +303,7 @@ int rtsp_reply_prepare_headers(unicast_reply_t *reply, int code, int CSeq) /** @brief Send a RTSP message * The method add headers the to a reply message */ -int rtsp_reply_send(unicast_reply_t *reply, int socket, const char* content_type) +int rtsp_send_reply(unicast_reply_t *reply, int socket, const char* content_type) { //we add the header information reply->type = REPLY_HEADER; @@ -333,7 +332,7 @@ int rtsp_reply_send(unicast_reply_t *reply, int socket, const char* content_type * initialization phase of RTSP. * @param Socket the socket on wich the information have to be sent */ -int unicast_send_rtsp_describe (int Socket, int CSeq) +int unicast_rtsp_describe_reply (int Socket, int CSeq) { unicast_reply_t* reply = unicast_reply_init(); if (NULL == reply) @@ -357,7 +356,7 @@ int unicast_send_rtsp_describe (int Socket, int CSeq) unicast_reply_write(reply, "m=video 0 %s 33\r\n", TransportType); rtsp_reply_prepare_headers(reply, 200, CSeq); - rtsp_reply_send(reply, Socket,"application/sdp"); + rtsp_send_reply(reply, Socket,"application/sdp"); if (0 != unicast_reply_free(reply)) { @@ -373,7 +372,7 @@ int unicast_send_rtsp_describe (int Socket, int CSeq) * * @param Socket the socket on wich the information have to be sent */ -int unicast_send_rtsp_options (int Socket, int CSeq) +int unicast_rtsp_options_reply (int Socket, int CSeq) { unicast_reply_t* reply = unicast_reply_init(); if (NULL == reply) @@ -385,7 +384,7 @@ int unicast_send_rtsp_options (int Socket, int CSeq) log_message(MSG_INFO,"RTSP OPTIONS request\n"); ; rtsp_reply_prepare_headers(reply, 200, CSeq); - rtsp_reply_send(reply, Socket,"text/plain"); + rtsp_send_reply(reply, Socket,"text/plain"); if (0 != unicast_reply_free(reply)) { @@ -401,9 +400,9 @@ int unicast_send_rtsp_options (int Socket, int CSeq) * * @param Socket the socket on wich the information have to be sent */ -int unicast_send_rtsp_setup (unicast_client_t *client, int CSeq, int Tsprt_type) +int unicast_rtsp_setup_reply (unicast_client_t *client, int CSeq, int Tsprt_type) { - int Socket=client->Socket; // On ne recupere pas la socket en parametre mais depuis la structure "client" + int Socket=client->Socket; char TransportType[20], broadcast_type[20]; unicast_reply_t* reply = unicast_reply_init(); if (NULL == reply) @@ -413,7 +412,6 @@ int unicast_send_rtsp_setup (unicast_client_t *client, int CSeq, int Tsprt_type) } log_message(MSG_INFO,"RTSP SETUP request\n"); - //unicast_reply_write(reply, RTSP_SETUP_REPLY); rtsp_reply_prepare_headers(reply, 200, CSeq); reply->type = REPLY_HEADER; @@ -430,7 +428,7 @@ int unicast_send_rtsp_setup (unicast_client_t *client, int CSeq, int Tsprt_type) strcpy( broadcast_type,"unicast"); log_message(MSG_DEBUG, "Transport: %s;%s;mode=play;destination=%s;client_port=%d-%d;server_port=%d\r\n", TransportType, broadcast_type, client->client_ip, client->rtsp_client_port, client->rtsp_client_port+1, client->rtsp_server_port); unicast_reply_write(reply, "Transport: %s;%s;mode=play;destination=%s;client_port=%d-%d;server_port=%d\r\n", TransportType, broadcast_type, client->client_ip, client->rtsp_client_port, client->rtsp_client_port+1, client->rtsp_server_port); - rtsp_reply_send(reply, Socket,"text/plain"); + rtsp_send_reply(reply, Socket,"text/plain"); if (0 != unicast_reply_free(reply)) { @@ -445,7 +443,7 @@ int unicast_send_rtsp_setup (unicast_client_t *client, int CSeq, int Tsprt_type) * * @param Socket the socket on wich the information have to be sent */ -int unicast_send_rtsp_play (int Socket, int CSeq, unicast_client_t *client, mumudvb_channel_t *channels, int number_of_channels) +int unicast_rtsp_play_reply (int Socket, int CSeq, unicast_client_t *client, mumudvb_channel_t *channels, int number_of_channels) { int err404; int requested_channel; @@ -477,7 +475,7 @@ int unicast_send_rtsp_play (int Socket, int CSeq, unicast_client_t *client, mumu log_message(MSG_INFO,"Unicast : Path not found i.e. 404\n"); unicast_reply_write(reply, "Session: %s\r\n", client->session); rtsp_reply_prepare_headers(reply, 404, CSeq); - rtsp_reply_send(reply, Socket, "text/plain");; + rtsp_send_reply(reply, Socket, "text/plain");; if (0 != unicast_reply_free(reply)) { log_message(MSG_INFO,"Unicast : Error when releasing the RTSP reply after sendinf it\n"); } @@ -486,7 +484,7 @@ int unicast_send_rtsp_play (int Socket, int CSeq, unicast_client_t *client, mumu unicast_reply_write(reply, "Session: %s\r\n", client->session); rtsp_reply_prepare_headers(reply, 200, CSeq); - rtsp_reply_send(reply, Socket, "text/plain"); + rtsp_send_reply(reply, Socket, "text/plain"); if(requested_channel) { @@ -496,7 +494,6 @@ int unicast_send_rtsp_play (int Socket, int CSeq, unicast_client_t *client, mumu channel_add_unicast_client(client, &channels[requested_channel-1]); } - if (0 != unicast_reply_free(reply)) { log_message(MSG_INFO,"Unicast : Error when releasing the RTSP reply after sendinf it\n"); @@ -510,7 +507,7 @@ int unicast_send_rtsp_play (int Socket, int CSeq, unicast_client_t *client, mumu * * @param Socket the socket on wich the information have to be sent */ -int unicast_send_rtsp_teardown (int Socket, int CSeq, unicast_client_t *client , mumudvb_channel_t *channels, unicast_parameters_t *unicast_vars, fds_t *fds, int number_of_channels) +int unicast_rtsp_teardown_reply (int Socket, int CSeq, unicast_client_t *client , mumudvb_channel_t *channels, unicast_parameters_t *unicast_vars, fds_t *fds, int number_of_channels) { int err=0; int requested_channel; @@ -524,7 +521,7 @@ int unicast_send_rtsp_teardown (int Socket, int CSeq, unicast_client_t *client , return -1; } - log_message(MSG_INFO,"Requete TEARDOWN RTSP\n"); + log_message(MSG_INFO,"RTSP TEARDOWN request\n"); tempstring=strstr(client->buffer,"rtsp://"); tempstring=strstr(tempstring+7,"/"); @@ -541,7 +538,7 @@ int unicast_send_rtsp_teardown (int Socket, int CSeq, unicast_client_t *client , log_message(MSG_INFO,"Unicast : Path not found i.e. 404\n"); unicast_reply_write(reply, "Session: %s\r\n", client->session); rtsp_reply_prepare_headers(reply, err, CSeq); - rtsp_reply_send(reply, Socket, "text/plain");; + rtsp_send_reply(reply, Socket, "text/plain");; if (0 != unicast_reply_free(reply)) { log_message(MSG_INFO,"Unicast : Error when releasing the RTSP reply after sendinf it\n"); } @@ -550,7 +547,7 @@ int unicast_send_rtsp_teardown (int Socket, int CSeq, unicast_client_t *client , unicast_reply_write(reply, "Session: %s\r\n", client->session); rtsp_reply_prepare_headers(reply, 200, CSeq); - rtsp_reply_send(reply, Socket, "text/plain"); + rtsp_send_reply(reply, Socket, "text/plain"); if(requested_channel) { From d2c3ebc697bf63034e1390b24910a0d02dbf3fb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludovic=20BOU=C3=89?= Date: Sat, 4 Jun 2011 19:28:49 +0200 Subject: [PATCH 22/28] Translate to english --- src/unicast_rtsp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/unicast_rtsp.c b/src/unicast_rtsp.c index f8c7e2a5..fe30a382 100644 --- a/src/unicast_rtsp.c +++ b/src/unicast_rtsp.c @@ -457,7 +457,7 @@ int unicast_rtsp_play_reply (int Socket, int CSeq, unicast_client_t *client, mum return -1; } - log_message(MSG_INFO,"Unicast : Requete PLAY RTSP\n"); + log_message(MSG_INFO,"Unicast : RTSP PLAY request\n"); tempstring=strstr(client->buffer,"rtsp://"); tempstring=strstr(tempstring+7,"/"); From f1767a28e4fccef549d537354c39a4a3c57ccbc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludovic=20BOU=C3=89?= Date: Sat, 4 Jun 2011 22:29:23 +0200 Subject: [PATCH 23/28] Fix debugging with Wireshark "Content-type: text/plain" field is not needed Signed-off-by: Brice DUBOST --- src/unicast_rtsp.c | 43 ++++++++++++++++++++++++++++++++----------- 1 file changed, 32 insertions(+), 11 deletions(-) diff --git a/src/unicast_rtsp.c b/src/unicast_rtsp.c index fe30a382..bbabaf30 100644 --- a/src/unicast_rtsp.c +++ b/src/unicast_rtsp.c @@ -197,7 +197,7 @@ int unicast_handle_rtsp_message(unicast_parameters_t *unicast_vars, unicast_clie log_message(MSG_DEBUG,"Client ports not found\n"); /** @todo implement RTSP error rtsp_reply_prepare_headers(reply, 451, CSeq); - rtsp_send_reply(reply, Socket, "text/plain"); */ + rtsp_send_reply(reply, Socket); */ return CLOSE_CONNECTION; } @@ -211,7 +211,7 @@ int unicast_handle_rtsp_message(unicast_parameters_t *unicast_vars, unicast_clie log_message(MSG_DETAIL,"Unicast : Client ip %s port %d \n",client->client_ip,(unsigned short) client->rtsp_client_port); client->rtsp_Socket=makeUDPsocket (client->client_ip, client->rtsp_client_port,&client->rtsp_SocketAddr); - log_message(MSG_DETAIL,"Unicast : New RTSP socket d_IP %s, d_port:%d n°%d\n",inet_ntoa(client->rtsp_SocketAddr.sin_addr), ntohs(client->rtsp_SocketAddr.sin_port), client->rtsp_Socket); + log_message(MSG_DETAIL,"Unicast : New RTSP socket n°%d\n, d_IP %s, d_port:%d", client->rtsp_Socket, inet_ntoa(client->rtsp_SocketAddr.sin_addr), ntohs(client->rtsp_SocketAddr.sin_port)); struct sockaddr_in tempSocketAddr; unsigned int l; @@ -303,7 +303,7 @@ int rtsp_reply_prepare_headers(unicast_reply_t *reply, int code, int CSeq) /** @brief Send a RTSP message * The method add headers the to a reply message */ -int rtsp_send_reply(unicast_reply_t *reply, int socket, const char* content_type) +int rtsp_send_reply_sdp(unicast_reply_t *reply, int socket, const char* content_type) { //we add the header information reply->type = REPLY_HEADER; @@ -323,6 +323,28 @@ int rtsp_send_reply(unicast_reply_t *reply, int socket, const char* content_type } +/** @brief Send a RTSP message + * The method add headers the to a reply message + */ +int rtsp_send_reply(unicast_reply_t *reply, int socket) +{ + //we add the header information + reply->type = REPLY_HEADER; + if(reply->used_body) + { + unicast_reply_write(reply, "Content-length: %d\r\n", reply->used_body); + } + unicast_reply_write(reply, "\r\n"); /* end header */ + //we merge the header and the body + reply->buffer_header = realloc(reply->buffer_header, reply->used_header+reply->used_body); + memcpy(&reply->buffer_header[reply->used_header],reply->buffer_body,sizeof(char)*reply->used_body); + reply->used_header+=reply->used_body; + //now we write the data + int size = write(socket, reply->buffer_header, reply->used_header); + return size; +} + + /** @brief Send RTSP_DESCRIBE_REPLY * The DESCRIBE method retrieves the description of a presentation or * media object identified by the request URL from a server. It may use @@ -346,7 +368,6 @@ int unicast_rtsp_describe_reply (int Socket, int CSeq) //if (TransportType) TransportType="RTP/AVP/TCP"; // =0:UDP, =1:TCP char *source_host = "MuMuDVB-server"; - unicast_reply_write(reply, "\r\n"); unicast_reply_write(reply, "v=0\r\n"); unicast_reply_write(reply, "o=- 14904518995472011776 14904518995472011776 IN IP4 %s\r\n", source_host); unicast_reply_write(reply, "s=unknown\r\n"); @@ -356,7 +377,7 @@ int unicast_rtsp_describe_reply (int Socket, int CSeq) unicast_reply_write(reply, "m=video 0 %s 33\r\n", TransportType); rtsp_reply_prepare_headers(reply, 200, CSeq); - rtsp_send_reply(reply, Socket,"application/sdp"); + rtsp_send_reply_sdp(reply, Socket,"application/sdp"); if (0 != unicast_reply_free(reply)) { @@ -384,7 +405,7 @@ int unicast_rtsp_options_reply (int Socket, int CSeq) log_message(MSG_INFO,"RTSP OPTIONS request\n"); ; rtsp_reply_prepare_headers(reply, 200, CSeq); - rtsp_send_reply(reply, Socket,"text/plain"); + rtsp_send_reply(reply, Socket); if (0 != unicast_reply_free(reply)) { @@ -428,7 +449,7 @@ int unicast_rtsp_setup_reply (unicast_client_t *client, int CSeq, int Tsprt_type strcpy( broadcast_type,"unicast"); log_message(MSG_DEBUG, "Transport: %s;%s;mode=play;destination=%s;client_port=%d-%d;server_port=%d\r\n", TransportType, broadcast_type, client->client_ip, client->rtsp_client_port, client->rtsp_client_port+1, client->rtsp_server_port); unicast_reply_write(reply, "Transport: %s;%s;mode=play;destination=%s;client_port=%d-%d;server_port=%d\r\n", TransportType, broadcast_type, client->client_ip, client->rtsp_client_port, client->rtsp_client_port+1, client->rtsp_server_port); - rtsp_send_reply(reply, Socket,"text/plain"); + rtsp_send_reply(reply, Socket); if (0 != unicast_reply_free(reply)) { @@ -475,7 +496,7 @@ int unicast_rtsp_play_reply (int Socket, int CSeq, unicast_client_t *client, mum log_message(MSG_INFO,"Unicast : Path not found i.e. 404\n"); unicast_reply_write(reply, "Session: %s\r\n", client->session); rtsp_reply_prepare_headers(reply, 404, CSeq); - rtsp_send_reply(reply, Socket, "text/plain");; + rtsp_send_reply(reply, Socket); if (0 != unicast_reply_free(reply)) { log_message(MSG_INFO,"Unicast : Error when releasing the RTSP reply after sendinf it\n"); } @@ -484,7 +505,7 @@ int unicast_rtsp_play_reply (int Socket, int CSeq, unicast_client_t *client, mum unicast_reply_write(reply, "Session: %s\r\n", client->session); rtsp_reply_prepare_headers(reply, 200, CSeq); - rtsp_send_reply(reply, Socket, "text/plain"); + rtsp_send_reply(reply, Socket); if(requested_channel) { @@ -538,7 +559,7 @@ int unicast_rtsp_teardown_reply (int Socket, int CSeq, unicast_client_t *client log_message(MSG_INFO,"Unicast : Path not found i.e. 404\n"); unicast_reply_write(reply, "Session: %s\r\n", client->session); rtsp_reply_prepare_headers(reply, err, CSeq); - rtsp_send_reply(reply, Socket, "text/plain");; + rtsp_send_reply(reply, Socket); if (0 != unicast_reply_free(reply)) { log_message(MSG_INFO,"Unicast : Error when releasing the RTSP reply after sendinf it\n"); } @@ -547,7 +568,7 @@ int unicast_rtsp_teardown_reply (int Socket, int CSeq, unicast_client_t *client unicast_reply_write(reply, "Session: %s\r\n", client->session); rtsp_reply_prepare_headers(reply, 200, CSeq); - rtsp_send_reply(reply, Socket, "text/plain"); + rtsp_send_reply(reply, Socket); if(requested_channel) { From 9cea2c47628b3a89fed5d328d174e0609b0ea7c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludovic=20BOU=C3=89?= Date: Sat, 4 Jun 2011 22:56:34 +0200 Subject: [PATCH 24/28] Time of day as Session ID and Session version value Signed-off-by: Brice DUBOST --- src/unicast_rtsp.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/unicast_rtsp.c b/src/unicast_rtsp.c index bbabaf30..ac7e56f5 100644 --- a/src/unicast_rtsp.c +++ b/src/unicast_rtsp.c @@ -368,8 +368,13 @@ int unicast_rtsp_describe_reply (int Socket, int CSeq) //if (TransportType) TransportType="RTP/AVP/TCP"; // =0:UDP, =1:TCP char *source_host = "MuMuDVB-server"; + // time of day as Session ID and Session version value + struct timeval tv; + gettimeofday(&tv, NULL); + log_message(MSG_DEBUG,"Unicast : time of day: %d\n", tv.tv_sec); + unicast_reply_write(reply, "v=0\r\n"); - unicast_reply_write(reply, "o=- 14904518995472011776 14904518995472011776 IN IP4 %s\r\n", source_host); + unicast_reply_write(reply, "o=- %u %u IN IP4 %s\r\n", tv.tv_sec, tv.tv_sec, source_host); unicast_reply_write(reply, "s=unknown\r\n"); unicast_reply_write(reply, "i=unknown\r\n"); unicast_reply_write(reply, "c=IN IP4 0.0.0.0\r\n"); From 34f563462031373691a0d10fd62a9aa793ef5e48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludovic=20BOU=C3=89?= Date: Sat, 4 Jun 2011 23:11:10 +0200 Subject: [PATCH 25/28] Function for generate session id Signed-off-by: Brice DUBOST --- src/unicast_rtsp.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/src/unicast_rtsp.c b/src/unicast_rtsp.c index ac7e56f5..3ce1e22e 100644 --- a/src/unicast_rtsp.c +++ b/src/unicast_rtsp.c @@ -70,6 +70,24 @@ int unicast_rtsp_setup_reply (unicast_client_t *client, int CSeq, int Tsprt_type int unicast_rtsp_play_reply (int Socket, int CSeq, unicast_client_t *client, mumudvb_channel_t *channels, int number_of_channels); int unicast_rtsp_teardown_reply (int Socket, int CSeq, unicast_client_t *client , mumudvb_channel_t *channels, unicast_parameters_t *unicast_vars, fds_t *fds, int number_of_channels); + + +/** @brief Create a random number as session id +*/ +int unicast_rtsp_session(char *session) +{ + for (int i=0;i<15;i++) + { + float randomnum; + randomnum = rand(); + randomnum/=RAND_MAX; + session[i]='a'+(int)(randomnum*25); + } + session[15]='\0'; + return 0; +} + + /** @brief Deal with an incoming message on the unicast client connection * This function will store and answer the RTSP requests * @@ -135,16 +153,8 @@ int unicast_handle_rtsp_message(unicast_parameters_t *unicast_vars, unicast_clie { pos=0; char *pos_search; - /** @todo put this in a function */ char session[16]; - for (int i=0;i<15;i++) - { - float randomnum; - randomnum = rand(); - randomnum/=RAND_MAX; - session[i]='a'+(int)(randomnum*25); - } - session[15]='\0'; + unicast_rtsp_session(session); strcpy(client->session, session); log_message(MSG_DEBUG,"Session : %s\n", session ); @@ -211,7 +221,7 @@ int unicast_handle_rtsp_message(unicast_parameters_t *unicast_vars, unicast_clie log_message(MSG_DETAIL,"Unicast : Client ip %s port %d \n",client->client_ip,(unsigned short) client->rtsp_client_port); client->rtsp_Socket=makeUDPsocket (client->client_ip, client->rtsp_client_port,&client->rtsp_SocketAddr); - log_message(MSG_DETAIL,"Unicast : New RTSP socket n°%d\n, d_IP %s, d_port:%d", client->rtsp_Socket, inet_ntoa(client->rtsp_SocketAddr.sin_addr), ntohs(client->rtsp_SocketAddr.sin_port)); + log_message(MSG_DETAIL,"Unicast : New RTSP socket n°%d\n, d_IP %s, d_port:%d\n", client->rtsp_Socket, inet_ntoa(client->rtsp_SocketAddr.sin_addr), ntohs(client->rtsp_SocketAddr.sin_port)); struct sockaddr_in tempSocketAddr; unsigned int l; From 397d2b09b7113a866a729e0222aba029ea47b6be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludovic=20BOU=C3=89?= Date: Sat, 4 Jun 2011 23:15:55 +0200 Subject: [PATCH 26/28] Error message for logging Signed-off-by: Brice DUBOST --- src/unicast_rtsp.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/unicast_rtsp.c b/src/unicast_rtsp.c index 3ce1e22e..042459ad 100644 --- a/src/unicast_rtsp.c +++ b/src/unicast_rtsp.c @@ -127,7 +127,7 @@ int unicast_handle_rtsp_message(unicast_parameters_t *unicast_vars, unicast_clie log_message(MSG_FLOOD,"Buffer : %s\n",client->buffer); if(poscseq==NULL) { - log_message(MSG_DEBUG,"Sequence number not found\n"); + log_message(MSG_ERROR,"Sequence number not found\n"); /** @todo Implement an error following the RTSP protocol*/ return CLOSE_CONNECTION; //tu n'est pas content ... } @@ -186,7 +186,7 @@ int unicast_handle_rtsp_message(unicast_parameters_t *unicast_vars, unicast_clie } else { - log_message(MSG_INFO,"Error 461 : Unsupported transport type"); + log_message(MSG_ERROR,"Error 461 : Unsupported transport type"); /* rtsp_reply_prepare_headers(reply, 461, CSeq); rtsp_send_reply(reply, Socket,"text/plain"); @@ -236,7 +236,7 @@ int unicast_handle_rtsp_message(unicast_parameters_t *unicast_vars, unicast_clie iRet=bind(client->rtsp_Socket,(struct sockaddr *) &tempsin,l); if (iRet == 0) { - log_message( MSG_ERROR,"bind failed : %s\n", strerror(errno)); + log_message( MSG_ERROR,"bind failed : %s\n", strerror(errno) ); } //client->rtsp_server_port=ntohs(client->rtsp_SocketAddr.sin_port); client->rtsp_server_port=unicast_vars->rtsp_portOut; @@ -369,7 +369,7 @@ int unicast_rtsp_describe_reply (int Socket, int CSeq) unicast_reply_t* reply = unicast_reply_init(); if (NULL == reply) { - log_message(MSG_INFO,"Unicast : Error when creating the RTSP reply\n"); + log_message(MSG_ERROR,"Unicast : Error when creating the RTSP reply\n"); return -1; } log_message(MSG_INFO,"RTSP DESCRIBE request\n"); @@ -396,7 +396,7 @@ int unicast_rtsp_describe_reply (int Socket, int CSeq) if (0 != unicast_reply_free(reply)) { - log_message(MSG_INFO,"Unicast : Error when releasing the RTSP reply after sendinf it\n"); + log_message(MSG_ERROR,"Unicast : Error when releasing the RTSP reply after sendinf it\n"); return -1; } @@ -413,7 +413,7 @@ int unicast_rtsp_options_reply (int Socket, int CSeq) unicast_reply_t* reply = unicast_reply_init(); if (NULL == reply) { - log_message(MSG_INFO,"Unicast : Error when creating the RTSP reply\n"); + log_message(MSG_ERROR,"Unicast : Error when creating the RTSP reply\n"); return -1; } @@ -424,7 +424,7 @@ int unicast_rtsp_options_reply (int Socket, int CSeq) if (0 != unicast_reply_free(reply)) { - log_message(MSG_INFO,"Unicast : Error when releasing the RTSP reply after sendinf it\n"); + log_message(MSG_ERROR,"Unicast : Error when releasing the RTSP reply after sendinf it\n"); return -1; } @@ -443,7 +443,7 @@ int unicast_rtsp_setup_reply (unicast_client_t *client, int CSeq, int Tsprt_type unicast_reply_t* reply = unicast_reply_init(); if (NULL == reply) { - log_message(MSG_INFO,"Unicast : Error when creating the RTSP reply\n"); + log_message(MSG_ERROR,"Unicast : Error when creating the RTSP reply\n"); return -1; } @@ -468,7 +468,7 @@ int unicast_rtsp_setup_reply (unicast_client_t *client, int CSeq, int Tsprt_type if (0 != unicast_reply_free(reply)) { - log_message(MSG_INFO,"Unicast : Error when releasing the RTSP reply after sendinf it\n"); + log_message(MSG_ERROR,"Unicast : Error when releasing the RTSP reply after sendinf it\n"); return -1; } @@ -489,7 +489,7 @@ int unicast_rtsp_play_reply (int Socket, int CSeq, unicast_client_t *client, mum unicast_reply_t* reply = unicast_reply_init(); if (NULL == reply) { - log_message(MSG_INFO,"Unicast : Error when creating the RTSP reply\n"); + log_message(MSG_ERROR,"Unicast : Error when creating the RTSP reply\n"); return -1; } @@ -513,7 +513,7 @@ int unicast_rtsp_play_reply (int Socket, int CSeq, unicast_client_t *client, mum rtsp_reply_prepare_headers(reply, 404, CSeq); rtsp_send_reply(reply, Socket); if (0 != unicast_reply_free(reply)) { - log_message(MSG_INFO,"Unicast : Error when releasing the RTSP reply after sendinf it\n"); + log_message(MSG_ERROR,"Unicast : Error when releasing the RTSP reply after sendinf it\n"); } return CLOSE_CONNECTION; //to delete the client } @@ -553,7 +553,7 @@ int unicast_rtsp_teardown_reply (int Socket, int CSeq, unicast_client_t *client unicast_reply_t* reply = unicast_reply_init(); if (NULL == reply) { - log_message(MSG_INFO,"Unicast : Error when creating the RTSP reply\n"); + log_message(MSG_ERROR,"Unicast : Error when creating the RTSP reply\n"); return -1; } @@ -576,7 +576,7 @@ int unicast_rtsp_teardown_reply (int Socket, int CSeq, unicast_client_t *client rtsp_reply_prepare_headers(reply, err, CSeq); rtsp_send_reply(reply, Socket); if (0 != unicast_reply_free(reply)) { - log_message(MSG_INFO,"Unicast : Error when releasing the RTSP reply after sendinf it\n"); + log_message(MSG_ERROR,"Unicast : Error when releasing the RTSP reply after sendinf it\n"); } return CLOSE_CONNECTION; //to delete the client } From 05343891cbabe2dc30aee84808c1d098f64a44a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludovic=20BOU=C3=89?= Date: Sat, 4 Jun 2011 23:39:10 +0200 Subject: [PATCH 27/28] Monitor Unicast Clients number Signed-off-by: Brice DUBOST --- src/unicast_http.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/unicast_http.c b/src/unicast_http.c index a22ced81..a9762f96 100644 --- a/src/unicast_http.c +++ b/src/unicast_http.c @@ -87,6 +87,8 @@ int unicast_send_signal_power_js (int Socket, fds_t *fds); int unicast_send_channel_traffic_js (int number_of_channels, mumudvb_channel_t *channels, int Socket); +int +unicast_send_channel_clients_js (int number_of_clients, int Socket); @@ -224,6 +226,13 @@ int unicast_handle_http_message(unicast_parameters_t *unicast_vars, unicast_clie unicast_send_channel_traffic_js(number_of_channels, channels, client->Socket); return CLOSE_CONNECTION; //We close the connection afterwards } + else if(strstr(client->buffer +pos ,"/monitor/clients.json ")==(client->buffer +pos)) + { + log_message(MSG_DETAIL,"Unicast Clients\n"); + unicast_send_channel_clients_js(unicast_vars->client_number, client->Socket); + return CLOSE_CONNECTION; //We close the connection afterwards + } + //Not implemented path --> 404 else err404=1; @@ -636,6 +645,35 @@ unicast_send_channel_traffic_js (int number_of_channels, mumudvb_channel_t *chan +/** @brief Send a basic JSON file containig the clients +* +* @param number_of_clients the number of clients +* @param channels the channels array +* @param Socket the socket on wich the information have to be sent +*/ +int + unicast_send_channel_clients_js (int number_of_clients, int Socket) +{ + unicast_reply_t* reply = unicast_reply_init(); + if (NULL == reply) { + log_message(MSG_INFO,"Unicast : Error when creating the HTTP reply\n"); + return -1; + } + + unicast_reply_write(reply, "{\"number\":%d},\n", number_of_clients); + + unicast_reply_send(reply, Socket, 200, "application/json"); + + if (0 != unicast_reply_free(reply)) { + log_message(MSG_INFO,"Unicast : Error when releasing the HTTP reply after sendinf it\n"); + return -1; + } + return 0; +} + + + + From 86aa64ab889444f32f17cefe557396f8207c3170 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludovic=20BOU=C3=89?= Date: Sun, 5 Jun 2011 00:09:58 +0200 Subject: [PATCH 28/28] Debug : show all the clients sessions Signed-off-by: Brice DUBOST --- src/unicast_rtsp.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/unicast_rtsp.c b/src/unicast_rtsp.c index 042459ad..38a8f5c8 100644 --- a/src/unicast_rtsp.c +++ b/src/unicast_rtsp.c @@ -250,6 +250,7 @@ int unicast_handle_rtsp_message(unicast_parameters_t *unicast_vars, unicast_clie if(iRet) return CLOSE_CONNECTION; unicast_flush_client(client); + unicast_show(unicast_vars, channels); /** @todo important : test if the client already exist when a new client arrives, delete dead clients*/ @@ -309,6 +310,29 @@ int rtsp_reply_prepare_headers(unicast_reply_t *reply, int code, int CSeq) return 0; } +/** @brief Show all the clients sessions +* +* @param unicast_vars the unicast parameters +* @param channels : the channels structure +*/ +void unicast_show(unicast_parameters_t *unicast_vars, mumudvb_channel_t *channels) +{ + unicast_client_t *actual_client; + unicast_client_t *next_client; + int i=0; + + for(actual_client=unicast_vars->clients; actual_client != NULL; actual_client=next_client) + { + next_client= actual_client->next; + // if(client->client_type==CLIENT_RTSP && client->rtsp_Socket) + if (actual_client->client_type==CLIENT_RTSP) + { + log_message(MSG_DEBUG,"Unicast : Client n°%d, Session : %s\n", i, actual_client->session); + } + i++; + + } +} /** @brief Send a RTSP message * The method add headers the to a reply message