예제 #1
0
int krad_app_client_send_fd (krad_app_client_t *client, int fd) {

  krad_system_set_socket_blocking (client->sd);

  char buf[1];
  struct iovec iov;
  struct msghdr msg;
  struct cmsghdr *cmsg;
  int n;
  char cms[CMSG_SPACE(sizeof(int))];

  buf[0] = 0;
  iov.iov_base = buf;
  iov.iov_len = 1;

  memset(&msg, 0, sizeof msg);
  msg.msg_iov = &iov;
  msg.msg_iovlen = 1;
  msg.msg_control = (caddr_t)cms;
  msg.msg_controllen = CMSG_LEN(sizeof(int));

  cmsg = CMSG_FIRSTHDR(&msg);
  cmsg->cmsg_len = CMSG_LEN(sizeof(int));
  cmsg->cmsg_level = SOL_SOCKET;
  cmsg->cmsg_type = SCM_RIGHTS;
  memmove(CMSG_DATA(cmsg), &fd, sizeof(int));

  if ((n=sendmsg(client->sd, &msg, 0)) != iov.iov_len) {
    krad_system_set_socket_nonblocking (client->sd);
    return 0;
  }
  return 1;
}
예제 #2
0
int krad_transmitter_listen_on (krad_transmitter_t *krad_transmitter, uint16_t port) {

    int ret;
    int r;
    int on;

    on = 1;
    r = 0;
    ret = 0;

    if (krad_transmitter->listening == 1) {
        krad_transmitter_stop_listening (krad_transmitter);
    }

    if (port == 0) {
        return -1;
    }

    krad_transmitter->port = port;
    krad_transmitter->listening = 1;

    krad_transmitter->local_address.sin_family = AF_INET;
    krad_transmitter->local_address.sin_port = htons (krad_transmitter->port);
    krad_transmitter->local_address.sin_addr.s_addr = htonl (INADDR_ANY);

    if ((krad_transmitter->incoming_connections_sd = socket (AF_INET, SOCK_STREAM, 0)) < 0) {
        printke ("Krad Transmitter: system call socket error");
        krad_transmitter->listening = 0;
        krad_transmitter->port = 0;
        return -1;
    }

    if ((setsockopt (krad_transmitter->incoming_connections_sd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on))) < 0) {
        printke ("Krad Transmitter: Could not setsockopt SO_REUSEADDR");
    }

    if (bind (krad_transmitter->incoming_connections_sd, (struct sockaddr *)&krad_transmitter->local_address,
              sizeof(krad_transmitter->local_address)) == -1) {

        krad_transmitter->listening = 0;
        krad_transmitter->port = 0;
        close (krad_transmitter->incoming_connections_sd);
        printke ("Krad Transmitter: bind error for tcp port %d", krad_transmitter->port);
        return -1;
    }

    printk ("Krad Transmitter: Listening on port %d", krad_transmitter->port);

    if (listen (krad_transmitter->incoming_connections_sd, SOMAXCONN) < 0) {
        printke ("Krad Transmitter: system call listen error");
        krad_transmitter->listening = 0;
        krad_transmitter->port = 0;
        close (krad_transmitter->incoming_connections_sd);
        return -1;
    }

    krad_system_set_socket_nonblocking (krad_transmitter->incoming_connections_sd);

    krad_transmitter->incoming_connections_efd = epoll_create (0);

    if (krad_transmitter->incoming_connections_efd == -1) {
        krad_transmitter->listening = 0;
        krad_transmitter->port = 0;
        close (krad_transmitter->incoming_connections_sd);
        close (krad_transmitter->incoming_connections_efd);
        printke ("Krad Transmitter: epoll_create");
        return -1;
    }

    krad_transmitter->event.data.fd = krad_transmitter->incoming_connections_sd;
    krad_transmitter->event.events = EPOLLIN | EPOLLET;

    ret = epoll_ctl (krad_transmitter->incoming_connections_efd, EPOLL_CTL_ADD,
                     krad_transmitter->incoming_connections_sd, &krad_transmitter->event);
    if (ret == -1) {
        printke ("Krad Transmitter: epoll_ctl");
        krad_transmitter->listening = 0;
        krad_transmitter->port = 0;
        close (krad_transmitter->incoming_connections_sd);
        close (krad_transmitter->incoming_connections_efd);
        return -1;
    }

    krad_transmitter->incoming_connection_events = calloc (KRAD_TRANSMITTER_MAXEVENTS, sizeof (struct epoll_event));

    if (krad_transmitter->incoming_connection_events == NULL) {
        krad_transmitter->listening = 0;
        krad_transmitter->port = 0;
        close (krad_transmitter->incoming_connections_sd);
        close (krad_transmitter->incoming_connections_efd);
        printke ("Krad Transmitter: Out of memory!");
        return -1;
    }

    krad_transmitter->krad_transmission_receivers = calloc (TOTAL_RECEIVERS, sizeof (krad_transmission_receiver_t));

    if (krad_transmitter->krad_transmission_receivers == NULL) {
        free (krad_transmitter->incoming_connection_events);
        krad_transmitter->listening = 0;
        krad_transmitter->port = 0;
        close (krad_transmitter->incoming_connections_sd);
        close (krad_transmitter->incoming_connections_efd);
        printke ("Krad Transmitter: Out of memory!");
        return -1;
    }

    for (r = 0; r < TOTAL_RECEIVERS; r++) {
        krad_transmitter->krad_transmission_receivers[r].krad_transmitter = krad_transmitter;
    }

    pthread_create (&krad_transmitter->listening_thread, NULL, krad_transmitter_listening_thread, (void *)krad_transmitter);

    return 0;

}
예제 #3
0
void *krad_transmitter_listening_thread (void *arg) {

    krad_transmitter_t *krad_transmitter = (krad_transmitter_t *)arg;

    krad_system_set_thread_name ("kr_tx_listen");

    krad_transmission_receiver_t *krad_transmission_receiver;

    int e;
    int ret;
    int eret;
    int cret;
    int addr_size;
    int client_fd;
    struct sockaddr_in remote_address;

    char hbuf[NI_MAXHOST];
    char sbuf[NI_MAXSERV];

    printk ("Krad Transmitter: Listening thread starting");

    addr_size = 0;
    e = 0;
    ret = 0;
    eret = 0;
    cret = 0;
    krad_transmission_receiver = NULL;
    memset (&remote_address, 0, sizeof(remote_address));

    addr_size = sizeof (remote_address);

    while (krad_transmitter->stop_listening == 0) {

        ret = epoll_wait (krad_transmitter->incoming_connections_efd, krad_transmitter->incoming_connection_events, KRAD_TRANSMITTER_MAXEVENTS, 50);

        if (ret < 0) {
            if ((ret < 0) && (errno == EINTR)) {
                continue;
            }
            printke ("Krad Transmitter: Failed on epoll wait %s", strerror(errno));
            krad_transmitter->stop_listening = 1;
            break;
        }

        if (ret > 0) {

            for (e = 0; e < ret; e++) {

                if ((krad_transmitter->incoming_connection_events[e].events & EPOLLERR) ||
                        (krad_transmitter->incoming_connection_events[e].events & EPOLLHUP))
                {

                    if (krad_transmitter->incoming_connections_sd == krad_transmitter->incoming_connection_events[e].data.fd) {
                        failfast ("Krad Transmitter: error on listen socket");
                    } else {

                        if (krad_transmitter->incoming_connection_events[e].events & EPOLLHUP) {
                            printke ("Krad Transmitter: incoming transmitter connection hangup");
                        }
                        if (krad_transmitter->incoming_connection_events[e].events & EPOLLERR) {
                            printke ("Krad Transmitter: incoming transmitter connection error");
                        }
                        krad_transmitter_receiver_destroy (krad_transmitter->incoming_connection_events[e].data.ptr);
                        continue;
                    }

                }

                if (krad_transmitter->incoming_connections_sd == krad_transmitter->incoming_connection_events[e].data.fd) {

                    while (1) {

                        client_fd = accept (krad_transmitter->incoming_connections_sd, (struct sockaddr *)&remote_address, (socklen_t *)&addr_size);
                        if (client_fd == -1) {
                            if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) {
                                // We have processed all incoming connections.
                                break;
                            } else {
                                failfast ("Krad Transmitter: error on listen socket accept");
                            }
                        }

                        if (getnameinfo ((struct sockaddr *)&remote_address, addr_size, hbuf, sizeof hbuf, sbuf, sizeof sbuf, NI_NUMERICHOST | NI_NUMERICSERV) == 0) {
                            printk ("Krad Transmitter: Accepted transmitter connection on descriptor %d (host=%s, port=%s)", client_fd, hbuf, sbuf);
                        } else {
                            printke ("Krad Transmitter: Accepted transmitter connection on descriptor %d ... but could not getnameinfo()?", client_fd, hbuf, sbuf);
                        }

                        krad_system_set_socket_nonblocking (client_fd);

                        krad_transmission_receiver = krad_transmitter_receiver_create (krad_transmitter, client_fd);

                        if (krad_transmission_receiver == NULL) {
                            failfast ("Krad Transmitter: ran out of connections!");
                        }

                        eret = epoll_ctl (krad_transmitter->incoming_connections_efd, EPOLL_CTL_ADD, client_fd, &krad_transmission_receiver->event);
                        if (eret != 0) {
                            failfast ("Krad Transmitter: incoming transmitter connection epoll error eret is %d errno is %i", eret, errno);
                        }
                    }

                    continue;
                }

                if (krad_transmitter->incoming_connection_events[e].events & EPOLLIN) {

                    while (1) {
                        krad_transmission_receiver = (krad_transmission_receiver_t *)krad_transmitter->incoming_connection_events[e].data.ptr;

                        cret = read (krad_transmission_receiver->fd,
                                     krad_transmission_receiver->buffer + krad_transmission_receiver->position,
                                     sizeof (krad_transmission_receiver->buffer) -  krad_transmission_receiver->position);
                        if (cret == -1) {
                            if (errno != EAGAIN) {
                                printke ("Krad Transmitter: error reading from a new incoming connection socket");
                                krad_transmitter_receiver_destroy (krad_transmitter->incoming_connection_events[e].data.ptr);
                            }
                            break;
                        }

                        if (cret == 0) {
                            printk ("Krad Transmitter: Client EOF Closed connection");
                            krad_transmitter_receiver_destroy (krad_transmitter->incoming_connection_events[e].data.ptr);
                            break;
                        }

                        if (cret > 0) {
                            krad_transmission_receiver->position += cret;
                            krad_transmitter_handle_incoming_connection (krad_transmitter, krad_transmission_receiver);
                            break;
                        }
                    }
                }
            }
        }

        if (ret == 0) {
            //printk ("Krad Transmitter: Listening thread... nothing happened");
        }
    }

    close (krad_transmitter->incoming_connections_efd);
    close (krad_transmitter->incoming_connections_sd);
    free (krad_transmitter->incoming_connection_events);

    krad_transmitter->port = 0;
    krad_transmitter->listening = 0;

    printk ("Krad Transmitter: Listening thread exiting");

    return NULL;

}
예제 #4
0
static int krad_app_client_init (krad_app_client_t *client, int timeout_ms) {

  int rc;
  char port_string[6];
  struct sockaddr_un unix_saddr;
  struct in6_addr serveraddr;
  struct addrinfo hints;
  struct addrinfo *res;

  res = NULL;

  //FIXME make connect nonblocking  
  

  if (client->tcp_port != 0) {

    //FIXME hrm we don't know the sysname of a remote connect! crazy ?
    //printf ("Krad APP Client: Connecting to remote %s:%d", client->host, client->tcp_port);

    memset(&hints, 0x00, sizeof(hints));
    hints.ai_flags = AI_NUMERICSERV;
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;

    rc = inet_pton (AF_INET, client->host, &serveraddr);
    if (rc == 1) {
      hints.ai_family = AF_INET;
      hints.ai_flags |= AI_NUMERICHOST;
    } else {
      rc = inet_pton (AF_INET6, client->host, &serveraddr);
      if (rc == 1) {
        hints.ai_family = AF_INET6;
        hints.ai_flags |= AI_NUMERICHOST;
      }
    }

    snprintf (port_string, 6, "%d", client->tcp_port);

    rc = getaddrinfo (client->host, port_string, &hints, &res);
    if (rc != 0) {
       printf ("Krad APP Client: Host not found --> %s\n", gai_strerror(rc));
       return 0;
    }
    
    client->sd = socket (res->ai_family, res->ai_socktype, res->ai_protocol);
    if (client->sd < 0) {
      printf ("Krad APP Client: Socket Error");
      if (res != NULL) {
        freeaddrinfo (res);
        res = NULL;
      }
      return 0;
    }

    rc = connect (client->sd, res->ai_addr, res->ai_addrlen);
    if (rc < 0) {
      printf ("Krad APP Client: Remote Connect Error\n");
      if (res != NULL) {
        freeaddrinfo (res);
        res = NULL;
      }
      return 0;
    }

    if (res != NULL) {
      freeaddrinfo (res);
      res = NULL;
    }

  } else {

    client->sd = socket (AF_UNIX, SOCK_STREAM, 0);
    if (client->sd == -1) {
      failfast ("Krad APP Client: socket fail");
      return 0;
    }

    memset(&unix_saddr, 0x00, sizeof(unix_saddr));
    unix_saddr.sun_family = AF_UNIX;
    snprintf (unix_saddr.sun_path, sizeof(unix_saddr.sun_path), "%s", client->api_path);
    if (client->on_linux) {
      unix_saddr.sun_path[0] = '\0';
    }

    if (connect (client->sd, (struct sockaddr *) &unix_saddr, sizeof (unix_saddr)) == -1) {
      close (client->sd);
      client->sd = 0;
      printke ("Krad APP Client: Can't connect to socket %s", client->api_path);
      return 0;
    }
  }
  
  krad_system_set_socket_nonblocking (client->sd);

  return client->sd;
}