Edinburgh Speech Tools  2.4-release
 All Classes Functions Variables Typedefs Enumerations Enumerator Friends Pages
EST_ServiceTable.cc
1  /************************************************************************/
2  /* */
3  /* Centre for Speech Technology Research */
4  /* University of Edinburgh, UK */
5  /* Copyright (c) 1996,1997 */
6  /* All Rights Reserved. */
7  /* */
8  /* Permission is hereby granted, free of charge, to use and distribute */
9  /* this software and its documentation without restriction, including */
10  /* without limitation the rights to use, copy, modify, merge, publish, */
11  /* distribute, sublicense, and/or sell copies of this work, and to */
12  /* permit persons to whom this work is furnished to do so, subject to */
13  /* the following conditions: */
14  /* 1. The code must retain the above copyright notice, this list of */
15  /* conditions and the following disclaimer. */
16  /* 2. Any modifications must be clearly marked as such. */
17  /* 3. Original authors' names are not deleted. */
18  /* 4. The authors' names are not used to endorse or promote products */
19  /* derived from this software without specific prior written */
20  /* permission. */
21  /* */
22  /* THE UNIVERSITY OF EDINBURGH AND THE CONTRIBUTORS TO THIS WORK */
23  /* DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING */
24  /* ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT */
25  /* SHALL THE UNIVERSITY OF EDINBURGH NOR THE CONTRIBUTORS BE LIABLE */
26  /* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES */
27  /* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN */
28  /* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, */
29  /* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF */
30  /* THIS SOFTWARE. */
31  /* */
32  /*************************************************************************/
33  /* */
34  /* Author: Richard Caley (rjc@cstr.ed.ac.uk) */
35  /* -------------------------------------------------------------------- */
36  /* Table of known services. */
37  /* */
38  /*************************************************************************/
39 #include <cstdlib>
40 #include <iomanip>
41 #include <iostream>
42 #include <ctime>
43 
44 using namespace std;
45 
46 #include "EST_Pathname.h"
47 #include "EST_socket.h"
48 #include "EST_error.h"
49 #include "EST_Token.h"
50 #include "EST_ServiceTable.h"
51 
52 #if defined(SYSTEM_IS_WIN32)
53 # define seed_random() srand((unsigned)time(NULL))
54 # define get_random() rand()
55 #else
56 # define seed_random() srandom(time(NULL));
57 # define get_random() random()
58 #endif
59 
60 #if defined(__sun__) && defined(__sparc__) && defined(__svr4__)
61 /* Solaris */
62 extern "C" {
63 long random();
64 #if defined(older_solaris)
65 int srandom( unsigned seed);
66 int gethostname(char *name, int namelen);
67 #endif
68 }
69 #endif
70 
71 
72 EST_ServiceTable::EntryTable EST_ServiceTable::entries;
73 bool EST_ServiceTable::random_init=FALSE;
74 
75 void EST_ServiceTable::init_random(void)
76 {
77  if (!random_init)
78  {
79  random_init=TRUE;
80  seed_random();
81  }
82 }
83 
84 bool operator == (const EST_ServiceTable::Entry &a, const EST_ServiceTable::Entry &b)
85 {
86  return &a == &b;
87 }
88 
90 {
91  name="";
92  type="";
93  hostname="";
94  address="";
95  cookie="";
96  port=0;
97 }
98 
99 EST_ServiceTable::Entry::operator EST_String() const
100 {
101  return EST_String::cat("{ ServiceTable entry ",
102  type,
103  ":",
104  name,
105  " }");
106 }
107 
108 
109 
111 {
112  EST_TokenStream str;
113  FILE *sfile;
114 
115  if ((sfile = fopen(socketsFileName, "r"))==NULL)
116  return;
117 
118  if (str.open(sfile, 1))
119  EST_sys_error("Can't access fringe file '%s'",
120  (const char *)socketsFileName);
121 
122  str.set_SingleCharSymbols("(){}[]#=.");
123 
124  while(!str.eof())
125  {
126  EST_Token tok = str.get();
127 
128  if (tok == "#")
129  {
130  str.get_upto_eoln();
131  continue;
132  }
133 
134  EST_String name = tok;
135 
136  str.must_get(".");
137 
138  tok = str.get();
139  EST_String type = tok;
140 
141  str.must_get("=");
142 
143  EST_Token val = str.get_upto_eoln();
144 
145  if (!entries.t.present(name))
146  {
147  Entry newent;
148  newent.name=name;
149  entries.t.add_item(name, newent);
150  }
151 
152  Entry &entry = entries.t.val(name);
153 
154  if (type=="host")
155  entry.hostname=(EST_String)val;
156  else if (type=="address")
157  entry.address=(EST_String)val;
158  else if (type=="type")
159  entry.type=(EST_String)val;
160  else if (type=="port")
161  entry.port=val;
162  else if (type=="cookie")
163  entry.cookie=(EST_String)val;
164  else
165  EST_warning("Unknown entry field '%s' at %s",
166  (const char *)type,
167  (const char *)str.pos_description());
168  }
169 
170  str.close();
171 }
172 
174 {
175  FILE *f;
176 
177  if ((f=fopen(filename, "w"))==NULL)
178  EST_sys_error("can't write serice file");
179 
180  fprintf(f, "#Services\n");
181 
183 
184  for(p.begin(entries.t); p ; ++p)
185  {
186  const EST_String &name = p->k;
187  const Entry &entry = p->v;
188 
189  fprintf(f, "%s.type=%s\n", (const char *)name, (const char *)entry.type);
190  fprintf(f, "%s.cookie=%s\n", (const char *)name, (const char *)entry.cookie);
191  fprintf(f, "%s.host=%s\n", (const char *)name, (const char *)entry.hostname);
192  fprintf(f, "%s.address=%s\n", (const char *)name, (const char *)entry.address);
193  fprintf(f, "%s.port=%d\n", (const char *)name, entry.port);
194  }
195 
196  fclose(f);
197 }
198 
199 
201 {
202  EST_Pathname socketsFileName(getenv("HOME")?getenv("HOME"):"/");
203 
204  socketsFileName += ".estServices";
205 
206  read_table(socketsFileName);
207 }
208 
210 {
211  EST_Pathname socketsFileName(getenv("HOME")?getenv("HOME"):"/");
212 
213  socketsFileName += ".estServices";
214 
215  write_table(socketsFileName);
216 }
217 
218 void EST_ServiceTable::list(ostream &s, const EST_String type)
219 {
220 
221  EntryTable::KeyEntries keys(entries.t);
222  char buff[31];
223 
224  s << "Known names:";
225  while(keys.has_more_elements())
226  {
227  EST_String key = keys.next_element();
228  s << " " << key;
229  }
230 
231  s << "\n\n";
232 
233  if (type != "")
234  s << "Entries of type " << type << ":\n";
235 
236  EntryTable::Entries them;
237 
238  //fmtflags old=s.flags();
239  s.setf(ios::left);
240  // (problems with iomanip in gcc-2.95.1 require oldfashioned solutions)
241 
242  s << " ";
243  sprintf(buff,"%10s","Name");
244  s << buff;
245  sprintf(buff,"%30s"," Hostname");
246  s << buff;
247  sprintf(buff,"%20s"," IP Address");
248  s << buff;
249  sprintf(buff,"%5s\n","Port");
250  s << buff;
251 
252  for(them.begin(entries.t); them; them++)
253  {
254  const Entry &entry = them->v;
255 
256  if (type != "" && entry.type != type)
257  continue;
258 
259  s << " ";
260  sprintf(buff,"%10s",(const char *)entry.name);
261  s << buff;
262  sprintf(buff,"%30s",(const char *)entry.hostname);
263  s << buff;
264  sprintf(buff,"%20s",(const char *)entry.address);
265  s << buff;
266  s << entry.port << "\n";
267  }
268 
269  // s.flags(old);
270 }
271 
273 {
274  names.clear();
275  EntryTable::Entries them;
276  for(them.begin(entries.t); them; them++)
277  if (type=="" || type == them->v.name)
278  names.append(them->k);
279 }
280 
282  const EST_String type)
283 {
284  if (entries.t.present(name))
285  {
286  Entry &entry = entries.t.val(name);
287 
288  if (entry.type == type)
289  return entry;
290  }
291 
292  return *(entries.t.default_val);
293 }
294 
296  const EST_String type,
297  int socket)
298 {
299  init_random();
300  Entry entry;
301  long cookie = get_random();
302  struct sockaddr_in sin;
303 
304  socklen_t size=sizeof(struct sockaddr_in);
305 
306  // This only gets the port number
307 
308  if (getsockname(socket, (struct sockaddr *)&sin, &size) != 0)
309  EST_sys_error("Can't find my address");
310 
311 
312  // We have to get an address by looking ourselves up.
313  char myname[100];
314 
315  gethostname(myname, 100);
316 
317  struct hostent *hent = gethostbyname(myname);
318 
319  if (hent == NULL)
320  EST_sys_error("Can't look up my address");
321 
322  // Arbitrarily choose the first address.
323  if (hent->h_addr_list != NULL)
324  memcpy(&(sin.sin_addr.s_addr),hent->h_addr_list[0], sizeof (sin.sin_addr.s_addr));
325 
326  EST_String address= inet_ntoa(sin.sin_addr);
327 
328  entry.name = name;
329  entry.type = type;
330  entry.cookie = EST_String::Number(cookie);
331  entry.port = ntohs(sin.sin_port);
332  entry.address = address;
333  entry.hostname = hent->h_name;
334 
335  entries.t.add_item(name, entry);
336 
337  return entries.t.val(name);
338 }
339 
340 
341 
342 Declare_KVL_T(EST_String, EST_ServiceTable::Entry, EST_String_ST_entry)
343 
344 #if defined(INSTANTIATE_TEMPLATES)
345 
346 #include "../base_class/EST_TList.cc"
347 #include "../base_class/EST_TSortable.cc"
348 #include "../base_class/EST_TKVL.cc"
349 
350 Instantiate_KVL_T(EST_String, EST_ServiceTable::Entry, EST_String_ST_entry)
351 
352 #endif
353 
354