]> git.zerfleddert.de Git - rigol/blob - rigold.c
29712e07b09db7230dc510be3032b9554c0d5a80
[rigol] / rigold.c
1 #include <sys/types.h>
2 #include <sys/socket.h>
3 #include <arpa/inet.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <strings.h>
8 #include <unistd.h>
9 #include <signal.h>
10 #include <stdarg.h>
11
12 #include "scope.h"
13 #include "commands.h"
14
15 #define TIMEOUT 4
16
17 static int send_binary(int s, char *buf, int len)
18 {
19 int ret;
20
21 while(len > 0) {
22 ret = write(s, buf, len);
23 if (ret == -1) {
24 perror("write");
25 return ret;
26 }
27 buf += ret;
28 len -= ret;
29 }
30
31 return 0;
32 }
33
34 static int send_text(int s, char *fmt, ...)
35 {
36 va_list argp;
37 char buf[4096];
38 int cnt;
39
40 va_start(argp, fmt);
41 cnt = vsnprintf(buf, sizeof(buf), fmt, argp);
42 va_end(argp);
43
44 if (cnt < 0)
45 return cnt;
46
47 return send_binary(s, buf, cnt);
48 }
49
50 static int send_command_output(int s, struct scope *sc, char *cmd)
51 {
52 unsigned char buf[1024*1024];
53 int res;
54
55 res = sendscpi(sc, cmd, buf, sizeof(buf));
56 send_binary(s, (char*)buf, res);
57
58 return res;
59 }
60
61 static void serve_index(int s, struct scope *sc, char *param)
62 {
63 send_text(s, "HTTP/1.0 200 OK\n");
64 send_text(s, "Content-type: text/html\n\n");
65 send_text(s, "<html><head><title>%s</title></head><body bgcolor=\"#ffffff\" text=\"#000000\">\n", scope_idn(sc));
66 send_text(s, "<img src=\"/cgi-bin/lcd\" height=\"234\" width=\"320\">\n");
67 send_text(s, "<br>\n");
68
69 claimscope(sc);
70 update_scope_status(sc);
71
72 send_text(s, "System: Language: %s, Counter: %d, Beep: %d<br>\n",
73 sc->status.system.lang,
74 sc->status.system.counter_enabled,
75 sc->status.system.beep_enabled);
76
77 send_text(s, "Keyboard: Key Lock: %d<br>\n",
78 sc->status.keyboard.key_lock);
79
80 send_text(s, "Acquire: Type: %s, Mode: %s, Averages: %d<br>\n",
81 sc->status.acquire.type,
82 sc->status.acquire.mode,
83 sc->status.acquire.averages);
84
85 send_text(s, "Horizontal: Mode: %s, Offset: %lg, Delayed Offset: %lg, Scale: %lg, Format: %s<br>\n",
86 sc->status.timebase.mode,
87 sc->status.timebase.offset,
88 sc->status.timebase.delayed_offset,
89 sc->status.timebase.scale,
90 sc->status.timebase.format);
91
92 send_text(s, "Display: ");
93 send_command_output(s, sc, ":DISP:TYPE?");
94 send_text(s, ", ");
95 send_command_output(s, sc, ":DISP:SCR?");
96 send_text(s, ", Grid: ");
97 send_command_output(s, sc, ":DISP:GRID?");
98 send_text(s, ", Persistence: ");
99 send_command_output(s, sc, ":DISP:PERS?");
100 send_text(s, ", Menu: ");
101 send_command_output(s, sc, ":DISP:MNUS?");
102 send_text(s, ", Brightness: ");
103 send_command_output(s, sc, ":DISP:BRIG?");
104 send_text(s, ", Intensity: ");
105 send_command_output(s, sc, ":DISP:INT?");
106 send_text(s, "<br>\n");
107
108 send_text(s, "Channel 1: ");
109 send_command_output(s, sc, ":CHAN1:DISP?");
110 send_text(s, ", ");
111 send_command_output(s, sc, ":CHAN1:MEMD?");
112 send_text(s, " sample depth, %.10lg samples/s<br>\n", sc->status.acquire.srate_chan1);
113 send_text(s, "Channel 2: ");
114 send_command_output(s, sc, ":CHAN2:DISP?");
115 send_text(s, ", ");
116 send_command_output(s, sc, ":CHAN2:MEMD?");
117 send_text(s, " sample depth, %.10lg samples/s<br>\n", sc->status.acquire.srate_chan2);
118
119 releasescope(sc);
120
121 send_text(s, sc->status.system.lang);
122
123 send_text(s, "<br>\n");
124 send_text(s, "<form method=\"get\" action=\"\">\n");
125 send_text(s, "<input type=\"text\" name=\"cmd\" value=\"");
126 if (param) {
127 if (strncmp(param, "cmd=", 4) == 0)
128 param += 4;
129
130 send_text(s, param);
131 }
132 send_text(s, "\">\n");
133 send_text(s, "<input type=\"submit\">\n");
134 send_text(s, "</form>\n");
135 send_text(s, "<a href=\"?cmd=:RUN\">RUN</a> ");
136 send_text(s, "<a href=\"?cmd=:STOP\">STOP</a> ");
137 send_text(s, "<a href=\"?cmd=:FORC\">FORCE</a> ");
138 if (param) {
139 claimscope(sc);
140 if (strchr (param, '?')) {
141 send_text(s, "<pre>< ");
142 send_text(s, param);
143 send_text(s, "\n> ");
144 send_command_output(s, sc, param);
145 send_text(s, "</pre>\n");
146 } else {
147 sendscpi(sc, param, NULL, 0);
148 }
149 releasescope(sc);
150 }
151 send_text(s, "</body></html>\n");
152 }
153
154 static void serve_lcd(int s, struct scope *sc)
155 {
156 char buf[256];
157 int imglen;
158 unsigned char *png;
159
160 claimscope(sc);
161 png = get_lcd(sc, &imglen, 0);
162 releasescope(sc);
163
164 if (png == NULL)
165 return;
166
167
168 send_text(s, "HTTP/1.0 200 OK\n");
169 send_text(s, "Content-type: image/png\n");
170 snprintf(buf, sizeof(buf), "Content-length: %u\n\n", imglen);
171 send_text(s, buf);
172 send_binary(s, (char*)png, imglen);
173 free(png);
174 }
175
176 static void serve_404(int s)
177 {
178 send_text(s, "HTTP/1.0 404 Not found\n");
179 send_text(s, "Content-type: text/html\n\n");
180 send_text(s, "<html><head><title>404</title></head>");
181 send_text(s, "<body bgcolor=\"#ffffff\" text=\"#000000\">\n");
182 send_text(s, "<h1>404</h1>");
183 send_text(s, "</body></html>\n");
184 }
185
186 int is_eor(char *buf)
187 {
188 int eor = 0;
189
190 /* This does not completely work, when the request is split
191 in multiple packets... */
192 if (strstr(buf, "\x0d\x0a\x0d\x0a")) {
193 eor = 1;
194 } else if (strstr(buf, "\x0a\x0a")) {
195 eor = 1;
196 } else if (strcmp(buf, "\x0d\x0a") == 0) {
197 eor = 1;
198 } else if (strcmp(buf, "\x0a") == 0) {
199 eor = 1;
200 }
201
202 return eor;
203 }
204
205
206 static void parse_request(int s, struct scope *sc)
207 {
208 int ret;
209 int eor;
210 char buf[4096];
211 char file[4096];
212 const char delim[] = " \t\x0d\x0a";
213 char *saveptr;
214 char *token;
215 char *param = NULL;
216
217 alarm(TIMEOUT);
218 ret=read(s, buf, sizeof(buf)-1);
219 if (ret == -1) {
220 perror("read");
221 return;
222 }
223 buf[ret] = 0;
224
225 eor = is_eor(buf);
226
227 token = strtok_r(buf, delim, &saveptr);
228 if (token == NULL)
229 return;
230 /* TODO: Only GET... */
231 token = strtok_r(NULL, delim, &saveptr);
232 if (token == NULL)
233 return;
234 bzero(&file, sizeof(file));
235 strncpy(file, token, sizeof(file)-1);
236
237 while (!eor) {
238 alarm(TIMEOUT);
239 ret=read(s, buf, sizeof(buf)-1);
240 if (ret == -1) {
241 perror("read");
242 return;
243 }
244 buf[ret] = 0;
245 eor = is_eor(buf);
246 }
247 alarm(0);
248
249 param = strchr(file, '?');
250 if (param) {
251 *param = 0;
252 param++;
253
254 while ((token = strchr(param, '%')) != NULL) {
255 char buf[3];
256
257 if (strlen(token+1) < 2)
258 break;
259
260 strncpy(buf, token+1, 3);
261 buf[2] = 0;
262
263 *token = (char)strtoul(buf, NULL, 16);
264 memmove(token+1, token+3, strlen(token)-2);
265
266 }
267 while ((token = strchr(param, '+')) != NULL) {
268 *token = ' ';
269 }
270 }
271
272 if (strcmp("/", file) == 0) {
273 serve_index(s, sc, param);
274 } else if (strcmp("/cgi-bin/lcd", file) == 0) {
275 serve_lcd(s, sc);
276 } else {
277 serve_404(s);
278 }
279 }
280
281 void sighandler(int sig)
282 {
283 switch(sig) {
284 case SIGPIPE:
285 break;
286 case SIGALRM:
287 default:
288 printf("Signal %d received\n", sig);
289 break;
290 }
291 }
292
293 int main(int argc, char **argv)
294 {
295 struct sigaction act;
296 int sock, csock;
297 int opt;
298 socklen_t slen;
299 struct scope *sc;
300 struct sockaddr_in sin, clientsin;
301 unsigned short port = 8088;
302
303 sc = initscope();
304 if (sc == NULL) {
305 printf("Scope not found!\n");
306 exit(EXIT_FAILURE);
307 }
308
309 bzero(&act, sizeof(act));
310 act.sa_handler = sighandler;
311 act.sa_flags = SA_RESTART;
312 if (sigaction(SIGPIPE, &act, NULL) == -1) {
313 perror("sigaction");
314 exit(EXIT_FAILURE);
315 }
316
317 bzero(&act, sizeof(act));
318 act.sa_handler = sighandler;
319 if (sigaction(SIGALRM, &act, NULL) == -1) {
320 perror("sigaction");
321 exit(EXIT_FAILURE);
322 }
323
324 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
325 perror("socket");
326 exit(EXIT_FAILURE);
327 }
328
329 if (argc == 2) {
330 port=atoi(argv[1]);
331 }
332
333 bzero(&sin, sizeof(sin));
334 sin.sin_addr.s_addr=htonl(INADDR_ANY);
335 sin.sin_family=AF_INET;
336 sin.sin_port=htons(port);
337
338 opt = 1;
339 setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt,sizeof(opt));
340
341 if (bind(sock, (struct sockaddr*)&sin, sizeof(sin)) == -1) {
342 perror("bind");
343 exit(EXIT_FAILURE);
344 }
345
346 listen(sock, 32);
347 printf("Listening on Port %u\n", port);
348
349 while(1) {
350 bzero(&clientsin, sizeof(clientsin));
351 slen = sizeof(clientsin);
352 if ((csock = accept(sock, (struct sockaddr*)&clientsin, &slen)) == -1) {
353 perror("accept");
354 }
355
356 parse_request(csock, sc);
357
358 close(csock);
359 }
360
361 closescope(sc);
362 return 0;
363 }
Impressum, Datenschutz