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; }
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; }
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; }
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; }