diff --git a/lib/socket.cpp b/lib/socket.cpp index 63cf624b..62cbc081 100644 --- a/lib/socket.cpp +++ b/lib/socket.cpp @@ -53,13 +53,16 @@ void Socket::Connection::setBlocking(bool blocking){ } /// Close connection. The internal socket is closed and then set to -1. +/// If the connection is already closed, nothing happens. void Socket::Connection::close(){ - #if DEBUG >= 6 - fprintf(stderr, "Socket closed.\n"); - #endif - shutdown(sock, SHUT_RDWR); - ::close(sock); - sock = -1; + if (connected()){ + #if DEBUG >= 6 + fprintf(stderr, "Socket closed.\n"); + #endif + shutdown(sock, SHUT_RDWR); + ::close(sock); + sock = -1; + } }//Socket::Connection::close /// Returns internal socket number. @@ -214,7 +217,7 @@ signed int Socket::Connection::ready(){ /// The connection status is updated after every read/write attempt, when errors occur /// and when the socket is closed manually. /// \returns True if socket is connected, false otherwise. -bool Socket::Connection::connected(){ +bool Socket::Connection::connected() const{ return (sock >= 0); } @@ -451,6 +454,24 @@ std::string Socket::Connection::getHost(){ return remotehost; } +/// Returns true if these sockets are the same socket. +/// Does not check the internal stats - only the socket itself. +bool Socket::Connection::operator== (const Connection &B) const{ + return sock == B.sock; +} + +/// Returns true if these sockets are not the same socket. +/// Does not check the internal stats - only the socket itself. +bool Socket::Connection::operator!= (const Connection &B) const{ + return sock != B.sock; +} + +/// Returns true if the socket is valid. +/// Aliases for Socket::Connection::connected() +Socket::Connection::operator bool() const{ + return connected(); +} + /// Create a new base Server. The socket is never connected, and a placeholder for later connections. Socket::Server::Server(){ sock = -1; @@ -661,13 +682,16 @@ Socket::Connection Socket::Server::accept(bool nonblock){ } /// Close connection. The internal socket is closed and then set to -1. +/// If the connection is already closed, nothing happens. void Socket::Server::close(){ - #if DEBUG >= 6 - fprintf(stderr, "ServerSocket closed.\n"); - #endif - shutdown(sock, SHUT_RDWR); - ::close(sock); - sock = -1; + if (connected()){ + #if DEBUG >= 6 + fprintf(stderr, "ServerSocket closed.\n"); + #endif + shutdown(sock, SHUT_RDWR); + ::close(sock); + sock = -1; + } }//Socket::Server::close /// Returns the connected-state for this socket. @@ -675,7 +699,7 @@ void Socket::Server::close(){ /// The connection status is updated after every accept attempt, when errors occur /// and when the socket is closed manually. /// \returns True if socket is connected, false otherwise. -bool Socket::Server::connected(){ +bool Socket::Server::connected() const{ return (sock >= 0); }//Socket::Server::connected diff --git a/lib/socket.h b/lib/socket.h index 9c88a248..0d33573b 100644 --- a/lib/socket.h +++ b/lib/socket.h @@ -37,7 +37,7 @@ namespace Socket{ bool canRead(); ///< Calls poll() on the socket, checking if data is available. bool canWrite(); ///< Calls poll() on the socket, checking if data can be written. signed int ready(); ///< Returns the ready-state for this socket. - bool connected(); ///< Returns the connected-state for this socket. + bool connected() const; ///< Returns the connected-state for this socket. bool read(const void * buffer, int len); ///< Reads data from socket. bool read(const void * buffer, int width, int count); ///< Read call that is compatible with file access syntax. bool write(const void * buffer, int len); ///< Writes data to socket. @@ -62,6 +62,10 @@ namespace Socket{ friend class Server; bool Error; ///< Set to true if a socket error happened. bool Blocking; ///< Set to true if a socket is currently or wants to be blocking. + //overloaded operators + bool operator== (const Connection &B) const; + bool operator!= (const Connection &B) const; + operator bool() const; }; /// This class is for easily setting up listening socket, either TCP or Unix. @@ -75,7 +79,7 @@ namespace Socket{ Server(int port, std::string hostname = "0.0.0.0", bool nonblock = false); ///< Create a new TCP Server. Server(std::string adres, bool nonblock = false); ///< Create a new Unix Server. Connection accept(bool nonblock = false); ///< Accept any waiting connections. - bool connected(); ///< Returns the connected-state for this socket. + bool connected() const; ///< Returns the connected-state for this socket. void close(); ///< Close connection. int getSocket(); ///< Returns internal socket number. }; diff --git a/src/conn_http.cpp b/src/conn_http.cpp index 129814c0..e8014eb4 100644 --- a/src/conn_http.cpp +++ b/src/conn_http.cpp @@ -163,8 +163,8 @@ namespace Connector_HTTP{ FLV::Tag tag;///< Temporary tag buffer. std::string recBuffer = ""; - std::string Movie = ""; - std::string Quality = ""; + std::string Movie; + std::string Quality; int Segment = -1; int ReqFragment = -1; int temp; @@ -235,32 +235,37 @@ namespace Connector_HTTP{ HTTP_S.SetHeader("Content-Type","text/xml"); HTTP_S.SetHeader("Cache-Control","no-cache"); std::string manifest = BuildManifest(Movie); - #if DEBUG >= 4 - printf("Manifest: %s\n", manifest.c_str()); - #endif HTTP_S.SetBody(manifest); conn.Send(HTTP_S.BuildResponse("200", "OK")); #if DEBUG >= 3 printf("Sent manifest\n"); #endif } - #if DEBUG >= 4 - printf( "Movie: %s\n", Movie.c_str()); - #endif - streamname = Movie; ready4data = true; }//FLASH handler if (handler == HANDLER_PROGRESSIVE){ //we assume the URL is the stream name with a 3 letter extension std::string extension = HTTP_R.url.substr(HTTP_R.url.size()-4); - streamname = HTTP_R.url.substr(0, HTTP_R.url.size()-4);//strip the extension + Movie = HTTP_R.url.substr(0, HTTP_R.url.size()-4);//strip the extension /// \todo VoD streams will need support for position reading from the URL parameters ready4data = true; - #if DEBUG >= 4 - printf( "Opening progressive stream: %s\n", streamname.c_str()); - #endif }//PROGRESSIVE handler - HTTP_R.Clean(); //clean for any possinble next requests + if (Movie != "" && Movie != streamname){ + #if DEBUG >= 4 + printf("Buffer switch detected (%s -> %s)! (Re)connecting buffer...\n", streamname.c_str(), Movie.c_str()); + #endif + streamname = Movie; + inited = false; + ss.close(); + if (handler == HANDLER_PROGRESSIVE){ + #if DEBUG >= 4 + printf("Progressive-mode reconnect impossible - disconnecting.\n"); + #endif + conn.close(); + ready4data = false; + } + } + HTTP_R.Clean(); //clean for any possible next requests }else{ #if DEBUG >= 3 fprintf(stderr, "Could not parse the following:\n%s\n", conn.Received().c_str()); @@ -275,8 +280,12 @@ namespace Connector_HTTP{ #if DEBUG >= 1 fprintf(stderr, "Could not connect to server!\n"); #endif - conn.close(); - break; + ss.close(); + HTTP_S.Clean(); + HTTP_S.SetBody("No such stream is available on the system. Please try again.\n"); + conn.Send(HTTP_S.BuildResponse("404", "Not found")); + ready4data = false; + continue; } #if DEBUG >= 3 fprintf(stderr, "Everything connected, starting to send video data...\n"); @@ -313,7 +322,7 @@ namespace Connector_HTTP{ } } conn.close(); - if (inited) ss.close(); + ss.close(); #if DEBUG >= 1 if (FLV::Parse_Error){fprintf(stderr, "FLV Parser Error: %s\n", FLV::Error_Str.c_str());} fprintf(stderr, "User %i disconnected.\n", conn.getSocket());