source: roaraudio/plugins/roard/protocol-gopher.c @ 4704:eeb6e758fced

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

prepare better NULL handling

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