|
Packit Service |
3975d1 |
// Copyright(c) 2018-2020, Intel Corporation
|
|
Packit Service |
3975d1 |
//
|
|
Packit Service |
3975d1 |
// Redistribution and use in source and binary forms, with or without
|
|
Packit Service |
3975d1 |
// modification, are permitted provided that the following conditions are met:
|
|
Packit Service |
3975d1 |
//
|
|
Packit Service |
3975d1 |
// * Redistributions of source code must retain the above copyright notice,
|
|
Packit Service |
3975d1 |
// this list of conditions and the following disclaimer.
|
|
Packit Service |
3975d1 |
// * Redistributions in binary form must reproduce the above copyright notice,
|
|
Packit Service |
3975d1 |
// this list of conditions and the following disclaimer in the documentation
|
|
Packit Service |
3975d1 |
// and/or other materials provided with the distribution.
|
|
Packit Service |
3975d1 |
// * Neither the name of Intel Corporation nor the names of its contributors
|
|
Packit Service |
3975d1 |
// may be used to endorse or promote products derived from this software
|
|
Packit Service |
3975d1 |
// without specific prior written permission.
|
|
Packit Service |
3975d1 |
//
|
|
Packit Service |
3975d1 |
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
Packit Service |
3975d1 |
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
Packit Service |
3975d1 |
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
Packit Service |
3975d1 |
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
Packit Service |
3975d1 |
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
Packit Service |
3975d1 |
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
Packit Service |
3975d1 |
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
Packit Service |
3975d1 |
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
Packit Service |
3975d1 |
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
Packit Service |
3975d1 |
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
Packit Service |
3975d1 |
// POSSIBILITY OF SUCH DAMAGE.
|
|
Packit Service |
3975d1 |
|
|
Packit Service |
3975d1 |
#ifdef HAVE_CONFIG_H
|
|
Packit Service |
3975d1 |
#include <config.h>
|
|
Packit Service |
3975d1 |
#endif // HAVE_CONFIG_H
|
|
Packit Service |
3975d1 |
|
|
Packit Service |
3975d1 |
#ifndef _GNU_SOURCE
|
|
Packit Service |
3975d1 |
#define _GNU_SOURCE
|
|
Packit Service |
3975d1 |
#endif
|
|
Packit Service |
3975d1 |
#ifndef __USE_GNU
|
|
Packit Service |
3975d1 |
#define __USE_GNU
|
|
Packit Service |
3975d1 |
#endif
|
|
Packit Service |
3975d1 |
|
|
Packit Service |
3975d1 |
#include <sys/socket.h>
|
|
Packit Service |
3975d1 |
#include <sys/un.h>
|
|
Packit Service |
3975d1 |
#include <poll.h>
|
|
Packit Service |
3975d1 |
#include <inttypes.h>
|
|
Packit Service |
3975d1 |
#include "events_api_thread.h"
|
|
Packit Service |
3975d1 |
#include "api/opae_events_api.h"
|
|
Packit Service |
3975d1 |
|
|
Packit Service |
3975d1 |
#ifdef LOG
|
|
Packit Service |
3975d1 |
#undef LOG
|
|
Packit Service |
3975d1 |
#endif
|
|
Packit Service |
3975d1 |
#define LOG(format, ...) \
|
|
Packit Service |
3975d1 |
log_printf("events_api_thread: " format, ##__VA_ARGS__)
|
|
Packit Service |
3975d1 |
|
|
Packit Service |
3975d1 |
events_api_thread_config events_api_config = {
|
|
Packit Service |
3975d1 |
.global = &global_config,
|
|
Packit Service |
3975d1 |
.sched_policy = SCHED_RR,
|
|
Packit Service |
3975d1 |
.sched_priority = 10,
|
|
Packit Service |
3975d1 |
};
|
|
Packit Service |
3975d1 |
|
|
Packit Service |
3975d1 |
#define MAX_CLIENT_CONNECTIONS 1023
|
|
Packit Service |
3975d1 |
#define SRV_SOCKET 0
|
|
Packit Service |
3975d1 |
#define FIRST_CLIENT_SOCKET 1
|
|
Packit Service |
3975d1 |
|
|
Packit Service |
3975d1 |
/* array keeping track of all connection file descriptors (plus server socket) */
|
|
Packit Service |
3975d1 |
STATIC struct pollfd pollfds[MAX_CLIENT_CONNECTIONS+1];
|
|
Packit Service |
3975d1 |
STATIC nfds_t num_fds = 1;
|
|
Packit Service |
3975d1 |
|
|
Packit Service |
3975d1 |
STATIC void remove_client(int conn_socket)
|
|
Packit Service |
3975d1 |
{
|
|
Packit Service |
3975d1 |
nfds_t i, j;
|
|
Packit Service |
3975d1 |
nfds_t removed = 0;
|
|
Packit Service |
3975d1 |
|
|
Packit Service |
3975d1 |
opae_api_unregister_all_events_for(conn_socket);
|
|
Packit Service |
3975d1 |
LOG("closing connection conn_socket=%d.\n", conn_socket);
|
|
Packit Service |
3975d1 |
close(conn_socket);
|
|
Packit Service |
3975d1 |
|
|
Packit Service |
3975d1 |
for (i = j = FIRST_CLIENT_SOCKET ; i < num_fds ; ++i) {
|
|
Packit Service |
3975d1 |
if (conn_socket != pollfds[i].fd) {
|
|
Packit Service |
3975d1 |
if (j != i)
|
|
Packit Service |
3975d1 |
pollfds[j] = pollfds[i];
|
|
Packit Service |
3975d1 |
++j;
|
|
Packit Service |
3975d1 |
} else {
|
|
Packit Service |
3975d1 |
++removed;
|
|
Packit Service |
3975d1 |
}
|
|
Packit Service |
3975d1 |
}
|
|
Packit Service |
3975d1 |
|
|
Packit Service |
3975d1 |
num_fds -= removed;
|
|
Packit Service |
3975d1 |
}
|
|
Packit Service |
3975d1 |
|
|
Packit Service |
3975d1 |
STATIC int handle_message(int conn_socket)
|
|
Packit Service |
3975d1 |
{
|
|
Packit Service |
3975d1 |
struct msghdr mh;
|
|
Packit Service |
3975d1 |
struct cmsghdr *cmh;
|
|
Packit Service |
3975d1 |
struct iovec iov[1];
|
|
Packit Service |
3975d1 |
struct event_request req;
|
|
Packit Service |
3975d1 |
char buf[CMSG_SPACE(sizeof(int))];
|
|
Packit Service |
3975d1 |
ssize_t n;
|
|
Packit Service |
3975d1 |
int *fd_ptr;
|
|
Packit Service |
3975d1 |
|
|
Packit Service |
3975d1 |
/* set up ancillary data message header */
|
|
Packit Service |
3975d1 |
iov[0].iov_base = &req;
|
|
Packit Service |
3975d1 |
iov[0].iov_len = sizeof(req);
|
|
Packit Service |
3975d1 |
memset(buf, 0, sizeof(buf));
|
|
Packit Service |
3975d1 |
mh.msg_name = NULL;
|
|
Packit Service |
3975d1 |
mh.msg_namelen = 0;
|
|
Packit Service |
3975d1 |
mh.msg_iov = iov;
|
|
Packit Service |
3975d1 |
mh.msg_iovlen = sizeof(iov) / sizeof(iov[0]);
|
|
Packit Service |
3975d1 |
mh.msg_control = buf;
|
|
Packit Service |
3975d1 |
mh.msg_controllen = CMSG_LEN(sizeof(int));
|
|
Packit Service |
3975d1 |
mh.msg_flags = 0;
|
|
Packit Service |
3975d1 |
cmh = CMSG_FIRSTHDR(&mh);
|
|
Packit Service |
3975d1 |
cmh->cmsg_len = CMSG_LEN(sizeof(int));
|
|
Packit Service |
3975d1 |
cmh->cmsg_level = SOL_SOCKET;
|
|
Packit Service |
3975d1 |
cmh->cmsg_type = SCM_RIGHTS;
|
|
Packit Service |
3975d1 |
|
|
Packit Service |
3975d1 |
n = recvmsg(conn_socket, &mh, 0);
|
|
Packit Service |
3975d1 |
if (n < 0) {
|
|
Packit Service |
3975d1 |
LOG("recvmsg() failed: %s\n", strerror(errno));
|
|
Packit Service |
3975d1 |
return (int)n;
|
|
Packit Service |
3975d1 |
}
|
|
Packit Service |
3975d1 |
|
|
Packit Service |
3975d1 |
if (!n) { // socket closed by peer
|
|
Packit Service |
3975d1 |
remove_client(conn_socket);
|
|
Packit Service |
3975d1 |
return (int)n;
|
|
Packit Service |
3975d1 |
}
|
|
Packit Service |
3975d1 |
|
|
Packit Service |
3975d1 |
switch (req.type) {
|
|
Packit Service |
3975d1 |
|
|
Packit Service |
3975d1 |
case REGISTER_EVENT:
|
|
Packit Service |
3975d1 |
fd_ptr = (int *)CMSG_DATA(cmh);
|
|
Packit Service |
3975d1 |
|
|
Packit Service |
3975d1 |
if (opae_api_register_event(conn_socket, *fd_ptr,
|
|
Packit Service |
3975d1 |
req.event, req.object_id)) {
|
|
Packit Service |
3975d1 |
LOG("failed to register event\n");
|
|
Packit Service |
3975d1 |
return -1;
|
|
Packit Service |
3975d1 |
}
|
|
Packit Service |
3975d1 |
|
|
Packit Service |
3975d1 |
LOG("registered event sock=%d:fd=%d"
|
|
Packit Service |
3975d1 |
"(event=%d object_id=0x%" PRIx64 ")\n",
|
|
Packit Service |
3975d1 |
conn_socket, *fd_ptr, req.event, req.object_id);
|
|
Packit Service |
3975d1 |
|
|
Packit Service |
3975d1 |
break;
|
|
Packit Service |
3975d1 |
|
|
Packit Service |
3975d1 |
case UNREGISTER_EVENT:
|
|
Packit Service |
3975d1 |
|
|
Packit Service |
3975d1 |
if (opae_api_unregister_event(conn_socket,
|
|
Packit Service |
3975d1 |
req.event,
|
|
Packit Service |
3975d1 |
req.object_id)) {
|
|
Packit Service |
3975d1 |
LOG("failed to unregister event\n");
|
|
Packit Service |
3975d1 |
return -1;
|
|
Packit Service |
3975d1 |
}
|
|
Packit Service |
3975d1 |
|
|
Packit Service |
3975d1 |
LOG("unregistered event sock=%d:"
|
|
Packit Service |
3975d1 |
"(event=%d object_id=0x%" PRIx64 ")\n",
|
|
Packit Service |
3975d1 |
conn_socket, req.event, req.object_id);
|
|
Packit Service |
3975d1 |
|
|
Packit Service |
3975d1 |
break;
|
|
Packit Service |
3975d1 |
|
|
Packit Service |
3975d1 |
default:
|
|
Packit Service |
3975d1 |
LOG("unknown request type %d\n", req.type);
|
|
Packit Service |
3975d1 |
return -1;
|
|
Packit Service |
3975d1 |
}
|
|
Packit Service |
3975d1 |
|
|
Packit Service |
3975d1 |
return 0;
|
|
Packit Service |
3975d1 |
}
|
|
Packit Service |
3975d1 |
|
|
Packit Service |
3975d1 |
STATIC volatile bool evt_api_is_ready = false;
|
|
Packit Service |
3975d1 |
|
|
Packit Service |
3975d1 |
bool events_api_is_ready(void)
|
|
Packit Service |
3975d1 |
{
|
|
Packit Service |
3975d1 |
return evt_api_is_ready;
|
|
Packit Service |
3975d1 |
}
|
|
Packit Service |
3975d1 |
|
|
Packit Service |
3975d1 |
void *events_api_thread(void *thread_context)
|
|
Packit Service |
3975d1 |
{
|
|
Packit Service |
3975d1 |
events_api_thread_config *c =
|
|
Packit Service |
3975d1 |
(events_api_thread_config *)thread_context;
|
|
Packit Service |
3975d1 |
struct sched_param sched_param;
|
|
Packit Service |
3975d1 |
int policy = 0;
|
|
Packit Service |
3975d1 |
int res;
|
|
Packit Service |
3975d1 |
|
|
Packit Service |
3975d1 |
nfds_t i;
|
|
Packit Service |
3975d1 |
struct sockaddr_un addr;
|
|
Packit Service |
3975d1 |
int server_socket;
|
|
Packit Service |
3975d1 |
int conn_socket;
|
|
Packit Service |
3975d1 |
size_t len;
|
|
Packit Service |
3975d1 |
|
|
Packit Service |
3975d1 |
LOG("starting\n");
|
|
Packit Service |
3975d1 |
|
|
Packit Service |
3975d1 |
res = pthread_getschedparam(pthread_self(), &policy, &sched_param);
|
|
Packit Service |
3975d1 |
if (res) {
|
|
Packit Service |
3975d1 |
LOG("error getting scheduler params: %s\n", strerror(res));
|
|
Packit Service |
3975d1 |
} else {
|
|
Packit Service |
3975d1 |
policy = c->sched_policy;
|
|
Packit Service |
3975d1 |
sched_param.sched_priority = c->sched_priority;
|
|
Packit Service |
3975d1 |
|
|
Packit Service |
3975d1 |
res = pthread_setschedparam(pthread_self(),
|
|
Packit Service |
3975d1 |
policy,
|
|
Packit Service |
3975d1 |
&sched_param);
|
|
Packit Service |
3975d1 |
if (res) {
|
|
Packit Service |
3975d1 |
LOG("error setting scheduler params"
|
|
Packit Service |
3975d1 |
" (got root?): %s\n", strerror(res));
|
|
Packit Service |
3975d1 |
}
|
|
Packit Service |
3975d1 |
}
|
|
Packit Service |
3975d1 |
|
|
Packit Service |
3975d1 |
unlink(c->global->api_socket);
|
|
Packit Service |
3975d1 |
|
|
Packit Service |
3975d1 |
server_socket = socket(AF_UNIX, SOCK_STREAM, 0);
|
|
Packit Service |
3975d1 |
if (server_socket < 0) {
|
|
Packit Service |
3975d1 |
LOG("failed to create server socket.\n");
|
|
Packit Service |
3975d1 |
goto out_exit;
|
|
Packit Service |
3975d1 |
}
|
|
Packit Service |
3975d1 |
LOG("created server socket.\n");
|
|
Packit Service |
3975d1 |
|
|
Packit Service |
3975d1 |
addr.sun_family = AF_UNIX;
|
|
Packit Service |
3975d1 |
|
|
Packit Service |
3975d1 |
len = strnlen(c->global->api_socket, sizeof(addr.sun_path) - 1);
|
|
Packit Service |
3975d1 |
memcpy(addr.sun_path, c->global->api_socket, len);
|
|
Packit Service |
3975d1 |
addr.sun_path[len] = '\0';
|
|
Packit Service |
3975d1 |
|
|
Packit Service |
3975d1 |
if (bind(server_socket, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
|
Packit Service |
3975d1 |
LOG("failed to bind server socket.\n");
|
|
Packit Service |
3975d1 |
goto out_close_server;
|
|
Packit Service |
3975d1 |
}
|
|
Packit Service |
3975d1 |
LOG("server socket bind success.\n");
|
|
Packit Service |
3975d1 |
|
|
Packit Service |
3975d1 |
if (listen(server_socket, 20) < 0) {
|
|
Packit Service |
3975d1 |
LOG("failed to listen on socket.\n");
|
|
Packit Service |
3975d1 |
goto out_close_server;
|
|
Packit Service |
3975d1 |
}
|
|
Packit Service |
3975d1 |
LOG("listening for connections.\n");
|
|
Packit Service |
3975d1 |
|
|
Packit Service |
3975d1 |
evt_api_is_ready = true;
|
|
Packit Service |
3975d1 |
|
|
Packit Service |
3975d1 |
pollfds[SRV_SOCKET].fd = server_socket;
|
|
Packit Service |
3975d1 |
pollfds[SRV_SOCKET].events = POLLIN | POLLPRI;
|
|
Packit Service |
3975d1 |
num_fds = 1;
|
|
Packit Service |
3975d1 |
|
|
Packit Service |
3975d1 |
while (c->global->running) {
|
|
Packit Service |
3975d1 |
|
|
Packit Service |
3975d1 |
res = poll(pollfds, num_fds, 100);
|
|
Packit Service |
3975d1 |
if (res < 0) {
|
|
Packit Service |
3975d1 |
LOG("poll error\n");
|
|
Packit Service |
3975d1 |
continue;
|
|
Packit Service |
3975d1 |
}
|
|
Packit Service |
3975d1 |
|
|
Packit Service |
3975d1 |
if (0 == res) // timeout
|
|
Packit Service |
3975d1 |
continue;
|
|
Packit Service |
3975d1 |
|
|
Packit Service |
3975d1 |
if ((nfds_t)res > num_fds) { // weird
|
|
Packit Service |
3975d1 |
LOG("something bad happened during poll!\n");
|
|
Packit Service |
3975d1 |
continue;
|
|
Packit Service |
3975d1 |
}
|
|
Packit Service |
3975d1 |
|
|
Packit Service |
3975d1 |
// handle requests on existing sockets
|
|
Packit Service |
3975d1 |
for (i = FIRST_CLIENT_SOCKET ; i < num_fds ; ++i) {
|
|
Packit Service |
3975d1 |
if (pollfds[i].revents) {
|
|
Packit Service |
3975d1 |
handle_message(pollfds[i].fd);
|
|
Packit Service |
3975d1 |
}
|
|
Packit Service |
3975d1 |
}
|
|
Packit Service |
3975d1 |
|
|
Packit Service |
3975d1 |
// handle new connection requests
|
|
Packit Service |
3975d1 |
if (pollfds[SRV_SOCKET].revents) {
|
|
Packit Service |
3975d1 |
|
|
Packit Service |
3975d1 |
if (num_fds == MAX_CLIENT_CONNECTIONS+1) {
|
|
Packit Service |
3975d1 |
LOG("exceeded max connections!\n");
|
|
Packit Service |
3975d1 |
continue;
|
|
Packit Service |
3975d1 |
}
|
|
Packit Service |
3975d1 |
|
|
Packit Service |
3975d1 |
conn_socket = accept(server_socket, NULL, NULL);
|
|
Packit Service |
3975d1 |
|
|
Packit Service |
3975d1 |
if (conn_socket < 0) {
|
|
Packit Service |
3975d1 |
LOG("failed to accept new connection!\n");
|
|
Packit Service |
3975d1 |
} else {
|
|
Packit Service |
3975d1 |
LOG("accepting connection %d.\n", conn_socket);
|
|
Packit Service |
3975d1 |
|
|
Packit Service |
3975d1 |
pollfds[num_fds].fd = conn_socket;
|
|
Packit Service |
3975d1 |
pollfds[num_fds].events = POLLIN | POLLPRI;
|
|
Packit Service |
3975d1 |
++num_fds;
|
|
Packit Service |
3975d1 |
}
|
|
Packit Service |
3975d1 |
|
|
Packit Service |
3975d1 |
}
|
|
Packit Service |
3975d1 |
|
|
Packit Service |
3975d1 |
}
|
|
Packit Service |
3975d1 |
|
|
Packit Service |
3975d1 |
opae_api_unregister_all_events();
|
|
Packit Service |
3975d1 |
|
|
Packit Service |
3975d1 |
// close any active client sockets
|
|
Packit Service |
3975d1 |
for (i = FIRST_CLIENT_SOCKET ; i < num_fds ; ++i) {
|
|
Packit Service |
3975d1 |
close(pollfds[i].fd);
|
|
Packit Service |
3975d1 |
}
|
|
Packit Service |
3975d1 |
|
|
Packit Service |
3975d1 |
out_close_server:
|
|
Packit Service |
3975d1 |
evt_api_is_ready = false;
|
|
Packit Service |
3975d1 |
close(server_socket);
|
|
Packit Service |
3975d1 |
out_exit:
|
|
Packit Service |
3975d1 |
LOG("exiting\n");
|
|
Packit Service |
3975d1 |
return NULL;
|
|
Packit Service |
3975d1 |
}
|