1 // 2 // Copyright (C) 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. 3 // 4 // This program is free software; you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation; either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // This program is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with this program; if not, write to the Free Software 16 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 // 18 19 #ifndef __HANDLER_H__ 20 #define __HANDLER_H__ 1 21 22 #include <map> 23 #include <cstdint> 24 #include <mutex> 25 #include <memory> 26 27 #include <vector> 28 #include <string> 29 30 #ifdef HAVE_POLL 31 # include <sys/poll.h> 32 #else 33 # ifdef HAVE_EPOLL 34 # include <sys/epoll.h> 35 # endif 36 #endif 37 38 #include "log.h" 39 #include "network.h" 40 #include "buffer.h" 41 #include "element.h" 42 #include "cque.h" 43 #include "network.h" 44 #include "dsodefs.h" //For DSOEXPORT. 45 #include "proc.h" 46 47 #include "diskstream.h" 48 #include "sharedlib.h" 49 #include "extension.h" 50 #include "diskstream.h" 51 52 #include "rtmp.h" 53 #include "rtmp_msg.h" 54 #include "http.h" 55 #include "network.h" 56 57 // _definst_ is the default instance name 58 namespace cygnal 59 { 60 61 // The number of disk streams in the array. 62 const size_t STREAMS_BLOCK = 1000; 63 64 class Cygnal; 65 class HTTPServer; 66 class RTMPServer; 67 68 class Handler : public gnash::Extension, gnash::Network 69 { 70 public: 71 /// \enum admin_cmd_e 72 /// The Admin command sent by the client 73 typedef enum { 74 UNKNOWN, 75 STATUS, 76 POLL, 77 HELP, 78 INTERVAL, 79 QUIT 80 } admin_cmd_e; 81 /// This enum contains the possible values for streaming video 82 /// types. 83 typedef enum { 84 RECORD, 85 LIVE, 86 APPEND 87 } pub_stream_e; 88 /// This typedef is only used for the io function that must be 89 /// supported by the plugin. 90 typedef size_t (*cygnal_io_write_t)(std::uint8_t *data, size_t size); 91 typedef std::shared_ptr<cygnal::Buffer> (*cygnal_io_read_t)(); 92 typedef struct { 93 std::string version; 94 std::string description; 95 std::string hostname; 96 std::string path; 97 cygnal_io_read_t read_func; 98 cygnal_io_write_t write_func; 99 gnash::Network::protocols_supported_e protocol; 100 } cygnal_init_t; 101 102 /// This typedef is only used for the init function optionally 103 /// supported by the plugin. 104 typedef std::shared_ptr<cygnal_init_t>(*cygnal_io_init_t)(std::shared_ptr<gnash::RTMPMsg> &msg); 105 106 DSOEXPORT Handler(); 107 ~Handler(); 108 109 /// \var sync 110 /// Send the onSync message to all connected clients sync()111 bool sync() { return sync(_in_fd); }; 112 bool sync(int in_fd); 113 114 // Access the name field setName(const std::string & x)115 void setName(const std::string &x) { _name = x; }; getName()116 std::string &getName() { return _name; } 117 118 // Check the status of active disk streams, which is one less than 119 // default as the Streams IDs start at 1. getActiveDiskStreams()120 int getActiveDiskStreams() { return _diskstreams.size(); } 121 // int removeDiskStream(std::shared_ptr<DiskStream> x); 122 123 // Operate on a disk streaming inprogress getDiskStream(int x)124 std::shared_ptr<gnash::DiskStream> getDiskStream(int x) { return _diskstreams[x]; } setDiskStream(int x,std::shared_ptr<gnash::DiskStream> y)125 void setDiskStream(int x, std::shared_ptr<gnash::DiskStream> y) { _diskstreams[x] = y; } 126 127 /// Add a SharedObject addSOL(std::shared_ptr<cygnal::Element> x)128 void addSOL(std::shared_ptr<cygnal::Element> x) { 129 _sol.push_back(x); 130 }; 131 132 /// \method addClient 133 /// Add a client to the list for output messages for a 134 /// resource. This also specifies the protocol handler 135 /// required for data on this file descriptor. 136 size_t addClient(int fd, gnash::Network::protocols_supported_e proto); 137 /// \method removeClient 138 /// Remove a client from the list for messages. 139 void removeClient(int fd); 140 /// \var getClients 141 /// Get the vector of file descriptors for this handler. getClients()142 std::vector<int> &getClients() { return _clients; }; 143 /// \var getClient 144 /// Get a client from the list of clients, we have too many 145 /// arrays so using an operator isn't useful. getClient(int x)146 int getClient(int x) { return _clients[x]; }; 147 148 /// \brief Receive a message from the other end of the network connection. 149 /// 150 /// @param fd The file descriptor to read from 151 /// 152 /// @return The number of bytes sent 153 int recvMsg(int fd); 154 getProtocol(int x)155 gnash::Network::protocols_supported_e getProtocol(int x) { return _protocol[x]; }; setProtocol(int fd,gnash::Network::protocols_supported_e x)156 void setProtocol(int fd, gnash::Network::protocols_supported_e x) { _protocol[fd] = x; }; 157 158 /// \method addRemote 159 /// Add a remote machine to the list for input messages. addRemote(int x)160 size_t addRemote(int x) { _remote.push_back(x); return _remote.size(); }; 161 162 void setPlugin(std::shared_ptr<Handler::cygnal_init_t> &init); 163 void setPlugin(Handler::cygnal_io_read_t read_ptr, Handler::cygnal_io_write_t write_ptr ); 164 165 /// Initialize the named module within Cygnal 166 // 167 std::shared_ptr<cygnal_init_t> initModule(const std::string& module); 168 169 /// \method initialized 170 /// See if any of the cgi-bins has been loaded. 171 bool initialized(); 172 173 /// This method reads raw data from a plugin. 174 std::shared_ptr<cygnal::Buffer> readFromPlugin(); 175 176 /// This method writes raw data to a plugin. writeToPlugin(cygnal::Buffer & buf)177 size_t writeToPlugin(cygnal::Buffer &buf) { 178 return writeToPlugin(buf.begin(), buf.allocated()); }; 179 size_t writeToPlugin(std::uint8_t *data, size_t size); 180 181 // These methods handle control of the file streaming, and are 182 // used by both HTTP and RTMP* 183 184 /// \fn int createStream() 185 double createStream(double transid); 186 /// \overload int createStream(const std::string &filespec) 187 /// @param filespec The spec of the file to stream 188 double createStream(double transid, const std::string &filespec); 189 190 /// \fn playStream 191 /// Play the specified file as a stream 192 bool playStream(); 193 /// \overload int playStream(const std::string &filespec) 194 bool playStream(const std::string &filespec); 195 196 // Publish a live RTMP stream 197 int publishStream(); 198 int publishStream(const std::string &filespec, pub_stream_e op); 199 200 // Seek within the RTMP stream 201 int seekStream(); 202 int seekStream(int offset); 203 204 // Pause the RTMP stream 205 int pauseStream(double transid); 206 207 // Find a stream in the vector or Disk Streams 208 std::shared_ptr<gnash::DiskStream> findStream(const std::string &filespec); 209 210 // Pause the RTMP stream 211 int togglePause(double); 212 213 // Resume the paused RTMP stream 214 double resumeStream(double transid); 215 216 // Close the RTMP stream 217 double closeStream(double transid); 218 219 // Delete the RTMP stream 220 double deleteStream(double transid); 221 222 // This is a site specific identifier of some kind. setFCSubscribe(const std::string & x)223 void setFCSubscribe(const std::string &x) { _fcsubscribe = x; }; getFCSubscribe()224 std::string &getFCSubscribe() { return _fcsubscribe; } 225 226 #if 1 227 // FIXME: This holds the data from the first NetConnection packet, 228 // and shouldn't really be done here, but we're trying not to 229 // break things while refactoring. setNetConnection(gnash::RTMPMsg * msg)230 void setNetConnection(gnash::RTMPMsg *msg) { _netconnect.reset(msg); }; setNetConnection(std::shared_ptr<gnash::RTMPMsg> msg)231 void setNetConnection(std::shared_ptr<gnash::RTMPMsg> msg) { _netconnect = msg; }; getNetConnection()232 std::shared_ptr<gnash::RTMPMsg> getNetConnection() { return _netconnect;}; 233 #endif 234 235 #if 1 getHTTPHandler(int fd)236 std::shared_ptr<HTTPServer> &getHTTPHandler(int fd) { return _http[fd]; }; getRTMPHandler(int fd)237 std::shared_ptr<RTMPServer> getRTMPHandler(int fd) { return _rtmp[fd]; }; 238 #endif 239 240 // Parse the first nessages when starting a new message handler, 241 // which is used to determine the name of the resource to 242 // initialize, or load from the cache. 243 cygnal::Buffer *parseFirstRequest(int fd, gnash::Network::protocols_supported_e proto); 244 getKey(int x)245 std::string &getKey(int x) { return _keys[x]; }; setKey(int fd,std::string x)246 void setKey(int fd, std::string x) { _keys[fd] = x; }; 247 248 // Dump internal data. 249 void dump(); 250 251 protected: 252 /// \var _name 253 /// The name of the path this handler is supporting. 254 std::string _name; 255 /// Each incoming request has one of 4 states the server has 256 /// to handle to send a response. 257 /// \var _streams 258 /// This is a counter of how many streams have been allocated 259 /// by the server. 260 int _streams; 261 /// \var _diskstreams 262 /// This is all the opened disk based files that are currently 263 /// being streamed by the server. 264 std::map<int, std::shared_ptr<gnash::DiskStream> > _diskstreams; 265 /// \var _protocol 266 /// this is the map of which protocol is being used by which 267 /// file descriptor. 268 std::map<int, gnash::Network::protocols_supported_e> _protocol; 269 #if 1 270 std::map<int, std::shared_ptr<HTTPServer> > _http; 271 std::map<int, std::shared_ptr<RTMPServer> > _rtmp; 272 #endif 273 /// \var _clients 274 /// is the array of all clients connected to this server for 275 /// this application. This is where all the output goes. 276 std::vector<int> _clients; 277 /// \var _remote 278 /// This is network connections to other processes, 279 /// on other computers. 280 std::vector<int> _remote; 281 282 /// \var _local 283 /// These are local process we're responsible for 284 /// starting and stopping. 285 std::shared_ptr<cygnal::Proc> _local; 286 /// \var _plugins 287 /// is for the dynamically loaded applications 288 std::shared_ptr<cygnal_init_t> _plugin; 289 /// \var _file 290 /// is for disk based files 291 std::vector<std::shared_ptr<gnash::DiskStream> > _files; 292 /// \var _sol 293 /// is for remote SharedObjects 294 std::vector<std::shared_ptr<cygnal::Element> > _sol; 295 ///var _bodysize; 296 /// is to store the body size of the previous packet for this 297 /// channel. 4 and 1 byte heades don't use the length field, 298 /// they just use the previous vaue for this field. 299 std::map<int, size_t> _bodysize; 300 /// \var _in_fd 301 /// The file descriptor of the incoming data for an 302 /// Invoke message. 303 int _in_fd; 304 305 /// \var _fcssubscribe 306 /// This is a string sometimes sent by the client with what 307 /// appears to be a unique ID number. 308 std::string _fcsubscribe; 309 310 #if 1 311 /// \var _netconnect 312 /// This store the data from the NetConnection ActionScript 313 /// object we get as the final part of the handshake process 314 /// that is used to set up the connection. This has all the 315 /// file paths and other information needed by the server. 316 std::shared_ptr<gnash::RTMPMsg> _netconnect; 317 #endif 318 319 std::map<int, std::string> _keys; 320 private: 321 std::mutex _mutex; 322 323 // Remote Shared Objects. References are an index into this vector. 324 // std::map<std::string, std::shared_ptr<handler_t> > _handlers; 325 }; 326 327 } // end of gnash namespace 328 329 #endif // end of __HANDLER_H__ 330 331 // local Variables: 332 // mode: C++ 333 // indent-tabs-mode: t 334 // End: 335