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