+}
+
+/* @timeout: max blocking time in milliseconds, -1 means infinity
+ *
+ * returns 1 to indicate a message was received
+ * returns 0 to indicate no message was received
+ * returns -1 to indicate an error
+ */
+
+int ustcomm_recv_message(struct ustcomm_server *server, char **msg, struct ustcomm_source *src, int timeout)
+{
+ struct pollfd *fds;
+ struct ustcomm_connection *conn;
+ int result;
+ int retval;
+
+ for(;;) {
+ int idx = 0;
+ int n_fds = 1;
+
+ list_for_each_entry(conn, &server->connections, list) {
+ n_fds++;
+ }
+
+ fds = (struct pollfd *) malloc(n_fds * sizeof(struct pollfd));
+ if(fds == NULL) {
+ ERR("malloc returned NULL");
+ return -1;
+ }
+
+ /* special idx 0 is for listening socket */
+ fds[idx].fd = server->listen_fd;
+ fds[idx].events = POLLIN;
+ idx++;
+
+ list_for_each_entry(conn, &server->connections, list) {
+ fds[idx].fd = conn->fd;
+ fds[idx].events = POLLIN;
+ idx++;
+ }
+
+ result = poll(fds, n_fds, timeout);
+ if(result == -1) {
+ PERROR("poll");
+ return -1;
+ }
+
+ if(result == 0)
+ return 0;
+
+ if(fds[0].revents) {
+ struct ustcomm_connection *newconn;
+ int newfd;
+
+ result = newfd = accept(server->listen_fd, NULL, NULL);
+ if(result == -1) {
+ PERROR("accept");
+ return -1;
+ }
+
+ newconn = (struct ustcomm_connection *) malloc(sizeof(struct ustcomm_connection));
+ if(newconn == NULL) {
+ ERR("malloc returned NULL");
+ return -1;
+ }
+
+ newconn->fd = newfd;
+
+ list_add(&newconn->list, &server->connections);
+ }
+
+ for(idx=1; idx<n_fds; idx++) {
+ if(fds[idx].revents) {
+ retval = recv_message_fd(fds[idx].fd, msg, src);
+ if(**msg == 0) {
+ /* connection finished */
+ close(fds[idx].fd);
+
+ list_for_each_entry(conn, &server->connections, list) {
+ if(conn->fd == fds[idx].fd) {
+ list_del(&conn->list);
+ break;
+ }
+ }
+ }
+ else {
+ goto free_fds_return;
+ }
+ }
+ }
+
+ free(fds);
+ }
+
+free_fds_return:
+ free(fds);
+ return retval;
+}
+
+int ustcomm_ustd_recv_message(struct ustcomm_ustd *ustd, char **msg, struct ustcomm_source *src, int timeout)
+{
+ return ustcomm_recv_message(&ustd->server, msg, src, timeout);
+}
+
+int ustcomm_app_recv_message(struct ustcomm_app *app, char **msg, struct ustcomm_source *src, int timeout)
+{
+ return ustcomm_recv_message(&app->server, msg, src, timeout);
+}
+
+/* This removes src from the list of active connections of app.
+ */
+
+int ustcomm_app_detach_client(struct ustcomm_app *app, struct ustcomm_source *src)
+{
+ struct ustcomm_server *server = (struct ustcomm_server *)app;
+ struct ustcomm_connection *conn;
+
+ list_for_each_entry(conn, &server->connections, list) {
+ if(conn->fd == src->fd) {
+ list_del(&conn->list);
+ goto found;
+ }
+ }
+
+ return -1;
+found:
+ return src->fd;