2016-05-26 18:27:59 +02:00
|
|
|
#include "communication.h"
|
2016-12-19 19:20:27 +01:00
|
|
|
#include "utils.h"
|
2016-12-21 01:26:47 +01:00
|
|
|
#include "error.h"
|
2016-12-17 18:00:04 +01:00
|
|
|
|
|
|
|
#include <assert.h>
|
2016-05-30 01:54:19 +02:00
|
|
|
#include <stdio.h>
|
2016-09-11 14:37:41 +02:00
|
|
|
#include <errno.h>
|
2016-10-28 13:58:04 +02:00
|
|
|
|
2016-12-18 00:54:43 +01:00
|
|
|
void service_path (char *path, const char *sname, int index, int version)
|
2016-12-15 00:28:42 +01:00
|
|
|
{
|
2016-12-21 01:26:47 +01:00
|
|
|
assert (path != NULL);
|
|
|
|
assert (sname != NULL);
|
2016-12-17 18:00:04 +01:00
|
|
|
memset (path, 0, PATH_MAX);
|
|
|
|
snprintf (path, PATH_MAX, "%s/%s-%d-%d", TMPDIR, sname, index, version);
|
2016-06-12 12:38:43 +02:00
|
|
|
}
|
|
|
|
|
2018-10-09 13:16:40 +02:00
|
|
|
int ipc_server_init (char **env
|
2018-10-04 00:30:47 +02:00
|
|
|
, struct ipc_service *srv, const char *sname)
|
2016-05-26 18:27:59 +02:00
|
|
|
{
|
2016-06-05 20:48:13 +02:00
|
|
|
if (srv == NULL)
|
2018-10-08 15:18:56 +02:00
|
|
|
return IPC_ERROR_WRONG_PARAMETERS;
|
2016-05-26 18:27:59 +02:00
|
|
|
|
2016-06-12 14:41:25 +02:00
|
|
|
// TODO
|
2018-10-09 13:16:40 +02:00
|
|
|
// use env parameters
|
2016-06-12 14:41:25 +02:00
|
|
|
// it will be useful to change some parameters transparently
|
|
|
|
// ex: to get resources from other machines, choosing the
|
|
|
|
// remote with environment variables
|
|
|
|
|
|
|
|
env = env;
|
|
|
|
|
2016-12-17 18:00:04 +01:00
|
|
|
// gets the service path
|
|
|
|
service_path (srv->spath, sname, srv->index, srv->version);
|
2016-06-13 09:47:19 +02:00
|
|
|
|
2018-10-08 15:18:56 +02:00
|
|
|
int ret = usock_init (&srv->service_fd, srv->spath);
|
|
|
|
if (ret < 0) {
|
|
|
|
handle_err ("ipc_server_init", "usock_init ret < 0");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
2016-05-26 18:27:59 +02:00
|
|
|
}
|
|
|
|
|
2018-10-04 00:30:47 +02:00
|
|
|
int ipc_server_accept (struct ipc_service *srv, struct ipc_client *p)
|
2016-12-19 18:16:38 +01:00
|
|
|
{
|
2016-12-21 01:26:47 +01:00
|
|
|
assert (srv != NULL);
|
|
|
|
assert (p != NULL);
|
2016-12-19 18:16:38 +01:00
|
|
|
|
2018-10-08 15:18:56 +02:00
|
|
|
int ret = usock_accept (srv->service_fd, &p->proc_fd);
|
|
|
|
if (ret < 0) {
|
|
|
|
handle_err ("ipc_server_accept", "usock_accept < 0");
|
|
|
|
return -1;
|
|
|
|
}
|
2016-12-19 19:20:27 +01:00
|
|
|
|
2016-12-19 18:16:38 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-10-08 16:15:35 +02:00
|
|
|
// empty the srv structure
|
2018-10-04 00:30:47 +02:00
|
|
|
int ipc_server_close (struct ipc_service *srv)
|
2016-05-26 18:27:59 +02:00
|
|
|
{
|
2016-12-17 18:00:04 +01:00
|
|
|
usock_close (srv->service_fd);
|
2018-10-08 16:15:35 +02:00
|
|
|
int ret = usock_remove (srv->spath);
|
|
|
|
ipc_service_empty (srv);
|
|
|
|
return ret;
|
2016-05-26 18:27:59 +02:00
|
|
|
}
|
|
|
|
|
2018-10-04 01:54:12 +02:00
|
|
|
int ipc_server_close_client (struct ipc_client *p)
|
2016-05-30 01:54:19 +02:00
|
|
|
{
|
2016-12-19 18:16:38 +01:00
|
|
|
return usock_close (p->proc_fd);
|
2016-05-26 21:56:43 +02:00
|
|
|
}
|
|
|
|
|
2018-10-04 00:30:47 +02:00
|
|
|
int ipc_server_read (const struct ipc_client *p, struct ipc_message *m)
|
2016-05-26 21:56:43 +02:00
|
|
|
{
|
2018-10-03 21:52:11 +02:00
|
|
|
return ipc_message_read (p->proc_fd, m);
|
2016-05-26 18:27:59 +02:00
|
|
|
}
|
|
|
|
|
2018-10-04 00:30:47 +02:00
|
|
|
int ipc_server_write (const struct ipc_client *p, const struct ipc_message *m)
|
2016-12-19 18:16:38 +01:00
|
|
|
{
|
2018-10-03 21:52:11 +02:00
|
|
|
return ipc_message_write (p->proc_fd, m);
|
2016-12-19 18:16:38 +01:00
|
|
|
}
|
|
|
|
|
2018-10-09 13:16:40 +02:00
|
|
|
int ipc_application_connection (char **env
|
2018-10-08 16:15:35 +02:00
|
|
|
, struct ipc_service *srv, const char *sname)
|
2016-06-10 01:21:04 +02:00
|
|
|
{
|
2018-10-09 13:16:40 +02:00
|
|
|
// TODO
|
|
|
|
// use env parameters
|
|
|
|
// it will be useful to change some parameters transparently
|
|
|
|
// ex: to get resources from other machines, choosing the
|
|
|
|
// remote with environment variables
|
|
|
|
|
2016-12-19 18:16:38 +01:00
|
|
|
env = env;
|
2016-11-03 22:44:35 +01:00
|
|
|
|
2016-12-17 18:00:04 +01:00
|
|
|
assert (srv != NULL);
|
|
|
|
assert (sname != NULL);
|
2016-10-28 13:58:04 +02:00
|
|
|
|
2016-12-17 18:00:04 +01:00
|
|
|
if (srv == NULL) {
|
2016-10-28 13:58:04 +02:00
|
|
|
return -1;
|
2016-12-17 18:00:04 +01:00
|
|
|
}
|
2016-10-28 13:58:04 +02:00
|
|
|
|
2016-12-17 18:00:04 +01:00
|
|
|
// gets the service path
|
|
|
|
service_path (srv->spath, sname, srv->index, srv->version);
|
2016-12-15 00:28:42 +01:00
|
|
|
|
2018-10-08 15:18:56 +02:00
|
|
|
int ret = usock_connect (&srv->service_fd, srv->spath);
|
|
|
|
if (ret < 0) {
|
|
|
|
handle_err ("ipc_application_connection", "usock_connect ret <= 0");
|
|
|
|
return -1;
|
|
|
|
}
|
2016-10-28 13:58:04 +02:00
|
|
|
|
|
|
|
return 0;
|
2016-06-10 01:21:04 +02:00
|
|
|
}
|
|
|
|
|
2016-12-23 13:06:31 +01:00
|
|
|
// send a CLOSE message then close the socket
|
2018-10-04 00:30:47 +02:00
|
|
|
int ipc_application_close (struct ipc_service *srv)
|
2016-05-26 18:27:59 +02:00
|
|
|
{
|
2016-12-17 18:00:04 +01:00
|
|
|
return usock_close (srv->service_fd);
|
2016-05-26 18:27:59 +02:00
|
|
|
}
|
|
|
|
|
2018-10-04 00:30:47 +02:00
|
|
|
int ipc_application_read (struct ipc_service *srv, struct ipc_message *m)
|
2016-10-28 14:24:15 +02:00
|
|
|
{
|
2018-10-03 21:52:11 +02:00
|
|
|
return ipc_message_read (srv->service_fd, m);
|
2016-05-26 18:27:59 +02:00
|
|
|
}
|
|
|
|
|
2018-10-04 00:30:47 +02:00
|
|
|
int ipc_application_write (struct ipc_service *srv, const struct ipc_message *m)
|
2016-05-26 18:27:59 +02:00
|
|
|
{
|
2018-10-03 21:52:11 +02:00
|
|
|
return ipc_message_write (srv->service_fd, m);
|
2016-10-28 13:58:04 +02:00
|
|
|
}
|
2016-12-20 23:36:00 +01:00
|
|
|
|
|
|
|
|
2017-01-19 22:07:52 +01:00
|
|
|
/*calculer le max filedescriptor*/
|
2018-10-04 22:51:31 +02:00
|
|
|
static int getMaxFd(struct ipc_clients *clients)
|
2017-01-19 22:07:52 +01:00
|
|
|
{
|
|
|
|
|
|
|
|
int i;
|
|
|
|
int max = 0;
|
|
|
|
|
2018-10-04 22:51:31 +02:00
|
|
|
for (i = 0; i < clients->size; i++ ) {
|
|
|
|
if (clients->clients[i]->proc_fd > max) {
|
|
|
|
max = clients->clients[i]->proc_fd;
|
2017-01-19 22:07:52 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return max;
|
|
|
|
}
|
|
|
|
|
2016-12-22 21:48:35 +01:00
|
|
|
/*
|
2018-10-03 21:24:20 +02:00
|
|
|
* ipc_server_select prend en parametre
|
2018-10-04 01:22:50 +02:00
|
|
|
* * un tableau de client qu'on écoute
|
2016-12-22 21:48:35 +01:00
|
|
|
* * le service qui attend de nouvelles connexions
|
2018-10-04 01:22:50 +02:00
|
|
|
* * un tableau de client qui souhaitent parler
|
2016-12-22 21:48:35 +01:00
|
|
|
*
|
2018-10-04 22:51:31 +02:00
|
|
|
* 0 = OK
|
|
|
|
* -1 = error
|
2016-12-22 21:48:35 +01:00
|
|
|
*/
|
|
|
|
|
2018-10-04 22:51:31 +02:00
|
|
|
int ipc_server_select (struct ipc_clients *clients, struct ipc_service *srv
|
|
|
|
, struct ipc_clients *active_clients, int *new_connection)
|
2016-12-22 21:48:35 +01:00
|
|
|
{
|
2018-10-05 22:33:43 +02:00
|
|
|
*new_connection = 0;
|
2018-10-04 22:51:31 +02:00
|
|
|
assert (clients != NULL);
|
|
|
|
assert (active_clients != NULL);
|
2016-12-23 01:33:52 +01:00
|
|
|
|
2018-10-04 22:51:31 +02:00
|
|
|
// delete previous read active_clients array
|
2018-10-08 16:15:35 +02:00
|
|
|
ipc_clients_free (active_clients);
|
2016-12-23 01:33:52 +01:00
|
|
|
|
2016-12-20 23:36:00 +01:00
|
|
|
int i, j;
|
|
|
|
/* master file descriptor list */
|
|
|
|
fd_set master;
|
|
|
|
fd_set readf;
|
|
|
|
|
|
|
|
/* maximum file descriptor number */
|
|
|
|
int fdmax;
|
|
|
|
/* listening socket descriptor */
|
|
|
|
int listener = srv->service_fd;
|
|
|
|
|
|
|
|
/* clear the master and temp sets */
|
|
|
|
FD_ZERO(&master);
|
|
|
|
FD_ZERO(&readf);
|
|
|
|
/* add the listener to the master set */
|
|
|
|
FD_SET(listener, &master);
|
|
|
|
|
2018-10-04 22:51:31 +02:00
|
|
|
for (i=0; i < clients->size; i++) {
|
|
|
|
FD_SET(clients->clients[i]->proc_fd, &master);
|
2016-12-20 23:36:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* keep track of the biggest file descriptor */
|
2018-10-04 22:51:31 +02:00
|
|
|
fdmax = getMaxFd(clients) > srv->service_fd ? getMaxFd(clients) : srv->service_fd;
|
|
|
|
|
|
|
|
// printf ("loop ipc_server_select main_loop\n");
|
|
|
|
readf = master;
|
|
|
|
if(select(fdmax+1, &readf, NULL, NULL, NULL) == -1) {
|
|
|
|
perror("select");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*run through the existing connections looking for data to be read*/
|
|
|
|
for (i = 0; i <= fdmax; i++) {
|
|
|
|
// printf ("loop ipc_server_select inner loop\n");
|
|
|
|
if (FD_ISSET(i, &readf)) {
|
|
|
|
if (i == listener) {
|
|
|
|
*new_connection = 1;
|
|
|
|
} else {
|
|
|
|
for(j = 0; j < clients->size; j++) {
|
|
|
|
// printf ("loop ipc_server_select inner inner loop\n");
|
|
|
|
if(i == clients->clients[j]->proc_fd ) {
|
|
|
|
ipc_client_add (active_clients, clients->clients[j]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
2018-10-05 22:33:43 +02:00
|
|
|
}
|
2018-10-10 23:08:58 +02:00
|
|
|
|
|
|
|
/*calculer le max filedescriptor*/
|
|
|
|
static int getMaxFdServices(struct ipc_services *services)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
int max = 0;
|
|
|
|
|
|
|
|
for (i = 0; i < services->size; i++ ) {
|
|
|
|
if (services->services[i]->service_fd > max) {
|
|
|
|
max = services->services[i]->service_fd;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return max;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* ipc_application_select prend en parametre
|
|
|
|
* * un tableau de server qu'on écoute
|
|
|
|
* * le service qui attend de nouvelles connexions
|
|
|
|
* * un tableau de client qui souhaitent parler
|
|
|
|
*
|
|
|
|
* 0 = OK
|
|
|
|
* -1 = error
|
|
|
|
*/
|
|
|
|
|
|
|
|
int ipc_application_select (struct ipc_services *services, struct ipc_services *active_services)
|
|
|
|
{
|
|
|
|
assert (services != NULL);
|
|
|
|
assert (active_services != NULL);
|
|
|
|
|
|
|
|
// delete previous read active_services array
|
|
|
|
ipc_services_free (active_services);
|
|
|
|
|
|
|
|
int i, j;
|
|
|
|
/* master file descriptor list */
|
|
|
|
fd_set master;
|
|
|
|
fd_set readf;
|
|
|
|
|
|
|
|
/* maximum file descriptor number */
|
|
|
|
int fdmax;
|
|
|
|
|
|
|
|
/* clear the master and temp sets */
|
|
|
|
FD_ZERO(&master);
|
|
|
|
FD_ZERO(&readf);
|
|
|
|
|
|
|
|
for (i=0; i < services->size; i++) {
|
|
|
|
FD_SET(services->services[i]->service_fd, &master);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* keep track of the biggest file descriptor */
|
|
|
|
fdmax = getMaxFdServices(services);
|
|
|
|
|
|
|
|
// printf ("loop ipc_server_select main_loop\n");
|
|
|
|
readf = master;
|
|
|
|
if(select(fdmax+1, &readf, NULL, NULL, NULL) == -1) {
|
|
|
|
perror("select");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*run through the existing connections looking for data to be read*/
|
|
|
|
for (i = 0; i <= fdmax; i++) {
|
|
|
|
// printf ("loop ipc_server_select inner loop\n");
|
|
|
|
if (FD_ISSET(i, &readf)) {
|
|
|
|
for(j = 0; j < services->size; j++) {
|
|
|
|
// printf ("loop ipc_server_select inner inner loop\n");
|
|
|
|
if(i == services->services[j]->service_fd ) {
|
|
|
|
ipc_service_add (active_services, services->services[j]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|