Archived
3
0

pong now uses ipc_application_loop() in interactive mode

This commit is contained in:
Philippe PITTOLI 2018-10-28 18:12:17 +01:00
parent 64f1977eb2
commit c43c678df8
4 changed files with 166 additions and 46 deletions

View File

@ -2,6 +2,7 @@
#include "utils.h"
#include "error.h"
#include "event.h"
#include <unistd.h>
#include <assert.h>
#include <stdio.h>
@ -109,7 +110,7 @@ int ipc_application_connection (char **env
return 0;
}
// send a CLOSE message then close the socket
// close the socket
int ipc_application_close (struct ipc_service *srv)
{
return usock_close (srv->service_fd);
@ -408,7 +409,120 @@ int ipc_service_loop (struct ipc_clients *clients, struct ipc_service *srv
return 0;
}
int ipc_application_loop (struct ipc_services *services)
int ipc_application_loop_ (struct ipc_services *services, struct ipc_event *event, int interactive)
{
assert (services != NULL);
IPC_EVENT_CLEAN(event);
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);
if (interactive) {
FD_SET(0, &master);
}
for (i=0; i < services->size; i++) {
FD_SET(services->services[i]->service_fd, &master);
}
/* keep track of the biggest file descriptor */
fdmax = get_max_fd_from_ipc_services_ (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)) {
// interactive: input on stdin
if (i == 0) {
// XXX: by default, message type is 0
struct ipc_message *m = malloc (sizeof (struct ipc_message));
if (m == NULL) {
return IPC_ERROR_NOT_ENOUGH_MEMORY;
}
memset (m, 0, sizeof (struct ipc_message));
m->payload = malloc (IPC_MAX_MESSAGE_SIZE);
m->length = read(0, m->payload , IPC_MAX_MESSAGE_SIZE);
IPC_EVENT_SET(event, IPC_EVENT_TYPE_STDIN, m, NULL);
return 0;
}
for(j = 0; j < services->size; j++) {
// printf ("loop ipc_server_select inner inner loop\n");
if(i == services->services[j]->service_fd ) {
// listen to what they have to say (disconnection or message)
// then add a client to `event`, the ipc_event structure
int ret = 0;
struct ipc_message *m = NULL;
m = malloc (sizeof(struct ipc_message));
if (m == NULL) {
return IPC_ERROR_NOT_ENOUGH_MEMORY;
}
memset (m, 0, sizeof (struct ipc_message));
// current talking client
struct ipc_service *ps = services->services[j];
ret = ipc_application_read (ps, m);
if (ret < 0) {
handle_err ("ipc_application_loop", "ipc_application_read < 0");
ipc_message_empty (m);
free (m);
IPC_EVENT_SET(event, IPC_EVENT_TYPE_ERROR, NULL, ps);
return IPC_ERROR_READ;
}
// disconnection: close the service
if (ret == 1) {
if (ipc_application_close (ps) < 0) {
handle_err( "ipc_application_loop", "ipc_application_close < 0");
}
if (ipc_service_del (services, ps) < 0) {
handle_err( "ipc_application_loop", "ipc_service_del < 0");
}
ipc_message_empty (m);
free (m);
IPC_EVENT_SET(event, IPC_EVENT_TYPE_DISCONNECTION, NULL, ps);
// warning: do not forget to free the ipc_client structure
return 0;
}
// we received a new message from a client
IPC_EVENT_SET (event, IPC_EVENT_TYPE_MESSAGE, m, ps);
return 0;
}
}
}
}
return 0;
}
int ipc_application_loop (struct ipc_services *services, struct ipc_event *event) {
return ipc_application_loop_ (services, event, 0);
}
int ipc_application_loop_interactive (struct ipc_services *services, struct ipc_event *event) {
return ipc_application_loop_ (services, event, 1);
}

View File

@ -51,4 +51,7 @@ int ipc_application_write (struct ipc_service *, const struct ipc_message *m);
int ipc_application_select (struct ipc_services *services, struct ipc_services *active_services);
int ipc_application_loop (struct ipc_services *services, struct ipc_event *event);
int ipc_application_loop_interactive (struct ipc_services *services, struct ipc_event *event);
#endif

View File

@ -6,6 +6,7 @@
enum ipc_event_type {
IPC_EVENT_TYPE_NOT_SET
, IPC_EVENT_TYPE_ERROR
, IPC_EVENT_TYPE_STDIN
, IPC_EVENT_TYPE_CONNECTION
, IPC_EVENT_TYPE_DISCONNECTION
, IPC_EVENT_TYPE_MESSAGE

View File

@ -3,9 +3,7 @@
#include <string.h>
#include <unistd.h>
#include "../../core/message.h"
#include "../../core/error.h"
#include "../../core/communication.h"
#include "../../core/ipc.h"
#define MSG "coucou"
#define SERVICE_NAME "pongd"
@ -53,17 +51,10 @@ void non_interactive (char *env[])
void interactive (char *env[])
{
struct ipc_message m;
memset (&m, 0, sizeof (struct ipc_message));
int ret = 0;
struct ipc_service srv;
memset (&srv, 0, sizeof (struct ipc_service));
char buf[IPC_MAX_MESSAGE_SIZE];
memset (buf, 0, IPC_MAX_MESSAGE_SIZE);
int n;
int ask_server_to_quit = 0;
// index and version should be filled
srv.index = 0;
srv.version = 0;
@ -74,50 +65,61 @@ void interactive (char *env[])
exit (EXIT_FAILURE);
}
struct ipc_event event;
memset (&event, 0, sizeof (struct ipc_event));
struct ipc_services services;
memset (&services, 0, sizeof (struct ipc_services));
ipc_service_add (&services, &srv);
while (1) {
printf ("msg to send: ");
fflush (stdout);
n = read (0, buf, IPC_MAX_MESSAGE_SIZE);
ret = ipc_application_loop_interactive (&services, &event);
if (n == 0 || strncmp (buf, "exit", 4) == 0)
break;
if (strncmp(buf, "close server", 12) == 0) {
ask_server_to_quit = 1;
break;
if (ret != 0) {
handle_error("ipc_application_loop != 0");
exit (EXIT_FAILURE);
}
ipc_message_format_data (&m, buf, strlen(buf) +1);
memset (buf, 0, IPC_MAX_MESSAGE_SIZE);
switch (event.type) {
case IPC_EVENT_TYPE_STDIN:
{
struct ipc_message *m = event.m;
if ( m->length == 0 || strncmp (m->payload, "exit", 4) == 0) {
// print_msg (&m);
ipc_message_empty (m);
free (m);
if (ipc_application_write (&srv, &m) < 0) {
handle_err("main", "application_write < 0");
exit (EXIT_FAILURE);
}
ipc_message_empty (&m);
ipc_services_free (&services);
if (ipc_application_read (&srv, &m) < 0) {
handle_err("main", "application_read < 0");
exit (EXIT_FAILURE);
}
if (ipc_application_close (&srv) < 0) {
handle_err("main", "application_close < 0");
exit (EXIT_FAILURE);
}
printf ("msg recv: %s", m.payload);
ipc_message_empty (&m);
}
exit (EXIT_SUCCESS);
}
if (ask_server_to_quit) {
ipc_message_format_server_close (&m);
if (ipc_application_write (&srv, &m) < 0) {
handle_err("main", "application_write < 0");
exit (EXIT_FAILURE);
}
ipc_message_empty (&m);
} else if (ipc_application_close (&srv) < 0) {
handle_err("main", "application_close < 0");
exit (EXIT_FAILURE);
if (ipc_application_write (&srv, m) < 0) {
handle_err("main", "application_write < 0");
exit (EXIT_FAILURE);
}
}
break;
case IPC_EVENT_TYPE_MESSAGE:
{
struct ipc_message *m = event.m;
printf ("msg recv: %.*s", m->length, m->payload);
};
break;
case IPC_EVENT_TYPE_DISCONNECTION:
case IPC_EVENT_TYPE_NOT_SET:
case IPC_EVENT_TYPE_CONNECTION:
case IPC_EVENT_TYPE_ERROR:
default :
fprintf (stderr, "should not happen, event type %d\n", event.type);
}
}
}