pong now uses ipc_application_loop() in interactive mode
parent
64f1977eb2
commit
c43c678df8
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Reference in New Issue