pong now uses ipc_application_loop() in interactive mode
parent
64f1977eb2
commit
c43c678df8
|
@ -2,6 +2,7 @@
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "event.h"
|
#include "event.h"
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -109,7 +110,7 @@ int ipc_application_connection (char **env
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// send a CLOSE message then close the socket
|
// close the socket
|
||||||
int ipc_application_close (struct ipc_service *srv)
|
int ipc_application_close (struct ipc_service *srv)
|
||||||
{
|
{
|
||||||
return usock_close (srv->service_fd);
|
return usock_close (srv->service_fd);
|
||||||
|
@ -408,7 +409,120 @@ int ipc_service_loop (struct ipc_clients *clients, struct ipc_service *srv
|
||||||
return 0;
|
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;
|
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);
|
||||||
|
}
|
||||||
|
|
|
@ -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_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
|
#endif
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
enum ipc_event_type {
|
enum ipc_event_type {
|
||||||
IPC_EVENT_TYPE_NOT_SET
|
IPC_EVENT_TYPE_NOT_SET
|
||||||
, IPC_EVENT_TYPE_ERROR
|
, IPC_EVENT_TYPE_ERROR
|
||||||
|
, IPC_EVENT_TYPE_STDIN
|
||||||
, IPC_EVENT_TYPE_CONNECTION
|
, IPC_EVENT_TYPE_CONNECTION
|
||||||
, IPC_EVENT_TYPE_DISCONNECTION
|
, IPC_EVENT_TYPE_DISCONNECTION
|
||||||
, IPC_EVENT_TYPE_MESSAGE
|
, IPC_EVENT_TYPE_MESSAGE
|
||||||
|
|
|
@ -3,9 +3,7 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "../../core/message.h"
|
#include "../../core/ipc.h"
|
||||||
#include "../../core/error.h"
|
|
||||||
#include "../../core/communication.h"
|
|
||||||
|
|
||||||
#define MSG "coucou"
|
#define MSG "coucou"
|
||||||
#define SERVICE_NAME "pongd"
|
#define SERVICE_NAME "pongd"
|
||||||
|
@ -53,17 +51,10 @@ void non_interactive (char *env[])
|
||||||
|
|
||||||
void interactive (char *env[])
|
void interactive (char *env[])
|
||||||
{
|
{
|
||||||
struct ipc_message m;
|
int ret = 0;
|
||||||
memset (&m, 0, sizeof (struct ipc_message));
|
|
||||||
struct ipc_service srv;
|
struct ipc_service srv;
|
||||||
memset (&srv, 0, sizeof (struct ipc_service));
|
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
|
// index and version should be filled
|
||||||
srv.index = 0;
|
srv.index = 0;
|
||||||
srv.version = 0;
|
srv.version = 0;
|
||||||
|
@ -74,50 +65,61 @@ void interactive (char *env[])
|
||||||
exit (EXIT_FAILURE);
|
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) {
|
while (1) {
|
||||||
printf ("msg to send: ");
|
printf ("msg to send: ");
|
||||||
fflush (stdout);
|
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)
|
if (ret != 0) {
|
||||||
break;
|
handle_error("ipc_application_loop != 0");
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
if (strncmp(buf, "close server", 12) == 0) {
|
|
||||||
ask_server_to_quit = 1;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ipc_message_format_data (&m, buf, strlen(buf) +1);
|
switch (event.type) {
|
||||||
memset (buf, 0, IPC_MAX_MESSAGE_SIZE);
|
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) {
|
ipc_services_free (&services);
|
||||||
handle_err("main", "application_write < 0");
|
|
||||||
exit (EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
ipc_message_empty (&m);
|
|
||||||
|
|
||||||
if (ipc_application_read (&srv, &m) < 0) {
|
if (ipc_application_close (&srv) < 0) {
|
||||||
handle_err("main", "application_read < 0");
|
handle_err("main", "application_close < 0");
|
||||||
exit (EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
printf ("msg recv: %s", m.payload);
|
exit (EXIT_SUCCESS);
|
||||||
ipc_message_empty (&m);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (ask_server_to_quit) {
|
if (ipc_application_write (&srv, m) < 0) {
|
||||||
ipc_message_format_server_close (&m);
|
handle_err("main", "application_write < 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:
|
||||||
ipc_message_empty (&m);
|
{
|
||||||
} else if (ipc_application_close (&srv) < 0) {
|
struct ipc_message *m = event.m;
|
||||||
handle_err("main", "application_close < 0");
|
printf ("msg recv: %.*s", m->length, m->payload);
|
||||||
exit (EXIT_FAILURE);
|
};
|
||||||
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Reference in New Issue