source: roaraudio/plugins/roard/protocol-gopher.c @ 4705:109ee6f17831

Last change on this file since 4705:109ee6f17831 was 4705:109ee6f17831, checked in by phi, 13 years ago

got gopher finally working, now moving myself into sleepingbag device...

File size: 5.4 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, struct roar_vio_calls * vio) {
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 const char * host;
81 unsigned int port;
82 struct roar_sockname sockaddr;
83
84 if ( roar_vio_ctl(vio, ROAR_VIO_CTL_GET_SOCKNAME, &sockaddr) == -1 ) {
85  memset(&sockaddr, 0, sizeof(sockaddr));
86 }
87
88 for (i = 0; i < menu->items_len; i++) {
89  item = &(menu->items[i]);
90  if ( roar_buffer_new_data(&buf, len, &data) == -1 ) {
91   if ( sockaddr.addr != NULL )
92    roar_mm_free(sockaddr.addr);
93   return -1;
94  }
95
96  chardata = data;
97
98  switch (item->type) {
99   case _INFO:
100     snprintf(data, len-1, "i%s\tfake\t(NULL)\t0\r\n", item->name);
101    break;
102   default:
103     host = item->host == NULL ? sockaddr.addr : item->host;
104     port = item->port ==    0 ? sockaddr.port : item->port;
105     snprintf(data, len-1, "%c%s\t%s\t%s\t%u\r\n", item->type, item->name, item->selector, host, port);
106    break;
107  }
108
109  chardata[len-1] = 0;
110
111  roar_buffer_set_len(buf, strlen(data));
112
113  clients_add_output(client, buf);
114 }
115
116 if ( sockaddr.addr != NULL )
117  roar_mm_free(sockaddr.addr);
118
119 return 0;
120}
121
122static int send_text (int client, const char * text, struct roar_vio_calls * vio) {
123 struct roar_buffer * buf;
124 void * data;
125 size_t len = strlen(text);
126
127 if ( roar_buffer_new_data(&buf, len+6, &data) == -1 )
128  return -1;
129
130 memcpy(data, text, len);
131 memcpy(data+len, "\r\n.\r\n\0", 6);
132 clients_add_output(client, buf);
133
134 return 0;
135}
136
137int emul_gopher_check_client(int client, struct roar_vio_calls * vio) {
138 struct roar_client_server * cs;
139 struct roar_vio_calls     rvio;
140 struct item * c = NULL;
141 char inbuf[1024];
142 ssize_t ret;
143 size_t i;
144 int funcret = -1;
145 size_t len = 0;
146 void * data;
147
148 if ( clients_get_server(client, &cs) == -1 ) {
149  clients_delete(client);
150  return -1;
151 }
152
153 if ( vio == NULL ) {
154  vio = &rvio;
155  roar_vio_open_fh_socket(vio, clients_get_fh(client));
156 }
157
158 if ( cs->inbuf != NULL ) {
159  len = sizeof(inbuf)-1;
160  if ( roar_buffer_shift_out(&(cs->inbuf), inbuf, &len) == -1 ) {
161   clients_delete(client);
162   return -1;
163  }
164
165  if ( cs->inbuf != NULL ) {
166   roar_buffer_free(cs->inbuf);
167   clients_delete(client);
168   return -1;
169  }
170
171  // test if we have still buffer space left.
172  if ( len == (sizeof(inbuf)-1) ) {
173   clients_delete(client);
174   return -1;
175  }
176 }
177
178 ret = roar_vio_read(vio, inbuf+len, sizeof(inbuf)-len-1);
179 if ( ret < 1 ) {
180  clients_delete(client);
181  return -1;
182 }
183
184 ret += len;
185
186 inbuf[ret] = 0;
187
188 if ( !strip_nl(inbuf) ) {
189  if ( roar_buffer_new_data(&(cs->inbuf), ret, &data) == -1 ) {
190   clients_delete(client);
191   return -1;
192  }
193
194  memcpy(data, inbuf, ret);
195  return 0;
196 }
197
198 for (i = 0; i < sizeof(g_gopher_items)/sizeof(*g_gopher_items); i++) {
199  if ( !strcmp(g_gopher_items[i].selector, inbuf) ) {
200   c = &(g_gopher_items[i]);
201   break;
202  }
203 }
204
205 if ( c == NULL ) {
206  clients_delete(client);
207  return -1;
208 }
209
210 switch (c->type) {
211  case _DIR:
212    funcret = send_menu(client, &(c->menu), vio);
213   break;
214  case _FILE:
215    funcret = send_text(client, c->text, vio);
216   break;
217  default:
218    funcret = -1;
219   break;
220 }
221
222 if ( funcret == -1 ) {
223  clients_delete(client);
224  return -1;
225 }
226
227 return 0;
228}
229
230int emul_gopher_flushed_client(int client, struct roar_vio_calls * vio) {
231 return clients_delete(client);
232}
233
234#endif
235
236//ll
Note: See TracBrowser for help on using the repository browser.