/*
 * shuffle.c
 * $Id: shuffle.c,v 1.2 1996/04/30 21:49:11 abaird Exp $
 */

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/uio.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <StubPreamble.h>
#include <javaString.h>

#include "w3c_jigsaw_http_Shuffler.h"
#include "w3c_httpd_cheat_io.h"
#include "ShufflerProtocol.h"

#define CLI_PERM 0777

/* # of sent request (may be diff. than msg count) */
static int request_sent = 1 ;

/*
 * Shuffler.initialize (String path) ;
 */

long 
w3c_jigsaw_http_Shuffler_initialize (struct Hw3c_jigsaw_http_Shuffler *s
				     , struct Hjava_lang_String *jpath) {
    int    fd = -1 ;
    struct sockaddr_un unadr ;
    char *path = makeCString (jpath) ;
    int unadrlen = - 1 ;
    char cpath[128] ;
    static int bid = 0 ;

    /* create the socket, connect and return */
    if ((fd = socket (AF_UNIX, SOCK_STREAM, 0)) < 0 ) {
	perror ("Shuffler[initialize]: connect") ;
	return (long) -1 ;
    }
    /* Get our identify */
    memset (&unadr, 0, sizeof(unadr)) ;
    unadr.sun_family = AF_UNIX ;
    sprintf (unadr.sun_path, "%s/shuffler-%05d%02d", path, getpid(), bid++) ;
    unadrlen = sizeof (unadr.sun_family) + strlen (unadr.sun_path) ;
    unlink (unadr.sun_path) ;
    if ( bind (fd, (struct sockaddr *) &unadr, unadrlen) < 0 ) {
	perror ("Shuffler[initialize]: bind") ;
	return (long) -2 ;
    }
    if ( chmod (unadr.sun_path, CLI_PERM) < 0 ) {
	perror ("Shuffler[initialize]: chmod") ;
	return (long) -3 ;
    }
    /* connect to server */
    memset (&unadr, 0, sizeof (unadr)) ;
    unadr.sun_family = AF_UNIX ;
    sprintf (unadr.sun_path, "%s/shuffler", path) ;
    unadrlen = sizeof (unadr.sun_family) + strlen (unadr.sun_path) ;
    if ( connect (fd, (struct sockaddr *) &unadr, unadrlen) < 0 ) {
	perror ("Shuffler[initialize]: connect" ) ;
	close (fd) ;
	return (long) -4 ;
    }
    unhand(s)->fd = fd ;
    return 0 ;
}

/*
 * Shuffler.shuffle (ShuffleHandler h) ;
 * Send the given bytes to the shuffler, along with the given array
 * of file descriptors.
 */

long 
w3c_jigsaw_http_Shuffler_shuffle (struct Hw3c_jigsaw_http_Shuffler *s
				  , struct Hw3c_jigsaw_http_ShuffleHandler *h)
{
    ShufflerMessageRec msg ;
    int socket = unhand(s)->fd ;
    int sid = -1 ;

    msg.msg.op    = SHUFFLER_OP_COPY ;
    msg.msg.msgid = request_sent++ ;
    msg.fds[0]    = unhand (unhand(h)->in)->fd - 1 ;
    msg.fds[1]    = unhand(unhand(h)->out)->fd - 1 ;
    if ( ShufflerSendMessage (socket, &msg) < 0 )
	return (long) -1 ;
    return request_sent - 1 ;
}

/**
 * Get next message, returns:
 * <0: if error occured,
 *  0: if thread should retry (no data ready)
 * >0: if okay
 */

long 
w3c_jigsaw_http_Shuffler_getNextMessage(struct Hw3c_jigsaw_http_Shuffler *s
					,struct Hw3c_jigsaw_http_ShuffleMessage *m) {
    ShufflerMessageRec msg ;
    int socket = unhand(s)->fd ;
    int rid = -1 ;
    struct timeval timeout ;
    int ready = -1 ;
    fd_set rfds ;

    memset (&timeout, 0, sizeof(timeout)) ;
    FD_ZERO(&rfds) ;
    FD_SET (socket, &rfds) ;
    if ( (ready = select (socket+1, &rfds, NULL, NULL, &timeout)) == 0 ) {
	return (long) 0 ;
    } else if ( ready < 0 ) {
	return (long) -1 ;
    }
    if ( (rid = ShufflerGetNextMessage (socket, &msg)) < 0 )
	return (long) -1 ;
    unhand(m)->op     = (long) msg.msg.op ;
    unhand(m)->length = (long) msg.msg.status ;
    unhand(m)->id     = (long) msg.msg.msgid ;
    return (long) msg.msg.msgid ;
}

