CSL  5.2
nonblocking_server_example.c
Go to the documentation of this file.
1 /*
2  * nonblocking_server_example.c
3  *
4  * This code demonstrates two methods of monitoring both an lo_server
5  * and other I/O from a single thread.
6  *
7  * Copyright (C) 2004 Steve Harris, Uwe Koloska
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU Lesser General Public License as
11  * published by the Free Software Foundation; either version 2.1 of the
12  * License, or (at your option) any later version.
13  *
14  * This program 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 Lesser General Public License for more details.
18  *
19  * $Id$
20  */
21 
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <sys/time.h>
25 #include <sys/types.h>
26 #include <strings.h>
27 #include <unistd.h>
28 
29 #include "lo/lo.h"
30 
31 int done = 0;
32 
33 void error(int num, const char *m, const char *path);
34 
35 int generic_handler(const char *path, const char *types, lo_arg **argv,
36  int argc, void *data, void *user_data);
37 
38 int foo_handler(const char *path, const char *types, lo_arg **argv, int argc,
39  void *data, void *user_data);
40 
41 int quit_handler(const char *path, const char *types, lo_arg **argv, int argc,
42  void *data, void *user_data);
43 
44 void read_stdin(void);
45 
46 int main()
47 {
48  int lo_fd;
49  fd_set rfds;
50  struct timeval tv;
51  int retval;
52 
53  /* start a new server on port 7770 */
54  lo_server s = lo_server_new("7770", error);
55 
56  /* add method that will match any path and args */
57  lo_server_add_method(s, NULL, NULL, generic_handler, NULL);
58 
59  /* add method that will match the path /foo/bar, with two numbers, coerced
60  * to float and int */
61  lo_server_add_method(s, "/foo/bar", "fi", foo_handler, NULL);
62 
63  /* add method that will match the path /quit with no args */
64  lo_server_add_method(s, "/quit", "", quit_handler, NULL);
65 
66  /* get the file descriptor of the server socket, if supported */
67  lo_fd = lo_server_get_socket_fd(s);
68 
69  if (lo_fd > 0) {
70 
71  /* select() on lo_server fd is supported, so we'll use select()
72  * to watch both stdin and the lo_server fd. */
73 
74  do {
75 
76  FD_ZERO(&rfds);
77 #ifndef WIN32
78  FD_SET(0, &rfds); /* stdin */
79 #endif
80  FD_SET(lo_fd, &rfds);
81 
82  retval = select(lo_fd + 1, &rfds, NULL, NULL, NULL); /* no timeout */
83 
84  if (retval == -1) {
85 
86  printf("select() error\n");
87  exit(1);
88 
89  } else if (retval > 0) {
90 
91  if (FD_ISSET(0, &rfds)) {
92 
93  read_stdin();
94 
95  }
96  if (FD_ISSET(lo_fd, &rfds)) {
97 
99 
100  }
101  }
102 
103  } while (!done);
104 
105  } else {
106 
107  /* lo_server protocol does not support select(), so we'll watch
108  * stdin while polling the lo_server. */
109 #ifdef WIN32
110  printf("non-blocking input from stdin not supported under Windows\n");
111  exit(1);
112 #else
113  do {
114 
115  FD_ZERO(&rfds);
116  FD_SET(0, &rfds);
117  tv.tv_sec = 0;
118  tv.tv_usec = 10000;
119 
120  retval = select(1, &rfds, NULL, NULL, &tv); /* timeout every 10ms */
121 
122  if (retval == -1) {
123 
124  printf("select() error\n");
125  exit(1);
126 
127  } else if (retval > 0 && FD_ISSET(0, &rfds)) {
128 
129  read_stdin();
130 
131  }
132 
134 
135  } while (!done);
136 #endif
137  }
138 
139  return 0;
140 }
141 
142 void error(int num, const char *msg, const char *path)
143 {
144  printf("liblo server error %d in path %s: %s\n", num, path, msg);
145 }
146 
147 /* catch any incoming messages and display them. returning 1 means that the
148  * message has not been fully handled and the server should try other methods */
149 int generic_handler(const char *path, const char *types, lo_arg **argv,
150  int argc, void *data, void *user_data)
151 {
152  int i;
153 
154  printf("path: <%s>\n", path);
155  for (i=0; i<argc; i++) {
156  printf("arg %d '%c' ", i, types[i]);
157  lo_arg_pp(types[i], argv[i]);
158  printf("\n");
159  }
160  printf("\n");
161  fflush(stdout);
162 
163  return 1;
164 }
165 
166 int foo_handler(const char *path, const char *types, lo_arg **argv, int argc,
167  void *data, void *user_data)
168 {
169  /* example showing pulling the argument values out of the argv array */
170  printf("%s <- f:%f, i:%d\n\n", path, argv[0]->f, argv[1]->i);
171  fflush(stdout);
172 
173  return 0;
174 }
175 
176 int quit_handler(const char *path, const char *types, lo_arg **argv, int argc,
177  void *data, void *user_data)
178 {
179  done = 1;
180  printf("quiting\n\n");
181 
182  return 0;
183 }
184 
185 void read_stdin(void)
186 {
187  char buf[256];
188  int len = read(0, buf, 256);
189  if (len > 0) {
190  printf("stdin: ");
191  fwrite(buf, len, 1, stdout);
192  printf("\n");
193  fflush(stdout);
194  }
195 }
196 
197 /* vi:set ts=8 sts=4 sw=4: */