Exemplo n.º 1
0
static int http_server(void)
{
    int server_fd = 0;
	int ctrl_fd = 0, ctrl_fd2 = 0;
    int ret, delay;
    struct pollfd *poll_table, *poll_entry;
    HTTPContext *c, *c_next;
    if(!(poll_table = av_mallocz_array(nb_max_http_connections + 1, sizeof(*poll_table)))) {
        http_log("Impossible to allocate a poll table handling %d connections.\n", nb_max_http_connections);
        return -1;
    }

	#if defined(PLUGIN_DVB)
	ctrl_fd = ff_ctl_open(1234);
    if (ctrl_fd < 0) {
        av_free(poll_table);
        return -1;
    }
	#endif
	
    if (my_http_addr.sin_port) {
        server_fd = socket_open_listen(&my_http_addr);
        if (server_fd < 0) {
            av_free(poll_table);
            return -1;
        }
    }

    if ( !server_fd) {
        http_log("HTTP disabled.\n");
        av_free(poll_table);
        return -1;
    }
	
	#if defined(PLUGIN_SSDP)
	ssdp_fd = mcast_open(ssdp_ip, ssdp_port);
	if(ssdp_fd <= 0){
		http_log("ssdp disabled\n");
	}
	ssdp_notify(ssdp_fd, ssdp_ip, ssdp_port, "ssdp:alive");
	#endif
	
    http_log("FFserver started.\n");

    for(;;) {
        poll_entry = poll_table;
		
		#if defined(PLUGIN_DVB)
		if(ctrl_fd){
			poll_entry->fd = ctrl_fd;
            poll_entry->events = POLLIN;
            poll_entry++;
		}
		if(ctrl_fd2){
			poll_entry->fd = ctrl_fd2;
			poll_entry->events = POLLIN;
			if(ctl_msg_pending() > 0){
				poll_entry->events |= POLLOUT;
			}
            poll_entry++;
		}
		#endif
		
        if (server_fd) {
            poll_entry->fd = server_fd;
            poll_entry->events = POLLIN;
            poll_entry++;
        }
		
		#if defined(PLUGIN_SSDP)
		if(ssdp_fd){
			poll_entry->fd = ssdp_fd;
            poll_entry->events = POLLIN;
            poll_entry++;
		}
		#endif

        /* wait for events on each HTTP handle */
        c = first_http_ctx;
        delay = 1500;
        while (c != NULL) {
            int fd;
            fd = c->fd;
            switch(c->state) {
            case HTTPSTATE_SEND_HEADER:
                c->poll_entry = poll_entry;
                poll_entry->fd = fd;
                poll_entry->events = POLLOUT;
                poll_entry++;
                break;
            case HTTPSTATE_SEND_DATA_HEADER:
            case HTTPSTATE_SEND_DATA:
            case HTTPSTATE_SEND_DATA_TRAILER:
                /*for TCP, we output as much as we can*/
                c->poll_entry = poll_entry;
                poll_entry->fd = fd;
                poll_entry->events = POLLOUT;
                poll_entry++;
                break;
            case HTTPSTATE_WAIT_REQUEST:
            case HTTPSTATE_RECEIVE_DATA:
            case HTTPSTATE_WAIT_FEED:
                /* need to catch errors */
                c->poll_entry = poll_entry;
                poll_entry->fd = fd;
                poll_entry->events = POLLIN;/* Maybe this will work */
                poll_entry++;
                break;
            default:
                c->poll_entry = NULL;
                break;
            }
            c = c->next;
        }

        /* wait for an event on one connection. We poll at least every second to handle timeouts */
        do {
            ret = poll(poll_table, poll_entry - poll_table, delay);
            if (ret < 0 && ff_neterrno() != AVERROR(EAGAIN) &&
                ff_neterrno() != AVERROR(EINTR)) {
                av_free(poll_table);
                return -1;
            }
        } while (ret < 0);

        cur_time = av_gettime() / 1000;

        /* now handle the events */
        for(c = first_http_ctx; c != NULL; c = c_next) {
            c_next = c->next;
            if (handle_connection(c) < 0) {
                log_connection(c);
                close_connection(c);
            }
        }

        poll_entry = poll_table;

		#if defined(PLUGIN_DVB)
		if(ctrl_fd){
			if(poll_entry->revents & POLLIN){
				ctrl_fd2 = ctl_msg_open(ctrl_fd);
			}
			poll_entry++;
		}
		if(ctrl_fd2 && poll_entry->fd == ctrl_fd2){
			if(poll_entry->revents & POLLIN){
				ctl_msg_recv();
				ff_ctl_recv(ctl_msg_cb);
			}else if(poll_entry->revents & POLLOUT){
				ctl_msg_send();
			}
			poll_entry++;
		}
		#endif
		if(poll_entry->fd != server_fd){
			printf("bad  entry\n");
		}
		
        if (server_fd) {
            if (poll_entry->revents & POLLIN)
                new_connection(server_fd, 0);
            poll_entry++;
        }
		
		#if defined(PLUGIN_SSDP)
		if (ssdp_fd) {
            if (poll_entry->revents & POLLIN)
                ssdp_response(ssdp_fd);
            poll_entry++;
        }
		#endif
	
    }
}
Exemplo n.º 2
0
/**
 * mc is set if packet arrived on our multicast listening socket
 */
static void
ssdp_input(int fd, int mc)
{
  char buf[2000];
  int r, cmd, self;
  struct http_header_list args;
  uint32_t myaddr;
  const char *usn;
  struct sockaddr_in si;

#if defined(IP_RECVDSTADDR)

  struct msghdr msg;
  struct cmsghdr *cmsg;
  struct iovec iov;
  char ctrl[500];

  iov.iov_base = buf;
  iov.iov_len = sizeof(buf);

  msg.msg_name = (struct sockaddr *)&si;
  msg.msg_namelen = sizeof(struct sockaddr_in);

  msg.msg_iov = &iov;
  msg.msg_iovlen = 1;

  msg.msg_control = ctrl;
  msg.msg_controllen = sizeof(ctrl);

  r = recvmsg(fd, &msg, 0);
  if(r < 1)
    return;

  buf[r] = 0;

  myaddr = 0;

  for(cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg,cmsg)) {
    if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_RECVDSTADDR) {
      struct in_addr *ia = (struct in_addr *)CMSG_DATA(cmsg);
      myaddr = ntohl(ia->s_addr);
      break;
    }
  }

#else
 
  socklen_t slen = sizeof(struct sockaddr_in);
  netif_t *ni;

  r = recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr *)&si, &slen);
  if(r < 1)
    return;
  buf[r] = 0;

  ni = net_get_interfaces();
  myaddr = ni ? ni[0].ipv4 : 0;
  free(ni);

#endif

  if(!myaddr)
    return;

  LIST_INIT(&args);

  cmd = ssdp_parse(buf, &args);
  usn = http_header_get(&args, "usn");

  self = usn != NULL && !strncmp(usn, "uuid:", 5) &&
    !strncmp(usn + 5, ssdp_uuid, strlen(ssdp_uuid));

  if(!self) {
    if(cmd == SSDP_NOTIFY && mc)
      ssdp_recv_notify(&args);
    if(cmd == SSDP_RESPONSE && !mc)
      ssdp_response(&args);
    if(cmd == SSDP_SEARCH && mc)
      ssdp_send_all(ssdp_fdu, myaddr, &si, NULL);
  }
  http_headers_free(&args);
}