source: roaraudio/plugins/roard/protocol-gopher.c @ 4703:be4d84be6f04

Last change on this file since 4703:be4d84be6f04 was 4703:be4d84be6f04, checked in by phi, 13 years ago

added basic gopher support

File size: 4.9 KB
Line 
1//emul_gopher.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010
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
36static struct roar_gopher_menu_item g_gopher_root_menu[] = {
37 {.type = _INFO, .name = "roard Root Menu"},
38 {.type = _FILE, .name = "Server Info", .selector = "/info.txt", .host = NULL, .port = 0}
39};
40
41static struct item {
42 const char * selector;
43 char type;
44 struct roar_gopher_menu menu;
45 struct roar_audio_info  info;
46 int dir;
47 const char * text;
48} g_gopher_items[] = {
49 {.selector = "", .type = _DIR,
50  .menu = {.items = g_gopher_root_menu, .items_len = sizeof(g_gopher_root_menu)/sizeof(*g_gopher_root_menu)}
51 },
52 // and again as selector '/' as some clients seems to require it:
53 {.selector = "/", .type = _DIR,
54  .menu = {.items = g_gopher_root_menu, .items_len = sizeof(g_gopher_root_menu)/sizeof(*g_gopher_root_menu)}
55 },
56 {.selector = "/info.txt", .type = _FILE, .text = "Some\nText."}
57};
58
59
60static int strip_nl (char * str) {
61 register char c;
62
63 for (; (c = *str) != 0; str++) {
64  if ( c == '\r' || c == '\n' ) {
65   *str = 0;
66   return 1;
67  }
68 }
69
70 return 0;
71}
72
73static int send_menu (int client, struct roar_gopher_menu * menu) {
74 struct roar_buffer * buf;
75 struct roar_gopher_menu_item * item;
76 const size_t len = 80;
77 size_t i;
78 void * data;
79 char * chardata;
80
81 for (i = 0; i < menu->items_len; i++) {
82  item = &(menu->items[i]);
83  if ( roar_buffer_new_data(&buf, len, &data) == -1 )
84   return -1;
85
86  chardata = data;
87
88  switch (item->type) {
89   case _INFO:
90     snprintf(data, len-1, "i%s\tfake\t(NULL)\t0\r\n", item->name);
91    break;
92   default:
93     snprintf(data, len-1, "%c%s\t%s\t%s\t%u\r\n", item->type, item->name, item->selector, item->host, item->port);
94    break;
95  }
96
97  chardata[len-1] = 0;
98
99  roar_buffer_set_len(buf, strlen(data));
100
101  clients_add_output(client, buf);
102 }
103
104 return 0;
105}
106
107static int send_text (int client, const char * text) {
108 struct roar_buffer * buf;
109 void * data;
110 size_t len = strlen(text);
111
112 if ( roar_buffer_new_data(&buf, len+6, &data) == -1 )
113  return -1;
114
115 memcpy(data, text, len);
116 memcpy(data+len, "\r\n.\r\n\0", 6);
117 clients_add_output(client, buf);
118
119 return 0;
120}
121
122int emul_gopher_check_client(int client, struct roar_vio_calls * vio) {
123 struct roar_client_server * cs;
124 struct roar_vio_calls     rvio;
125 struct item * c = NULL;
126 char inbuf[1024];
127 ssize_t ret;
128 size_t i;
129 int funcret = -1;
130 size_t len = 0;
131 void * data;
132
133 if ( clients_get_server(client, &cs) == -1 ) {
134  clients_delete(client);
135  return -1;
136 }
137
138 if ( vio == NULL ) {
139  vio = &rvio;
140  roar_vio_open_fh_socket(vio, clients_get_fh(client));
141 }
142
143 if ( cs->inbuf != NULL ) {
144  len = sizeof(inbuf)-1;
145  if ( roar_buffer_shift_out(&(cs->inbuf), inbuf, &len) == -1 ) {
146   clients_delete(client);
147   return -1;
148  }
149
150  if ( cs->inbuf != NULL ) {
151   roar_buffer_free(cs->inbuf);
152   clients_delete(client);
153   return -1;
154  }
155
156  // test if we have still buffer space left.
157  if ( len == (sizeof(inbuf)-1) ) {
158   clients_delete(client);
159   return -1;
160  }
161 }
162
163 ret = roar_vio_read(vio, inbuf+len, sizeof(inbuf)-len-1);
164 if ( ret < 1 ) {
165  clients_delete(client);
166  return -1;
167 }
168
169 ret += len;
170
171 inbuf[ret] = 0;
172
173 if ( !strip_nl(inbuf) ) {
174  if ( roar_buffer_new_data(&(cs->inbuf), ret, &data) == -1 ) {
175   clients_delete(client);
176   return -1;
177  }
178
179  memcpy(data, inbuf, ret);
180  return 0;
181 }
182
183 for (i = 0; i < sizeof(g_gopher_items)/sizeof(*g_gopher_items); i++) {
184  if ( !strcmp(g_gopher_items[i].selector, inbuf) ) {
185   c = &(g_gopher_items[i]);
186   break;
187  }
188 }
189
190 if ( c == NULL ) {
191  clients_delete(client);
192  return -1;
193 }
194
195 switch (c->type) {
196  case _DIR:
197    funcret = send_menu(client, &(c->menu));
198   break;
199  case _FILE:
200    funcret = send_text(client, c->text);
201   break;
202  default:
203    funcret = -1;
204   break;
205 }
206
207 if ( funcret == -1 ) {
208  clients_delete(client);
209  return -1;
210 }
211
212 return 0;
213}
214
215int emul_gopher_flushed_client(int client, struct roar_vio_calls * vio) {
216 return clients_delete(client);
217}
218
219#endif
220
221//ll
Note: See TracBrowser for help on using the repository browser.