Ejemplo n.º 1
0
static void *
ssdp_thread(void *aux)
{
  struct sockaddr_in si = {0};
  int fdm, fdu;
  int one = 1, r;
  int64_t next_send = 0;
  struct pollfd fds[2];
  socklen_t sl = sizeof(struct sockaddr_in);
  struct ip_mreq imr;

  fdm = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);

  setsockopt(fdm, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(int));
#if defined(SO_REUSEPORT)
  setsockopt(fdm, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(int));
#endif

#if defined(IP_RECVDSTADDR)
  setsockopt(fdm, IPPROTO_IP, IP_RECVDSTADDR, &one, sizeof(int));
#endif
  si.sin_family = AF_INET;
  si.sin_port = htons(1900);

  if(bind(fdm, (struct sockaddr *)&si, sizeof(struct sockaddr_in)) == -1) {
    TRACE(TRACE_ERROR, "SSDP", "Unable to bind -- %s", strerror(errno));
    return NULL;
  }

  memset(&imr, 0, sizeof(imr));
  imr.imr_multiaddr.s_addr = htonl(0xeffffffa); // 239.255.255.250
  if(setsockopt(fdm, IPPROTO_IP, IP_ADD_MEMBERSHIP, &imr, 
		sizeof(struct ip_mreq)) == -1) {
    TRACE(TRACE_ERROR, "SSDP", "Unable to join 239.255.255.250: %s",
	  strerror(errno));
    return NULL;
  }

  fdu = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);

#if defined(IP_RECVDSTADDR)
  setsockopt(fdu, IPPROTO_IP, IP_RECVDSTADDR, &one, sizeof(int));
#endif

  si.sin_family = AF_INET;
  si.sin_port = 0;

  if(bind(fdu, (struct sockaddr *)&si, sizeof(struct sockaddr_in)) == -1) {
    TRACE(TRACE_ERROR, "SSDP", "Unable to bind");
    return NULL;
  }

  if(getsockname(fdu, (struct sockaddr *)&ssdp_selfaddr, &sl) == -1) {
    TRACE(TRACE_ERROR, "SSDP", "Unable to figure local port");
    return NULL;
  }

  ssdp_fdm = fdm;
  ssdp_fdu = fdu;
  
  ssdp_send_static(fdu, SEARCHREQ);

  fds[0].fd = fdm;
  fds[0].events = POLLIN;
  fds[1].fd = fdu;
  fds[1].events = POLLIN;

  while(ssdp_run) {
    
    int64_t delta = next_send - showtime_get_ts();
    if(delta <= 0) {
      delta = 15000000LL;
      next_send = showtime_get_ts() + delta;
      ssdp_send_notify("ssdp:alive");
    }
    r = poll(fds, 2, (delta / 1000) + 1);
    if(r > 0 && fds[0].revents & POLLIN)
      ssdp_input(fdm, 1);
    if(r > 0 && fds[1].revents & POLLIN)
      ssdp_input(fdu, 0);
  }
  return NULL;
}
Ejemplo n.º 2
0
static int
ssdp_loop(int log_fail)
{
  struct sockaddr_in si = {0};
  int fdm, fdu;
  int one = 1, r;
  int64_t next_send = 0;
  struct pollfd fds[2];
  struct ip_mreq imr;

  fdm = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);

  setsockopt(fdm, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(int));
#if defined(SO_REUSEPORT)
  setsockopt(fdm, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(int));
#endif

#if defined(IP_RECVDSTADDR)
  setsockopt(fdm, IPPROTO_IP, IP_RECVDSTADDR, &one, sizeof(int));
#endif
  si.sin_family = AF_INET;
  si.sin_port = htons(1900);

  if(bind(fdm, (struct sockaddr *)&si, sizeof(struct sockaddr_in)) == -1) {
    if(log_fail)
      TRACE(TRACE_ERROR, "SSDP", "Unable to bind -- %s", strerror(errno));
    close(fdm);
    return 1;
  }

  memset(&imr, 0, sizeof(imr));
  imr.imr_multiaddr.s_addr = htonl(0xeffffffa); // 239.255.255.250
  if(setsockopt(fdm, IPPROTO_IP, IP_ADD_MEMBERSHIP, &imr, 
		sizeof(struct ip_mreq)) == -1) {
    if(log_fail)
      TRACE(TRACE_ERROR, "SSDP", "Unable to join 239.255.255.250: %s",
            strerror(errno));
    close(fdm);
    return 1;
  }

  fdu = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);

#if defined(IP_RECVDSTADDR)
  setsockopt(fdu, IPPROTO_IP, IP_RECVDSTADDR, &one, sizeof(int));
#endif

  si.sin_family = AF_INET;
  si.sin_port = 0;

  if(bind(fdu, (struct sockaddr *)&si, sizeof(struct sockaddr_in)) == -1) {
    if(log_fail)
      TRACE(TRACE_ERROR, "SSDP", "Unable to bind -- %s", strerror(errno));
    close(fdu);
    close(fdm);
    return 1;
  }

  ssdp_fdm = fdm;
  ssdp_fdu = fdu;
  
  ssdp_send_static(fdu, SEARCHREQ);

  fds[0].fd = fdm;
  fds[0].events = POLLIN;
  fds[1].fd = fdu;
  fds[1].events = POLLIN;

  TRACE(TRACE_DEBUG, "SSDP", "Running");

  while(ssdp_run) {
    
    int64_t delta = next_send - arch_get_ts();
    if(delta <= 0) {
      delta = 15000000LL;
      next_send = arch_get_ts() + delta;
      ssdp_send_notify("ssdp:alive");
    }
    r = poll(fds, 2, (delta / 1000) + 1);
    if(r > 0 && fds[0].revents & POLLIN)
      ssdp_input(fdm, 1);
    if(r > 0 && fds[1].revents & POLLIN)
      ssdp_input(fdu, 0);
  }
  return 0;
}