1 /*
2 
3   Faust Project
4 
5   Copyright (C) 2012-2014 Grame
6 
7   This library is free software; you can redistribute it and/or
8   modify it under the terms of the GNU Lesser General Public
9   License as published by the Free Software Foundation; either
10   version 2.1 of the License, or (at your option) any later version.
11 
12   This library is distributed in the hope that it will be useful,
13   but WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15   Lesser General Public License for more details.
16 
17   You should have received a copy of the GNU Lesser General Public
18   License along with this library; if not, write to the Free Software
19   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
20 
21   Grame Research Laboratory, 11 cours de Verdun Gensoul, 69002 Lyon - France
22   research@grame.fr
23 
24 */
25 #ifdef _WIN32
26 #include <winsock2.h>
27 #else
28 #include <netdb.h>
29 #include <unistd.h>
30 #endif
31 
32 #include <stdlib.h>
33 #include <iostream>
34 #include <sstream>
35 
36 #include "HTTPDControler.h"
37 #include "FaustFactory.h"
38 #include "HTTPDSetup.h"
39 #include "jsonfactory.h"
40 #include "htmlfactory.h"
41 #include "RootNode.h"
42 
43 using namespace std;
44 
45 namespace httpdfaust
46 {
47 
48 #define kVersion	 0.73f
49 #define kVersionStr	"0.73"
50 
51 static const char* kPortOpt	= "-port";
52 
53 //--------------------------------------------------------------------------
54 // utility for command line arguments
55 //--------------------------------------------------------------------------
getPortOption(int argc,char * argv[],const string & option,int defaultValue)56 static int getPortOption(int argc, char* argv[], const string& option, int defaultValue)
57 {
58 	for (int i = 0; i < argc-1; i++) {
59 		if (option == argv[i]) {
60 			int val = strtol( argv[i+1], 0, 10);
61 			if (val) return val;
62 		}
63 	}
64 	return defaultValue;
65 }
66 
67 //--------------------------------------------------------------------------
68 // utility for host name and ip address
69 //--------------------------------------------------------------------------
getNetInfos(string & name,string & ip)70 static bool getNetInfos(string& name, string& ip)
71 {
72 	char szBuffer[1024];
73 
74 	if (gethostname(szBuffer, sizeof(szBuffer)))
75 	return false;
76 
77 	name = szBuffer;
78 	struct hostent *host = gethostbyname(szBuffer);
79 	if (!host) return false;
80 
81 	stringstream s;
82 	unsigned char * ptr = (unsigned char*)host->h_addr;
83 	s << int(ptr[0]) << "." << int(ptr[1]) << "." << int(ptr[2]) << "." << int(ptr[3]);
84 	ip = s.str();
85 	return true;
86 }
87 
88 
89 //--------------------------------------------------------------------------
HTTPDControler(int argc,char * argv[],const char * applicationname,bool init)90 HTTPDControler::HTTPDControler(int argc, char* argv[], const char* applicationname, bool init)
91 	: fTCPPort(kTCPBasePort), fJson(0), fInit(init)
92 {
93 	fTCPPort = getPortOption(argc, argv, kPortOpt, fTCPPort);
94 	fFactory = new FaustFactory();
95 	fHttpd = new HTTPDSetup();
96 
97 	string host, ip;
98 	getNetInfos (host, ip);
99 	if (host.find('.') == string::npos) host.clear();	// ignore non qualifed domain names and uses IP number
100 	const char* hostname = host.size() ? host.c_str() : (ip.size() ? ip.c_str() : "localhost");
101 	fJson = new jsonfactory(applicationname, hostname, fTCPPort);
102 	fHtml = new htmlfactory(applicationname, hostname, fTCPPort);
103 }
104 
~HTTPDControler()105 HTTPDControler::~HTTPDControler()
106 {
107 	stop();
108 	delete fFactory;
109 	delete fHttpd;
110 	delete fJson;
111 }
112 
113 //--------------------------------------------------------------------------
version()114 float HTTPDControler::version()				{ return kVersion; }
versionstr()115 const char* HTTPDControler::versionstr()	{ return kVersionStr; }
116 
117 //--------------------------------------------------------------------------
118 // Add a node in the current group (top of the group stack)
addnode(const char * type,const char * label,float * zone,float init,float min,float max,float step)119 template<> void HTTPDControler::addnode<float>(const char* type, const char* label, float* zone, float init, float min, float max, float step)
120 {
121 	fFactory->addnode(label, zone, init, min, max, fInit);
122 	fJson->addnode<float>(type, label, init, min, max, step, fCurrentMeta);
123 	fHtml->addnode(type, label, init, min, max, step);
124 	fCurrentMeta.clear();
125 }
addnode(const char * type,const char * label,float * zone,float min,float max)126 template<> void HTTPDControler::addnode<float>(const char* type, const char* label, float* zone, float min, float max)
127 {
128 	fFactory->addnode(label, zone, min, max, fInit);
129 	fJson->addnode<float>(type, label, min, max, fCurrentMeta);
130 	fHtml->addnode(type, label, min, max);
131 	fCurrentMeta.clear();
132 }
addnode(const char * type,const char * label,float * zone)133 template<> void HTTPDControler::addnode<float>(const char* type, const char* label, float* zone)
134 {
135 	fFactory->addnode(label, zone, 0.f, 0.f, 1.f, fInit);
136 	fJson->addnode<float>(type, label, fCurrentMeta);
137 	fHtml->addnode(type, label);
138 	fCurrentMeta.clear();
139 }
140 
addnode(const char * type,const char * label,double * zone,double min,double max)141 template<> void HTTPDControler::addnode<double>(const char* type, const char* label, double* zone, double min, double max)
142 {
143 	fFactory->addnode(label, zone, min, max, fInit);
144 	fJson->addnode<double>(type, label, min, max, fCurrentMeta);
145 	fHtml->addnode(type, label, float(min), float(max));
146 	fCurrentMeta.clear();
147 }
148 
addnode(const char * type,const char * label,double * zone,double init,double min,double max,double step)149 template<> void HTTPDControler::addnode<double>(const char* type, const char* label, double* zone, double init, double min, double max, double step)
150 {
151 	fFactory->addnode(label, zone, init, min, max, fInit);
152 	fJson->addnode<double>(type, label, init, min, max, step, fCurrentMeta);
153 	fHtml->addnode(type, label, float(init), float(min), float(max), float(step));
154 	fCurrentMeta.clear();
155 }
addnode(const char * type,const char * label,double * zone)156 template<> void HTTPDControler::addnode<double>(const char* type, const char* label, double* zone)
157 {
158 	fFactory->addnode(label, zone, 0., 0., 1., fInit);
159 	fJson->addnode<double>(type, label, fCurrentMeta);
160 	fHtml->addnode(type, label);
161 	fCurrentMeta.clear();
162 }
163 
164 //--------------------------------------------------------------------------
opengroup(const char * type,const char * label)165 void HTTPDControler::opengroup(const char* type, const char* label)
166 {
167 	fFactory->opengroup(label);
168 	fJson->opengroup(type, label, fCurrentMeta);
169 	fHtml->opengroup(type, label);
170     fCurrentMeta.clear();
171 }
172 
173 //--------------------------------------------------------------------------
closegroup()174 void HTTPDControler::closegroup ()
175 {
176 	fFactory->closegroup();
177 	fJson->closegroup();
178 	fHtml->closegroup();
179 }
180 
181 //--------------------------------------------------------------------------
182 // start the network services
run()183 void HTTPDControler::run()
184 {
185 	SMessageDriven root = fFactory->root();		// first get the root node
186 	if (root) {
187 		// and cast it to a RootNode
188 		RootNode * rootnode = dynamic_cast<RootNode*>((MessageDriven*)root);
189 		// starts the network services
190 		if (fHttpd->start(root, fTCPPort)) {
191             fJson->root().setPort(fTCPPort);
192             string json = fJson->root().json();  // fJson->root().json(true); to 'flatten' JSON
193             if (rootnode) rootnode->setJSON(json);
194             stringstream strhtml;
195             fHtml->root().setPort(fTCPPort);
196             fHtml->root().print(strhtml, json);
197             if (rootnode) rootnode->setHtml(strhtml.str());
198 			// and outputs a message
199 			cout << "Faust httpd server version " << version() <<  " is running on TCP port " << fTCPPort << endl;
200 		}
201 	}
202 }
203 
204 //--------------------------------------------------------------------------
stop()205 void HTTPDControler::stop()
206 {
207 	fHttpd->stop();
208 }
209 
210 //------------------------------Accessor to json Interface
getJSON()211 string HTTPDControler::getJSON()
212 {
213     return fJson->root().json();
214 }
215 
setInputs(int numInputs)216 void HTTPDControler::setInputs(int numInputs)
217 {
218     fJson->root().setInputs(numInputs);
219 }
220 
setOutputs(int numOutputs)221 void HTTPDControler::setOutputs(int numOutputs)
222 {
223     fJson->root().setOutputs(numOutputs);
224 }
225 
226 }
227