Example #1
0
File: main.c Project: dsd/fprintd
static int setup_pollfds(void)
{
	size_t numfds;
	size_t i;
	struct fp_pollfd *fpfds;
	GSource *gsource = g_source_new(&sourcefuncs, sizeof(struct fdsource));

	fdsource = (struct fdsource *) gsource;
	fdsource->pollfds = NULL;

	numfds = fp_get_pollfds(&fpfds);
	if (numfds < 0) {
		if (fpfds)
			free(fpfds);
		return (int) numfds;
	} else if (numfds > 0) {
		for (i = 0; i < numfds; i++) {
			struct fp_pollfd *fpfd = &fpfds[i];
			pollfd_add(fpfd->fd, fpfd->events);
		}
	}

	free(fpfds);
	fp_set_pollfd_notifiers(pollfd_added_cb, pollfd_removed_cb);
	g_source_attach(gsource, NULL);
	return 0;
}
Example #2
0
static void 
main_loop(int listen_fd, int event_sub_fd) {
  int i, nready;
  int new_fd;
  int deleted_entry;

  struct sockaddr_in client_addr;
  socklen_t client_len;

  pollfd_add(pfdinfo, listen_fd, POLLIN, NULL); 
  pollfd_add(pfdinfo, event_sub_fd, POLLIN, NULL); 

  /* Main loop */
  while(1) {
    deleted_entry = 0;
		GDEBUG(1, "Before poll():");
    PRINT_POLLFDINFO(pfdinfo);

    /* Poll */
    nready = poll(pfdinfo->pollfd, pfdinfo->nfds, -1);
    /* There is an error? */
    if(nready == -1) {
      fprintf(stderr, "poll() error: %s; I continue.\n", strerror(errno));
      continue;
    }

    for(i = 0; i < pfdinfo->nfds; i++) {
      if(pfdinfo->pollfd[i].revents == 0)
        continue;
      GDEBUG(1, "fd = %d is ready for event 0x%X\n", pfdinfo->pollfd[i].fd, pfdinfo->pollfd[i].revents);
      /* If there is an error, I close the connection */
      if( pfdinfo->pollfd[i].revents & POLLERR || pfdinfo->pollfd[i].revents & POLLHUP || 
          pfdinfo->pollfd[i].revents & POLLNVAL) {
          /* printf("Error, getchar():\n"); getchar(); */
          close_connection(pfdinfo, i);
          deleted_entry = 1;
          if(--nready < 0) break;
          continue;
      }

	    /*********************************************/
	    /* New Connection/Event Subscribe management */
	    /*********************************************/
	    if((pfdinfo->pollfd[i].fd == listen_fd || pfdinfo->pollfd[i].fd == event_sub_fd) 
          && pfdinfo->pollfd[i].revents & POLLIN) {
        enum client_type type;
        int size;
        enum client_state state;
        if(pfdinfo->pollfd[i].fd == listen_fd) {
          type = REQ_RESP;
          size = sizeof(struct handshake);
          state = WAITING_ARCH;
        } else {
          type = EVENT_SUB;
          size = sizeof(struct rsc_es_hdr);
          state = CONN_READING_HDR;
        }
        
	      bzero(&client_addr, sizeof(client_addr));
	      client_len = sizeof(client_addr);
	
	      /* I accept the new connection */
	      new_fd = accept(pfdinfo->pollfd[i].fd, (struct sockaddr *)&client_addr, &client_len); 
	
	      if(new_fd == -1) {
	        fprintf(stderr, "Accept() error: %s\n", strerror(errno));
	      } else {
	        /* I create the new client structure */
	        struct client *new_client;
          void *data;
	        new_client = create_client(new_fd, type, state);
          data = malloc(sizeof(struct handshake));
          if(data == NULL) {
            close(new_fd);
            if(--nready < 0) break;
            continue;
          }

	        if(new_client == NULL || data == NULL) {
	          fprintf(stderr, "I cannot create a new client struct for fd %d\n", new_fd);
            if(new_client == NULL)
              free(new_client);
            if(data == NULL);
              free(data);
	          close(new_fd);
	        } else {
            buff_enq(new_client->rbuf, data, size);
			      GDEBUG(1, "Accepting new connection from "); print_addr_port(new_client->fd); GDEBUG(1, " (fd = %d).\n", new_client->fd);
            pollfd_add(pfdinfo, new_client->fd, POLLIN, new_client);
	        }
	      }
	      if(--nready <= 0) break;
        /*************************************************************************/
        /* Management of descriptors ready to read of type REQ_RESP or EVENT_SUB */
        /*************************************************************************/
      } else if(pfdinfo->clients[i]->type == REQ_RESP || pfdinfo->clients[i]->type == EVENT_SUB) {
        struct client *client = pfdinfo->clients[i];
        /***********************************************/
        /*  POLLIN                                     */
        /***********************************************/
        if(pfdinfo->pollfd[i].revents &  POLLIN) {
	        void *buf;
	        int size, nread;
          /* If there are data to read, but the read buffer is empty 
           * I create a new message */
          if(client->rbuf->first == NULL) {
            int size = 0;
            void *data;
            if(pfdinfo->clients[i]->type == REQ_RESP && 
                pfdinfo->clients[i]->state == CONN_READING_HDR)
              size = sizeof(struct req_header);
            else if(pfdinfo->clients[i]->type == EVENT_SUB && 
                pfdinfo->clients[i]->state == CONN_READING_HDR)
              size = sizeof(struct rsc_es_hdr);
            if(size != 0) {
              data = malloc(size);
              if(data == NULL) {
                close_connection(pfdinfo, i);
                deleted_entry = 1;
                if(--nready < 0) break;
                continue;
              }

              buff_enq(client->rbuf, data, size);
            }
          }
		      GDEBUG(1, "There are data ready do be read for fd %d", pfdinfo->pollfd[i].fd);
          /* I read the data from the first message */
	        buf = client->rbuf->first->data + client->rbuf->first->n;
	        size = client->rbuf->first->tot - client->rbuf->first->n;
			    nread = read(client->fd, buf, size);
	        if(nread <= 0 ) {
	          /* If there is an error or the connection was close,
             * I close the connection from my side */
            close_connection(pfdinfo, i);
            deleted_entry = 1;
            if(--nready <= 0) break;
            continue;
          } else {
	          client->rbuf->first->n += nread;
          }
			    
          /* If I've read all the data, I remove the buffer from client->rbuf
           * and I process the data */
			    if(client->rbuf->first->n == client->rbuf->first->tot) {
            void *read_data = buff_deq(client->rbuf);
	          if(pfdinfo->clients[i]->type == REQ_RESP) {
				      if(client->state == WAITING_ARCH) {
			          /* I read the architecture of the client */
					      struct handshake *client_arch, *server_arch;
			          client_arch = (struct handshake *)read_data;
				
						    client->arch = ntohl(client_arch->arch);
						    GDEBUG(1, "Client (%d) architecture is %s\n", client->fd, aconv_arch2str(client->arch));
                free(read_data);
						    
						    /* Now I can send my architecture */
		            client->state = SENDING_ARCH;
		            server_arch = calloc(1, sizeof(struct handshake));
		            if(server_arch == NULL) {
                  close_connection(pfdinfo, i);
                  deleted_entry = 1;
                  if(--nready < 0) break;
                  continue;
                }
                server_arch->arch = htonl(my_arch);
		            buff_enq(client->wbuf, server_arch, sizeof(struct handshake));
                pfdinfo->pollfd[i].events |=  POLLOUT;
                client->state = SENDING_ARCH;
				      }else if(client->state == CONN_READING_HDR) {
			          struct req_header *req_hd;
                struct msg *m;
		            int req_size;
                void *new_data;
		            /* I've read all the request header, now I've to read all the request body */
                client->state = CONN_READING_BODY;
		            req_hd = (struct req_header *)read_data;
			          req_size = rsc_req_msg_size(req_hd);
                new_data = realloc(read_data, req_size);
                if(new_data == NULL) {
                  close_connection(pfdinfo, i);
                  deleted_entry = 1;
                  if(--nready < 0) break;
                  continue;
                }

		            m = buff_enq(client->rbuf, new_data, req_size);
                /* I've already read the req_header, so I need to update m->n field */
                m->n = sizeof(struct req_header);
		          }else if(client->state == CONN_READING_BODY) {
			          /* Now I've read all the request and I can pass it to RSC function */
                struct iovec *resp;
					      resp = rscs_manage_request(client->arch, read_data);
                /* If there is an error, I close the connection */
                if(resp == NULL) {
                  close_connection(pfdinfo, i);
                  deleted_entry = 1;
                  if(--nready < 0) break;
                  continue;
                }
		            buff_enq(client->wbuf, resp[0].iov_base, resp[0].iov_len);
                pfdinfo->pollfd[i].events |=  POLLOUT;
                client->state = CONN_SENDING_RESP;
                free(read_data);
              }
            } else {
	            /* type == EVENT_SUB */
				      if(client->state == CONN_READING_HDR) {
	              struct rsc_es_hdr *hdr;
	              int size;
                void *new_data;
                struct msg *m;
	              hdr = (struct rsc_es_hdr *)read_data;
	              size = rsc_es_msg_size(hdr->type);
	              if(size == -1) {
                  close_connection(pfdinfo, i);
                  deleted_entry = 1;
                  if(--nready < 0) break;
                  continue;
                }
                new_data = realloc(read_data, size);
                if(new_data == NULL) {
                  close_connection(pfdinfo, i);
                  deleted_entry = 1;
                  if(--nready < 0) break;
                  continue;
                }
                m = buff_enq(client->rbuf, new_data, size);
                m->n = sizeof(struct rsc_es_hdr);
                client->state = CONN_READING_BODY;
	            } else if(client->state == CONN_READING_BODY) {
	              struct rsc_es_ack *ack;
	              ack = rscs_es_manage_msg(client->fd, read_data);
                free(read_data);
			          /* I take the appropriate action based on ack->response field.
			           * If the response is ACK_FD_REG I've to insert the fd into the
			           * pollfd set. If the response is ACK_FD_DEREG_NOT_READY or ACK_FD_READY,
			           * I remove the fd from the pollfd. */
			          if(ack->response == ACK_FD_REG) {
				          struct client *c;
			            /* Into the client structure I insert the stream fd and not the 
			             * fd to subscribe, In this way I can know where to send data */
			            c = create_client(client->fd, SUBSCRIBED_FD, CONN_SENDING_RESP);
                  if(c == NULL) {
                    close_connection(pfdinfo, i);
                    deleted_entry = 1;
                    if(--nready < 0) break;
                    continue;
                  }
                  c->esfd_index = i;
			            pollfd_add(pfdinfo, ntohl(ack->fd), ntohl(ack->how), c);
			          } else if(ack->response == ACK_FD_DEREG_NOT_READY || ack->response == ACK_FD_DEREG_READY) {
			            int j;
			            for(j = 0; j < pfdinfo->size; j++) 
			              if( pfdinfo->pollfd[j].fd != -1 &&
			                  pfdinfo->clients[j] != NULL &&
			                  pfdinfo->clients[j]->type == SUBSCRIBED_FD &&
			                  pfdinfo->clients[j]->fd == client->fd && 
			                  pfdinfo->pollfd[j].fd == ntohl(ack->fd) && 
			                  pfdinfo->pollfd[j].events == ntohl(ack->how))
			                break;
			            if(j < pfdinfo->size)
			              pollfd_del(pfdinfo, j);
			          }
			          GDEBUG(1, "After rscem_manage_msg:");
			          PRINT_POLLFDINFO(pfdinfo);
	              /* Now I can send ack back */
                buff_enq(client->wbuf, ack, sizeof(struct rsc_es_ack));
                pfdinfo->pollfd[i].events |=  POLLOUT;
                /* It's not an error, I don't need to keep trace of the sending state */
                client->state = CONN_READING_HDR;
	            }
	          }
          }
          /***********************************************/
          /*  POLLOUT                                    */
          /***********************************************/
        } else if(pfdinfo->pollfd[i].revents & POLLOUT) {
	        void *buf;
	        int size, nwrite;
          /* If write buffer is empty, I remove the POLLOUT event and I continue */
          if(client->wbuf->first == NULL) {
            pfdinfo->pollfd[i].events &= (~POLLOUT);
            if(--nready <= 0) 
              break;
            continue;
          }
		      GDEBUG(1, "There are data ready do be written for fd %d", pfdinfo->pollfd[i].fd);
	        buf = client->wbuf->first->data + client->wbuf->first->n;
	        size = client->wbuf->first->tot - client->wbuf->first->n;
			    nwrite = write(client->fd, buf, size);
          if(nwrite < 0) {
            close_connection(pfdinfo, i);
            deleted_entry = 1;
            if(--nready < 0) break;
            continue;
          } else {
            client->wbuf->first->n += nwrite;
          }
			    if(client->wbuf->first->n == client->wbuf->first->tot) {
            /* I remove the message from the buffer and I free it */
            void *data = buff_deq(client->wbuf);
            free(data);
            /* If it's a request/response fd and I've sent an arch or response message,
             * I change my state to reading header */
	          if( pfdinfo->clients[i]->type == REQ_RESP && 
                ( client->state == SENDING_ARCH || client->state == CONN_SENDING_RESP) )
              client->state = CONN_READING_HDR;
	          /* if client->type is EVENT_SUB  there is nothing to do: I need only
            * to continue to send the buffered data */
          }
        }
        if(--nready <= 0) break;
      /*******************************************/
      /* An event subscribed fd is waken up      */
      /*******************************************/
      /* The event is occurred, I send back a response I didn't it before */
      }else if(pfdinfo->clients[i]->type == SUBSCRIBED_FD) {
        struct rsc_es_resp *resp;
        int esfd_index = pfdinfo->clients[i]->esfd_index;

        resp = rscs_es_event_occurred(pfdinfo->pollfd[esfd_index].fd, pfdinfo->pollfd[i].fd, pfdinfo->pollfd[i].revents);
        if(resp != NULL) {
          buff_enq(pfdinfo->clients[esfd_index]->wbuf, resp, sizeof(struct rsc_es_resp)); 
          pfdinfo->pollfd[esfd_index].events |=  POLLOUT;
        } 
	      if(--nready <= 0) break;
      }
    } /* for(i = 0; i < nready; i++) */
    /* If I've deleted a pfdinfo, I compact it */
    if(deleted_entry)
      pollfd_compact(pfdinfo);
  } /* while(1) */
}
Example #3
0
File: main.c Project: dsd/fprintd
static void pollfd_added_cb(int fd, short events)
{
	g_message("now monitoring fd %d", fd);
	pollfd_add(fd, events);
}
Example #4
0
void loop2(void)
{
    int             i, listenfd, clifd, nread;
    char            buf[MAXLENLINE];
    uid_t           uid;
    struct pollfd   *pollfd = NULL;
    int             numfd = 1;
    pollfd_wrap     *pfd_wrap;

    struct pollfd *default_pfd;
    default_pfd->fd = -1;
    default_pfd->events = POLLIN;
    default_pfd->events = 0;

    pfd_wrap->pfd   = default_pfd;
    pfd_wrap->maxfd = NALLOC;

    pollfd_init(pfd_wrap, default_pfd);

    pollfd = pfd_wrap->pfd;
    int maxfd = pfd_wrap->maxfd;

    if ((listenfd = serv_listen(CS_OPEN)) < 0)
    {
        //log_sys("serv_listen error");
    }

    client_add(listenfd, 0);
    pollfd[0].fd = listenfd;

    for (;;)
    {
        if (poll(pollfd, numfd, -1) < 0)
        {
            //log_sys("poll error");
        }

        if (pollfd[0].revents & POLLIN)
        {
            if ((clifd = serv_accept(listenfd, &uid)) < 0)
            {
                //log_sys("serv_accept error: %d", clifd);
            }
            client_add(clifd,uid);

            if (numfd == pfd_wrap->maxfd)
            {
                default_pfd->fd = -1;
                pollfd_alloc(pfd_wrap, default_pfd);
            }
            else
            {
                default_pfd->fd = clifd;
                pollfd_add(pfd_wrap, default_pfd);
            }
            pollfd = pfd_wrap->pfd;

            pollfd[numfd].fd = clifd;
            pollfd[numfd].events = POLLIN;
            pollfd[numfd].revents = 0;
            numfd++;
            //log_msg("new connection: uid %d, fd %d, uid, clifd");
        }

        for (i = 1; i < numfd; i++)
        {
            if (pollfd[i].revents & POLLHUP)
            {
                goto hungup;
            }
            else if(pollfd[i].revents & POLLIN)
            {
                if ((nread = read(pollfd[i].fd, buf, MAXLENLINE)) < 0)
                {
                    //log_sys("read error on fd %d",pollfd[i].fd);
                }
                else if(nread == 0)
                {
        hungup:
                    //log_msg("closed: fd %d", pollfd[i].fd);
                    client_del(pollfd[i].fd);
                    close(pollfd[i].fd);
                    //pack the pollfd
                    //TODO there is a drawback, if you allocate
                    //many pollfds, it cannot be released if you
                    //needn't them;
                    if (i < (numfd-1))
                    {
                        pollfd[i].fd = pollfd[numfd-1].fd;
                        pollfd[i].events = pollfd[numfd-1].events;
                        pollfd[i].revents = pollfd[numfd-1].revents;
                        i--;
                    }
                    numfd--;
                }
                else
                {
                    handle_request(buf, nread, pollfd[i].fd,client[i].uid);
                }
            }
        }
    }
}