source: roaraudio/plugins/roard/protocol-gopher.c @ 5602:6d421545ca98

Last change on this file since 5602:6d421545ca98 was 5602:6d421545ca98, checked in by phi, 12 years ago

moved strselcmp() and strseltok() to libroar (Closes: #285)

File size: 20.9 KB
Line 
1//emul_gopher.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010-2012
5 *
6 *  This file is part of roard a part of RoarAudio,
7 *  a cross-platform sound system for both, home and professional use.
8 *  See README for details.
9 *
10 *  This file is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU General Public License version 3
12 *  as published by the Free Software Foundation.
13 *
14 *  RoarAudio is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU General Public License for more details.
18 *
19 *  You should have received a copy of the GNU General Public License
20 *  along with this software; see the file COPYING.  If not, write to
21 *  the Free Software Foundation, 51 Franklin Street, Fifth Floor,
22 *  Boston, MA 02110-1301, USA.
23 *
24 */
25
26#include "roard.h"
27
28#ifndef ROAR_WITHOUT_DCOMP_EMUL_GOPHER
29#include <roaraudio/proto_gopher.h>
30
31#define _INFO  ROAR_GOPHER_TYPE_INFO
32#define _DIR   ROAR_GOPHER_TYPE_DIR
33#define _FILE  ROAR_GOPHER_TYPE_FILE
34#define _SOUND ROAR_GOPHER_TYPE_SOUND
35
36struct item;
37
38static int scb_status_txt (int client, struct roar_vio_calls * vio, char * selector, char ** text, struct item * sitem);
39static int scb_test       (int client, struct roar_vio_calls * vio, char * selector, char ** text, struct item * sitem);
40static int scb_clients    (int client, struct roar_vio_calls * vio, char * selector, char ** text, struct item * sitem);
41static int scb_streams    (int client, struct roar_vio_calls * vio, char * selector, char ** text, struct item * sitem);
42static int scb_client_info(int client, struct roar_vio_calls * vio, char * selector, char ** text, struct item * sitem);
43static int scb_stream_info(int client, struct roar_vio_calls * vio, char * selector, char ** text, struct item * sitem);
44static int scb_listen_menu(int client, struct roar_vio_calls * vio, char * selector, char ** text, struct item * sitem);
45static int scb_listen     (int client, struct roar_vio_calls * vio, char * selector, char ** text, struct item * sitem);
46
47static struct roar_gopher_menu_item g_gopher_root_menu[] = {
48 {.type = _INFO, .name = "roard Root Menu"},
49 {.type = _FILE, .name = "Server Info",   .selector = "/info.txt",   .host = NULL, .port = 0},
50 {.type = _FILE, .name = "Server Status", .selector = "/status.txt", .host = NULL, .port = 0},
51 {.type = _DIR,  .name = "Clients",       .selector = "/clients/",   .host = NULL, .port = 0},
52 {.type = _DIR,  .name = "Streams",       .selector = "/streams/",   .host = NULL, .port = 0},
53 {.type = _DIR,  .name = "Listen!",       .selector = "/listen/",    .host = NULL, .port = 0},
54};
55
56// need a true constant string.
57#define info_text \
58 "This server is RoarAudio server (roard) with a small status gopher server\n" \
59 "integrated. (For version and stuff see /status.txt.)\n" \
60 "RoarAudio is a modern, multi OS, networed sound system.\n" \
61 "For more information see http://roaraudio.keep-cool.org/\n"
62
63static struct item {
64 const char * selector;
65 char type;
66 struct roar_gopher_menu menu;
67 struct roar_audio_info  info;
68 int dir;
69 const char * text;
70 int (*cb)(int client, struct roar_vio_calls * vio, char * selector, char ** text, struct item * sitem);
71} g_gopher_items[] = {
72 {.selector = "", .type = _DIR,
73  .menu = {.items = g_gopher_root_menu, .items_len = sizeof(g_gopher_root_menu)/sizeof(*g_gopher_root_menu)},
74  .cb = NULL
75 },
76 // and again as selector '/' as some clients seems to require it:
77 {.selector = "/", .type = _DIR,
78  .menu = {.items = g_gopher_root_menu, .items_len = sizeof(g_gopher_root_menu)/sizeof(*g_gopher_root_menu)},
79  .cb = NULL
80 },
81 {.selector = "/info.txt",   .type = _FILE, .text = info_text, .cb = NULL},
82 {.selector = "/status.txt", .type = _FILE, .cb = scb_status_txt},
83 {.selector = "/test/*",     .type = _FILE, .cb = scb_test},
84 {.selector = "/clients/",   .type = _DIR,  .cb = scb_clients},
85 {.selector = "/streams/",   .type = _DIR,  .cb = scb_streams},
86 {.selector = "/clients/*/", .type = _DIR,  .cb = scb_client_info},
87 {.selector = "/streams/*/", .type = _DIR,  .cb = scb_stream_info},
88 {.selector = "/listen/",    .type = _DIR,  .cb = scb_listen_menu},
89 {.selector = "/listen/*/*/*/*/*", .type = _FILE,  .cb = scb_listen}
90};
91
92static char * _aprintf(size_t sizehint, const char * format, ...);
93
94static int send_menu (int client, struct roar_gopher_menu * menu, struct roar_vio_calls * vio);
95static int send_text (int client, const char * text, struct roar_vio_calls * vio);
96
97
98// SCBs:
99static int scb_status_txt (int client, struct roar_vio_calls * vio, char * selector, char ** text, struct item * sitem) {
100 const size_t len = 1024;
101 const char * server_version = NULL;
102
103 if ( DISTRIBUTION_VERSION_STRING[0] == 0 ) {
104  server_version = "roard/" PACKAGE_VERSION " <" DEVICE_VENDOR_STRING ">";
105 } else {
106  server_version = "roard/" PACKAGE_VERSION " <" DEVICE_VENDOR_STRING "> (" DISTRIBUTION_VERSION_STRING ")";
107 }
108
109 *text = roar_mm_malloc(len);
110 if ( *text == NULL )
111  return -1;
112
113 **text = 0;
114
115 snprintf(*text, len,
116          "Server version:     %s\r\n"
117          "Server location:    %s\r\n"
118          "Server description: %s\r\n"
119          "\r\n"
120          "Counters current:   %llu clients, %llu streams\r\n"
121          "Counters sum:       %llu clients, %llu streams\r\n",
122          server_version,
123          g_config->location,
124          g_config->description,
125          (long long unsigned int)g_counters.cur.clients,
126          (long long unsigned int)g_counters.cur.streams,
127          (long long unsigned int)g_counters.sum.clients,
128          (long long unsigned int)g_counters.sum.streams
129         );
130
131 (*text)[len-1] = 0;
132 return 0;
133}
134
135static int scb_test(int client, struct roar_vio_calls * vio, char * selector, char ** text, struct item * sitem) {
136 ssize_t toks;
137 char * tok;
138 size_t len;
139
140 toks = roar_mm_strseltok(sitem->selector, selector, &tok, 1);
141
142 if ( toks == -1 )
143  return -1;
144
145 len  = strlen(tok);
146 len += 64;
147
148 *text = roar_mm_malloc(1024);
149 if ( *text == NULL )
150  return -1;
151
152 **text = 0;
153
154 snprintf(*text, len, "Your text was: %s", tok);
155
156 (*text)[len-1] = 0;
157
158 return 0;
159}
160
161static int scb_clients    (int client, struct roar_vio_calls * vio, char * selector, char ** text, struct item * sitem) {
162 struct roar_gopher_menu_item items[ROAR_CLIENTS_MAX];
163 struct roar_gopher_menu menu = {.flags = 0, .items = items, .items_len = 0};
164 struct roar_gopher_menu_item * item;
165 struct roar_client_server * cs;
166 struct roar_client        * c;
167 const size_t len = 80;
168 char * d;
169 size_t i;
170 int ret;
171
172 memset(items, 0, sizeof(items));
173
174 for (i = 0; i < ROAR_CLIENTS_MAX; i++) {
175  if ( (c = ROAR_CLIENT((cs = g_clients[i]))) != NULL ) {
176   item = &(items[menu.items_len++]);
177   item->type = _DIR;
178   d = roar_mm_malloc(len);
179   if ( d == NULL ) {
180    menu.items_len--;
181    continue;
182   }
183   if ( c->name != NULL && c->name[0] != 0 ) {
184    snprintf(d, len, "Client %i: %s", (int)i, c->name);
185   } else {
186    snprintf(d, len, "Client %i", (int)i);
187   }
188   item->name = d;
189
190   d = roar_mm_malloc(len);
191   if ( d == NULL ) {
192    if ( item->name != NULL )
193     roar_mm_free((void*)item->name);
194    menu.items_len--;
195    continue;
196   }
197
198   snprintf(d, len, "/clients/%i/", (int)i);
199   item->selector = d;
200  }
201 }
202
203 ret = send_menu(client, &menu, vio);
204
205 for (i = 0; i < menu.items_len; i++) {
206  if ( items[i].name != NULL )
207   roar_mm_free((void*)items[i].name);
208  if ( items[i].selector != NULL )
209   roar_mm_free((void*)items[i].selector);
210 }
211
212 return ret;
213}
214
215static int scb_streams    (int client, struct roar_vio_calls * vio, char * selector, char ** text, struct item * sitem) {
216 struct roar_gopher_menu_item items[ROAR_STREAMS_MAX];
217 struct roar_gopher_menu menu = {.flags = 0, .items = items, .items_len = 0};
218 struct roar_gopher_menu_item * item;
219 struct roar_stream_server * ss;
220 struct roar_stream        * s;
221 const size_t len = 80;
222 char * d;
223 size_t i;
224 int ret;
225
226 memset(items, 0, sizeof(items));
227
228 for (i = 0; i < ROAR_STREAMS_MAX; i++) {
229  if ( (s = ROAR_STREAM((ss = g_streams[i]))) != NULL ) {
230   item = &(items[menu.items_len++]);
231   item->type = _DIR;
232   d = roar_mm_malloc(len);
233   if ( d == NULL ) {
234    menu.items_len--;
235    continue;
236   }
237   if ( ss->name != NULL && ss->name[0] != 0 ) {
238    snprintf(d, len, "Stream %i: %s", (int)i, ss->name);
239   } else {
240    snprintf(d, len, "Stream %i", (int)i);
241   }
242   item->name = d;
243
244   d = roar_mm_malloc(len);
245   if ( d == NULL ) {
246    if ( item->name != NULL )
247     roar_mm_free((void*)item->name);
248    menu.items_len--;
249    continue;
250   }
251
252   snprintf(d, len, "/streams/%i/", (int)i);
253   item->selector = d;
254  }
255 }
256
257 ret = send_menu(client, &menu, vio);
258
259 for (i = 0; i < menu.items_len; i++) {
260  if ( items[i].name != NULL )
261   roar_mm_free((void*)items[i].name);
262  if ( items[i].selector != NULL )
263   roar_mm_free((void*)items[i].selector);
264 }
265
266 return ret;
267}
268
269static int scb_client_info(int client, struct roar_vio_calls * vio, char * selector, char ** text, struct item * sitem) {
270#define _MAX_ITEMS (16 + ROAR_CLIENTS_MAX_STREAMS_PER_CLIENT)
271 struct roar_gopher_menu_item items[_MAX_ITEMS];
272 struct roar_gopher_menu menu = {.flags = 0, .items = items, .items_len = 0};
273 struct roar_gopher_menu_item * item;
274 struct roar_client_server * cs;
275 struct roar_client        * c;
276 size_t i;
277 int ret;
278 ssize_t toks;
279 char * tok;
280 int id;
281 char tmp[80];
282
283 memset(items, 0, sizeof(items));
284
285 toks = roar_mm_strseltok(sitem->selector, selector, &tok, 1);
286 if ( toks == -1 )
287  return -1;
288
289 id = atoi(tok);
290
291 if ( clients_get_server(id, &cs) == -1 )
292  return -1;
293
294 c = ROAR_CLIENT(cs);
295
296 item = &(items[menu.items_len++]);
297 item->type = _INFO;
298 if ( c->name != NULL && c->name[0] != 0 ) {
299  item->name = _aprintf(64, "Client %i: %s", id, c->name);
300 } else {
301  item->name = _aprintf(64, "Client %i", id);
302 }
303
304 if ( roar_nnode_get_socktype(&(c->nnode)) != ROAR_SOCKET_TYPE_UNKNOWN ) {
305  if ( roar_nnode_to_str(&(c->nnode), tmp, sizeof(tmp)) == 0 ) {
306   item = &(items[menu.items_len++]);
307   item->type = _INFO;
308   item->name = _aprintf(64, "Network node: %s", tmp);
309  }
310 }
311
312 item = &(items[menu.items_len++]);
313 item->type = _INFO;
314 item->name = _aprintf(64, "Protocol: %s", roar_proto2str(c->proto));
315
316 if ( c->execed != -1 ) {
317  item = &(items[menu.items_len++]);
318  item->type = _DIR;
319  item->name = _aprintf(64, "Exected Stream: %i", c->execed);
320  item->selector = _aprintf(64, "/streams/%i/", c->execed);
321 }
322
323 for (i = 0; i < ROAR_CLIENTS_MAX_STREAMS_PER_CLIENT; i++) {
324  if ( c->streams[i] != -1 ) {
325   item = &(items[menu.items_len++]);
326   item->type = _DIR;
327   item->name = _aprintf(64, "Stream: %i", c->streams[i]);
328   item->selector = _aprintf(64, "/streams/%i/", c->streams[i]);
329  }
330 }
331
332 ret = send_menu(client, &menu, vio);
333
334 for (i = 0; i < menu.items_len; i++) {
335  if ( items[i].name != NULL )
336   roar_mm_free((void*)items[i].name);
337  if ( items[i].selector != NULL )
338   roar_mm_free((void*)items[i].selector);
339 }
340
341#undef _MAX_ITEMS
342 return ret;
343}
344
345static int scb_stream_info(int client, struct roar_vio_calls * vio, char * selector, char ** text, struct item * sitem) {
346#define _MAX_ITEMS 12
347 struct roar_gopher_menu_item items[_MAX_ITEMS];
348 struct roar_gopher_menu menu = {.flags = 0, .items = items, .items_len = 0};
349 struct roar_gopher_menu_item * item;
350 struct roar_stream_server * ss;
351 struct roar_stream        * s;
352 size_t i;
353 int ret;
354 ssize_t toks;
355 char * tok;
356 int id;
357
358 memset(items, 0, sizeof(items));
359
360 toks = roar_mm_strseltok(sitem->selector, selector, &tok, 1);
361 if ( toks == -1 )
362  return -1;
363
364 id = atoi(tok);
365
366 if ( streams_get(id, &ss) == -1 )
367  return -1;
368
369 s = ROAR_STREAM(ss);
370
371
372 item = &(items[menu.items_len++]);
373 item->type = _INFO;
374 if ( ss->name != NULL && ss->name[0] != 0 ) {
375  item->name = _aprintf(64, "Stream %i: %s", id, ss->name);
376 } else {
377  item->name = _aprintf(64, "Stream %i", id);
378 }
379
380 item = &(items[menu.items_len++]);
381 item->type = _INFO;
382 item->name = _aprintf(64, "Stream state: %s", roar_streamstate2str(ss->state));
383
384 item = &(items[menu.items_len++]);
385 item->type = _INFO;
386 item->name = _aprintf(64, "Stream direction: %s", roar_dir2str(s->dir));
387
388 item = &(items[menu.items_len++]);
389 item->type = _INFO;
390 item->name = _aprintf(128, "Signal info: rate:%iHz bits:%i channels:%i codec:%s",
391                            s->info.rate, s->info.bits, s->info.channels, roar_codec2str(s->info.codec));
392
393 if ( ss->codec_orgi != -1 && ss->codec_orgi != s->info.codec ) {
394  item = &(items[menu.items_len++]);
395  item->type = _INFO;
396  item->name = _aprintf(64, "Streamed codec: %s", roar_codec2str(ss->codec_orgi));
397 }
398
399 if ( ss->role != -1 ) {
400  item = &(items[menu.items_len++]);
401  item->type = _INFO;
402  item->name = _aprintf(64, "Stream role: %s", roar_role2str(ss->role));
403 }
404
405 item = &(items[menu.items_len++]);
406 item->type = _DIR;
407 item->name = _aprintf(64, "Client: %i", ss->client);
408 item->selector = _aprintf(64, "/clients/%i/", ss->client);
409
410 ret = send_menu(client, &menu, vio);
411
412 for (i = 0; i < menu.items_len; i++) {
413  if ( items[i].name != NULL )
414   roar_mm_free((void*)items[i].name);
415  if ( items[i].selector != NULL )
416   roar_mm_free((void*)items[i].selector);
417 }
418
419#undef _MAX_ITEMS
420 return ret;
421}
422
423static int scb_listen_menu(int client, struct roar_vio_calls * vio, char * selector, char ** text, struct item * sitem) {
424#define _MAX_ITEMS 12
425 struct roar_gopher_menu_item items[_MAX_ITEMS];
426 struct roar_gopher_menu menu = {.flags = 0, .items = items, .items_len = 0};
427 struct roar_gopher_menu_item * item;
428 const char * codec;
429 int ret;
430 int codecs[] = {ROAR_CODEC_DEFAULT, ROAR_CODEC_RIFF_WAVE, ROAR_CODEC_AU, ROAR_CODEC_OGG_VORBIS};
431 size_t i;
432
433 memset(items, 0, sizeof(items));
434
435 item = &(items[menu.items_len++]);
436 item->type = _INFO;
437 item->name = roar_mm_strdup("Select a format you want to listen in:");
438
439 item = &(items[menu.items_len++]);
440 item->type = _INFO;
441 item->name = NULL; // empty lion
442
443 for (i = 0; i < (sizeof(codecs)/sizeof(*codecs)); i++) {
444  item = &(items[menu.items_len++]);
445  item->type = _SOUND;
446  codec = roar_codec2str(codecs[i]);
447  item->name = _aprintf(64, "%u channels with %u bits at %uHz, %s",
448                            g_sa->channels, g_sa->bits, g_sa->rate, codec);
449  item->selector = _aprintf(64, "/listen/monitor/%u/%u/%u/%s", g_sa->rate, g_sa->bits, g_sa->channels, codec);
450 }
451
452 ret = send_menu(client, &menu, vio);
453
454 for (i = 0; i < menu.items_len; i++) {
455  if ( items[i].name != NULL )
456   roar_mm_free((void*)items[i].name);
457  if ( items[i].selector != NULL )
458   roar_mm_free((void*)items[i].selector);
459 }
460
461#undef _MAX_ITEMS
462 return ret;
463}
464
465static int scb_listen     (int client, struct roar_vio_calls * vio, char * selector, char ** text, struct item * sitem) {
466 struct roar_stream_server * ss;
467 struct roar_stream        * s;
468 struct roar_audio_info info;
469 int dir = -1;
470 ssize_t toks;
471 char * tok[5];
472 int stream = -1;
473
474 toks = roar_mm_strseltok(sitem->selector, selector, tok, 5);
475
476 if ( toks != 5 )
477  return -1;
478
479 memset(&info, 0, sizeof(info));
480
481 if ( (dir = roar_str2dir(tok[0])) == -1 )
482  return -1;
483
484 // test for unsupported dirs:
485 switch (dir) {
486  case ROAR_DIR_THRU:
487  case ROAR_DIR_RAW_IN:
488  case ROAR_DIR_FILTER:
489    return -1;
490   break;
491 }
492
493 info.rate     = atoi(tok[1]);
494 info.bits     = atoi(tok[2]);
495 info.channels = atoi(tok[3]);
496 info.codec    = roar_str2codec(tok[4]);
497
498 if ( info.codec == -1 )
499  return -1;
500
501 if ((stream = streams_new()) == -1 )
502  return -1;
503
504 if ( streams_get(stream, &ss) == -1 ) {
505  streams_delete(stream);
506  return -1;
507 }
508
509 s = ROAR_STREAM(ss);
510
511 if ( client_stream_add(client, stream) == -1 ) {
512  streams_delete(stream);
513  return -1;
514 }
515
516 memcpy(&(s->info), &info, sizeof(info));
517 ss->codec_orgi = info.codec;
518
519 if ( streams_set_dir(stream, dir, 1) == -1 ) {
520  streams_delete(stream);
521  return -1;
522 }
523
524 if ( client_stream_exec(client, stream) == -1 ) {
525  streams_delete(stream);
526  return -1;
527 }
528
529 return 0;
530}
531
532// other code:
533static int strip_nl (char * str) {
534 register char c;
535
536 for (; (c = *str) != 0; str++) {
537  if ( c == '\r' || c == '\n' ) {
538   *str = 0;
539   return 1;
540  }
541 }
542
543 return 0;
544}
545
546static char * _aprintf(size_t sizehint, const char * format, ...) {
547 va_list ap;
548 char * buf;
549 int ret;
550
551 sizehint += 128;
552
553 if ( (buf = roar_mm_malloc(sizehint)) == NULL )
554  return NULL;
555
556 va_start(ap, format);
557 ret = vsnprintf(buf, sizehint, format, ap);
558 va_end(ap);
559
560 buf[sizehint-1] = 0;
561
562 return buf;
563}
564
565static int send_menu (int client, struct roar_gopher_menu * menu, struct roar_vio_calls * vio) {
566 struct roar_buffer * buf;
567 struct roar_gopher_menu_item * item;
568 const size_t len = 256;
569 size_t i;
570 void * data;
571 char * chardata;
572 const char * host;
573 unsigned int port;
574 struct roar_sockname sockaddr;
575
576 if ( roar_vio_ctl(vio, ROAR_VIO_CTL_GET_SOCKNAME, &sockaddr) == -1 ) {
577  memset(&sockaddr, 0, sizeof(sockaddr));
578 }
579
580 for (i = 0; i < menu->items_len; i++) {
581  item = &(menu->items[i]);
582  if ( roar_buffer_new_data(&buf, len, &data) == -1 ) {
583   if ( sockaddr.addr != NULL )
584    roar_mm_free(sockaddr.addr);
585   return -1;
586  }
587
588  chardata = data;
589
590  switch (item->type) {
591   case _INFO:
592     snprintf(data, len-1, "i%s\tfake\t(NULL)\t0\r\n", item->name == NULL ? "" : item->name);
593    break;
594   default:
595     host = item->host == NULL ? sockaddr.addr : item->host;
596     port = item->port ==    0 ? sockaddr.port : item->port;
597     snprintf(data, len-1, "%c%s\t%s\t%s\t%u\r\n", item->type, item->name, item->selector, host, port);
598    break;
599  }
600
601  chardata[len-1] = 0;
602
603  if ( roar_buffer_set_len(buf, strlen(data)) == -1 ) {
604   roar_buffer_free(buf);
605   return -1;
606  }
607
608  clients_add_output(client, &buf);
609 }
610
611 if ( sockaddr.addr != NULL )
612  roar_mm_free(sockaddr.addr);
613
614 return 0;
615}
616
617static int send_text (int client, const char * text, struct roar_vio_calls * vio) {
618 struct roar_buffer * buf;
619 void * data;
620 size_t len = strlen(text);
621
622 if ( roar_buffer_new_data(&buf, len+6, &data) == -1 )
623  return -1;
624
625 memcpy(data, text, len);
626 //memcpy(data+len, "\r\n.\r\n\0", 6);
627 memcpy(data+len, "\0", 1);
628 clients_add_output(client, &buf);
629
630 return 0;
631}
632
633int emul_gopher_check_client(int client, struct roar_vio_calls * vio) {
634 struct roar_client_server * cs;
635 struct roar_vio_calls     rvio;
636 struct item * c = NULL;
637 char inbuf[1024];
638 ssize_t ret;
639 size_t i;
640 int funcret = -1;
641 size_t len = 0;
642 void * data;
643 char * text;
644
645 ROAR_DBG("emul_gopher_check_client(client=%i, vio=%p) = ?", client, vio);
646
647 if ( clients_get_server(client, &cs) == -1 ) {
648  clients_delete(client);
649  return -1;
650 }
651
652 ROAR_DBG("emul_gopher_check_client(client=%i, vio=%p) = ?", client, vio);
653
654 if ( vio == NULL ) {
655  vio = &rvio;
656  roar_vio_open_fh_socket(vio, clients_get_fh(client));
657 }
658
659 ROAR_DBG("emul_gopher_check_client(client=%i, vio=%p) = ?", client, vio);
660
661 if ( cs->inbuf != NULL ) {
662  len = sizeof(inbuf)-1;
663  if ( roar_buffer_shift_out(&(cs->inbuf), inbuf, &len) == -1 ) {
664   clients_delete(client);
665   return -1;
666  }
667
668  if ( cs->inbuf != NULL ) {
669   roar_buffer_free(cs->inbuf);
670   clients_delete(client);
671   return -1;
672  }
673
674  // test if we have still buffer space left.
675  if ( len == (sizeof(inbuf)-1) ) {
676   clients_delete(client);
677   return -1;
678  }
679 }
680
681 ROAR_DBG("emul_gopher_check_client(client=%i, vio=%p) = ?", client, vio);
682
683 ret = roar_vio_read(vio, inbuf+len, sizeof(inbuf)-len-1);
684 if ( ret < 1 ) {
685  clients_delete(client);
686  ROAR_DBG("emul_gopher_check_client(client=%i, vio=%p) = -1", client, vio);
687  return -1;
688 }
689
690 ret += len;
691
692 inbuf[ret] = 0;
693
694 ROAR_DBG("emul_gopher_check_client(client=%i, vio=%p) = ?", client, vio);
695
696 if ( !strip_nl(inbuf) ) {
697  if ( roar_buffer_new_data(&(cs->inbuf), ret, &data) == -1 ) {
698   clients_delete(client);
699   ROAR_DBG("emul_gopher_check_client(client=%i, vio=%p) = -1", client, vio);
700   return -1;
701  }
702
703  memcpy(data, inbuf, ret);
704
705  ROAR_DBG("emul_gopher_check_client(client=%i, vio=%p) = 0", client, vio);
706
707  return 0;
708 }
709
710 ROAR_DBG("emul_gopher_check_client(client=%i, vio=%p) = ?", client, vio);
711
712 for (i = 0; i < sizeof(g_gopher_items)/sizeof(*g_gopher_items); i++) {
713//  if ( !roar_mm_strselcmp(g_gopher_items[i].selector, inbuf) ) {
714  if ( !roar_mm_strselcmp(g_gopher_items[i].selector, inbuf) ) {
715   c = &(g_gopher_items[i]);
716   break;
717  }
718 }
719
720 if ( c == NULL ) {
721  clients_delete(client);
722  ROAR_DBG("emul_gopher_check_client(client=%i, vio=%p) = -1", client, vio);
723  return -1;
724 }
725
726 ROAR_DBG("emul_gopher_check_client(client=%i, vio=%p) = ?", client, vio);
727
728 if ( c->cb != NULL ) {
729  text = NULL;
730  funcret = c->cb(client, vio, inbuf, &text, c);
731
732  if ( funcret == 0 && text != NULL )
733   funcret = send_text(client, text, vio);
734
735  if ( text != NULL )
736   roar_mm_free(text);
737 } else {
738  switch (c->type) {
739   case _DIR:
740     funcret = send_menu(client, &(c->menu), vio);
741    break;
742   case _FILE:
743     funcret = send_text(client, c->text, vio);
744    break;
745   default:
746     funcret = -1;
747    break;
748  }
749 }
750
751 ROAR_DBG("emul_gopher_check_client(client=%i, vio=%p) = ?", client, vio);
752
753 if ( funcret == -1 ) {
754  clients_delete(client);
755  ROAR_DBG("emul_gopher_check_client(client=%i, vio=%p) = -1", client, vio);
756  return -1;
757 }
758
759 ROAR_DBG("emul_gopher_check_client(client=%i, vio=%p) = 0", client, vio);
760
761 return 0;
762}
763
764int emul_gopher_flushed_client(int client, struct roar_vio_calls * vio) {
765 ROAR_DBG("emul_gopher_flushed_client(client=%i, vio=%p) = ?", client, vio);
766
767 return clients_delete(client);
768}
769
770#endif
771
772//ll
Note: See TracBrowser for help on using the repository browser.