libipc-old/core/communication.c

256 lines
6.8 KiB
C
Raw Normal View History

2016-05-26 18:27:59 +02:00
#include "communication.h"
2016-12-17 18:00:04 +01:00
#include "usocket.h"
#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>
#include <stdio.h>
2016-09-11 14:37:41 +02:00
#include <errno.h>
2016-10-28 13:58:04 +02:00
void service_path (char *path, const char *sname, int index, int version)
{
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-03 21:24:20 +02:00
int ipc_server_init (int argc, char **argv, 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)
2016-06-13 09:47:19 +02:00
return ER_PARAMS;
2016-05-26 18:27:59 +02:00
2016-06-12 14:41:25 +02:00
// TODO
// use the argc, argv and env parameters
// it will be useful to change some parameters transparently
// ex: to get resources from other machines, choosing the
// remote with environment variables
argc = argc;
argv = argv;
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
return usock_init (&srv->service_fd, srv->spath);
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-21 01:26:47 +01:00
assert (srv != NULL);
assert (p != NULL);
2016-12-21 01:26:47 +01:00
usock_accept (srv->service_fd, &p->proc_fd);
2018-10-03 22:02:37 +02:00
struct ipc_message m_con;
memset (&m_con, 0, sizeof (struct ipc_message));
2018-10-03 21:24:20 +02:00
ipc_server_read (p, &m_con);
2016-12-21 01:26:47 +01:00
// TODO: handle the parameters in the first message
2018-10-03 21:52:11 +02:00
ipc_message_free (&m_con);
2018-10-03 22:02:37 +02:00
struct ipc_message m_ack;
memset (&m_ack, 0, sizeof (struct ipc_message));
2018-10-03 21:52:11 +02:00
ipc_message_format_ack (&m_ack, NULL, 0);
2018-10-03 21:24:20 +02:00
ipc_server_write (p, &m_ack);
2018-10-03 21:52:11 +02:00
ipc_message_free (&m_ack);
2016-12-19 22:49:26 +01:00
return 0;
}
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);
return usock_remove (srv->spath);
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)
{
2018-10-03 22:02:37 +02:00
// struct ipc_message m_ack_dis;
// memset (&m_ack_dis, 0, sizeof (struct ipc_message));
2016-12-23 13:06:31 +01:00
// m_ack_dis.type = MSG_TYPE_CLOSE;
2016-12-23 01:33:52 +01:00
2018-10-03 21:52:11 +02:00
// if (ipc_message_write (p->proc_fd, &m_ack_dis) < 0) {
2018-10-04 01:54:12 +02:00
// handle_err ("server_close_client", "ipc_message_write < 0");
2016-12-23 01:33:52 +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)
{
2018-10-03 21:52:11 +02:00
return ipc_message_write (p->proc_fd, m);
}
2018-10-03 21:24:20 +02:00
int ipc_application_connection (int argc, char **argv, char **env
2018-10-04 00:30:47 +02:00
, struct ipc_service *srv, const char *sname
, const char *connectionstr, size_t msize)
{
argc = argc;
argv = argv;
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);
usock_connect (&srv->service_fd, srv->spath);
2016-10-28 13:58:04 +02:00
// send connection string and receive acknowledgement
2018-10-03 22:02:37 +02:00
struct ipc_message m_con;
memset (&m_con, 0, sizeof (struct ipc_message));
2016-12-21 01:26:47 +01:00
// format the connection msg
2018-10-03 21:52:11 +02:00
if (ipc_message_format_con (&m_con, connectionstr, msize) < 0) {
handle_err ("application_connection", "ipc_message_format_con");
return -1;
}
2016-12-21 01:26:47 +01:00
// send connection msg
2018-10-03 21:24:20 +02:00
ipc_application_write (srv, &m_con);
2018-10-03 21:52:11 +02:00
ipc_message_free (&m_con);
2016-12-21 01:26:47 +01:00
// receive ack msg
2018-10-03 22:02:37 +02:00
struct ipc_message m_ack;
memset (&m_ack, 0, sizeof (struct ipc_message));
2018-10-03 21:24:20 +02:00
ipc_application_read (srv, &m_ack);
2016-12-21 01:26:47 +01:00
assert (m_ack.type == MSG_TYPE_ACK);
2018-10-04 01:54:12 +02:00
assert (m_ack.length == 0);
2018-10-03 21:52:11 +02:00
ipc_message_free (&m_ack);
2016-12-19 22:49:26 +01:00
2016-10-28 13:58:04 +02:00
return 0;
}
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
{
2018-10-03 22:02:37 +02:00
struct ipc_message m;
memset (&m, 0, sizeof (struct ipc_message));
2016-12-23 13:06:31 +01:00
m.type = MSG_TYPE_CLOSE;
2018-10-03 21:52:11 +02:00
if (ipc_message_write (srv->service_fd, &m) < 0) {
handle_err ("application_close", "ipc_message_write < 0");
2016-12-21 01:26:47 +01: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 01:22:50 +02:00
static int getMaxFd(struct ipc_client_array *ap)
2017-01-19 22:07:52 +01:00
{
int i;
int max = 0;
for (i = 0; i < ap->size; i++ ) {
2018-10-04 01:54:12 +02:00
if (ap->clients[i]->proc_fd > max) {
max = ap->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 01:22:50 +02:00
* la fonction trouve le clientus/service actif et renvoie
2016-12-22 21:48:35 +01:00
* un entier correspondant à quel descripteur de fichier il faut lire
* * celui du serveur = nouvelle connexion entrante (CONNECTION)
2018-10-04 01:22:50 +02:00
* * celui d'un ou plusieurs clientus = ils nous parlent (APPLICATION)
2016-12-22 21:48:35 +01:00
* * les deux à la fois (CON_APP)
*/
2018-10-04 01:22:50 +02:00
int ipc_server_select (struct ipc_client_array *ap, struct ipc_service *srv
2018-10-04 01:54:12 +02:00
, struct ipc_client_array *client)
2016-12-22 21:48:35 +01:00
{
2016-12-23 01:33:52 +01:00
assert (ap != NULL);
2018-10-04 01:54:12 +02:00
assert (client != NULL);
2016-12-23 01:33:52 +01:00
2018-10-04 01:22:50 +02:00
// delete previous read client array
2018-10-04 01:54:12 +02:00
ipc_client_array_free (client);
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);
2016-12-23 01:33:52 +01:00
for (i=0; i < ap->size; i++) {
2018-10-04 01:54:12 +02:00
FD_SET(ap->clients[i]->proc_fd, &master);
2016-12-20 23:36:00 +01:00
}
/* keep track of the biggest file descriptor */
fdmax = getMaxFd(ap) > srv->service_fd ? getMaxFd(ap) : srv->service_fd;
2016-12-23 01:33:52 +01:00
int is_listener = 0;
do {
2018-10-03 21:24:20 +02:00
// printf ("loop ipc_server_select main_loop\n");
2016-12-20 23:36:00 +01:00
readf = master;
2016-12-22 21:48:35 +01:00
if(select(fdmax+1, &readf, NULL, NULL, NULL) == -1) {
perror("select");
return -1;
2016-12-20 23:36:00 +01:00
}
/*run through the existing connections looking for data to be read*/
for (i = 0; i <= fdmax; i++) {
2018-10-03 21:24:20 +02:00
// printf ("loop ipc_server_select inner loop\n");
2016-12-20 23:36:00 +01:00
if (FD_ISSET(i, &readf)) {
if (i == listener) {
2016-12-23 01:33:52 +01:00
is_listener = 1;
2016-12-22 21:48:35 +01:00
} else {
2016-12-20 23:36:00 +01:00
for(j = 0; j < ap->size; j++) {
2018-10-03 21:24:20 +02:00
// printf ("loop ipc_server_select inner inner loop\n");
2018-10-04 01:54:12 +02:00
if(i == ap->clients[j]->proc_fd ) {
ipc_client_add (client, ap->clients[j]);
2016-12-20 23:36:00 +01:00
}
}
}
}
}
2016-12-23 01:33:52 +01:00
} while (0);
2018-10-04 01:54:12 +02:00
if (client->size > 0 && is_listener)
2016-12-23 01:33:52 +01:00
return CON_APP;
2018-10-04 01:54:12 +02:00
if (client->size > 0)
2016-12-23 01:33:52 +01:00
return APPLICATION;
return CONNECTION;
2016-12-20 23:36:00 +01:00
}