cvsuser     03/10/11 00:09:00

  Modified:    io       io_unix.c io_win32.c
  Log:
  Beginnings of a network API. Not compiled by default so as not to break
  untested platforms yet. Set PARROT_NET_DEVEL to 1 in io/io_private.h
  to play with it. Currently only a UNIX version, Win32 coming soon.
  
  Revision  Changes    Path
  1.36      +257 -2    parrot/io/io_unix.c
  
  Index: io_unix.c
  ===================================================================
  RCS file: /cvs/public/parrot/io/io_unix.c,v
  retrieving revision 1.35
  retrieving revision 1.36
  diff -u -w -r1.35 -r1.36
  --- io_unix.c 11 Oct 2003 04:10:13 -0000      1.35
  +++ io_unix.c 11 Oct 2003 07:08:59 -0000      1.36
  @@ -1,7 +1,7 @@
   /* io_unix.c
    *  Copyright: 2001-2003 The Perl Foundation.  All Rights Reserved.
    *  CVS Info
  - *      $Id: io_unix.c,v 1.35 2003/10/11 04:10:13 mrjoltcola Exp $
  + *      $Id: io_unix.c,v 1.36 2003/10/11 07:08:59 mrjoltcola Exp $
    *  Overview:
    *      This is the Parrot IO UNIX layer. May be changed to
    *      include other platforms if that platform is similar
  @@ -420,6 +420,248 @@
   
   
   
  +/*
  + * These could be native extensions but they probably should be
  + * here if we wish to make them integrated with the async IO system.
  + */
  +
  +
  +/*
  + *  Networking Section of IO Layer
  + *  Very minimal stubs for now, maybe someone will run with these.
  + */
  +
  +
  +/*
  + * PIO_sockaddr_in is not part of the layer and so must be extern
  + * XXX: We can probably just write our own routines (htons, inet_aton, etc.) 
  + * and take this out of platform specific compilation
  + */
  +STRING *
  +PIO_sockaddr_in(theINTERP, unsigned short port, STRING * addr)
  +{
  +    STRING * packed;
  +    struct sockaddr_in sa;
  +    /* XXX: Fixme, inet_addr obsolete, replace with inet_aton */
  +    sa.sin_addr.s_addr =
  +                inet_addr(string_to_cstring(interpreter, addr));
  +    sa.sin_port = htons(port);
  +
  +    fprintf(stderr, "sockaddr_in: port %d\n", port);
  +    packed = string_make(interpreter, &sa, sizeof(struct sockaddr), NULL, 0,
  +                                NULL);
  +    if(!packed)
  +        PANIC("unix_sockaddr: failed to create string");
  +    return packed;
  +}
  +
  +#if PARROT_NET_DEVEL
  +
  +
  +static ParrotIO *
  +PIO_unix_socket(theINTERP, ParrotIOLayer *layer, int fam, int type, int proto)
  +{
  +    int sock;
  +    ParrotIO * io;
  +    if((sock = socket(fam, type, proto)) >= 0) {
  +        io = PIO_new(interpreter, PIO_F_SOCKET, 0, PIO_F_READ|PIO_F_WRITE);
  +        io->fd = sock;
  +        io->remote.sin_family = fam;
  +        fprintf(stderr, "socket: fd = %d\n", sock);
  +        return io;
  +    }
  +    perror("socket:");
  +    return 0;
  +}
  +
  +static INTVAL
  +PIO_unix_connect(theINTERP, ParrotIOLayer *layer, ParrotIO *io, STRING *r)
  +{
  +    if(r) {
  +        struct sockaddr_in sa;
  +        memcpy(&sa, r->bufstart, sizeof(struct sockaddr));
  +        io->remote.sin_addr.s_addr = sa.sin_addr.s_addr;
  +        io->remote.sin_port = sa.sin_port;
  +    }
  +AGAIN:
  +    fprintf(stderr, "connect: fd = %d port = %d\n", io->fd, 
ntohs(io->remote.sin_port));
  +    if((connect(io->fd, (struct sockaddr*)&io->remote,
  +                   sizeof(struct sockaddr))) != 0) {
  +        switch(errno) {
  +            case EINTR:        goto AGAIN;
  +            case EINPROGRESS:  goto AGAIN;
  +            case EISCONN:      return 0;
  +            case EINVAL:
  +            default:           perror("connect:"); return -1;
  +        }
  +    }
  +
  +    return 0;
  +}
  +
  +
  +static INTVAL
  +PIO_unix_send(theINTERP, ParrotIOLayer *layer, ParrotIO * io, STRING *s)
  +{
  +    int error, bytes, byteswrote, maxwrite;
  +    bytes = string_length(s);
  +    byteswrote = 0;
  +    maxwrite = 2048;
  +AGAIN:
  +    /*
  +     * Ignore encoding issues for now.
  +     */
  +    if((error = send(io->fd, (char *)s->bufstart + byteswrote,
  +                            s->buflen, 0)) >= 0) {
  +        byteswrote += error;
  +        if(byteswrote >= bytes) {
  +            return byteswrote;
  +        }
  +        else if(bytes - byteswrote < maxwrite) {
  +            maxwrite = bytes - byteswrote;
  +        }
  +        goto AGAIN;
  +    }
  +    else {
  +        switch(errno) {
  +            case EINTR:        goto AGAIN;
  +#ifdef EWOULDBLOCK
  +            case EWOULDBLOCK:  goto AGAIN;
  +#else
  +            case EAGAIN:       goto AGAIN;
  +#endif
  +            case EPIPE:        close(io->fd);
  +                               return -1;
  +            default:           return -1;
  +        }
  +    }
  +}
  +
  +static INTVAL
  +PIO_unix_recv(theINTERP, ParrotIOLayer *layer, ParrotIO * io, STRING **s)
  +{
  +    int error;
  +    unsigned int bytesread = 0;
  +    char buf[2048+1];
  +AGAIN:
  +    if((error = recv(io->fd, buf, 2048, 0)) >= 0) {
  +        if(error > 0)
  +            bytesread += error;
  +        else {
  +            close(io->fd);
  +        }
  +        *s = string_make(interpreter, buf, bytesread + 1, NULL, 0, NULL);
  +        if(!*s) {
  +            PANIC("PIO_recv: Failed to allocate string");
  +        }
  +        return bytesread;
  +    } else {
  +        switch(errno) {
  +            case EINTR:        goto AGAIN;
  +#ifdef EWOULDBLOCK
  +            case EWOULDBLOCK:  goto AGAIN;
  +#else
  +            case EGAIN:        goto AGAIN;
  +#endif
  +            case ECONNRESET:   close(io->fd);
  +                               return -1;
  +            default:           close(io->fd);
  +                               return -1;
  +        }
  +    }
  +}
  +
  +
  +/*
  + * Utility function for polling a single IO stream with a timeout.
  + * Returns 1 | 2 | 4 (read, write, error) value
  + * This is not equivalent to any speficic POSIX or BSD Socket
  + * call, however it is a useful, common primitive.
  + * Also, a buffering layer above this may choose to reimpliment
  + * by checking the read buffer.
  + */
  +static INTVAL
  +PIO_unix_poll(theINTERP, ParrotIOLayer *l, ParrotIO *io, int which,
  +               int sec, int usec)
  +{
  +    int n;
  +    fd_set r, w, e;
  +    struct timeval t;
  +    t.tv_sec = sec;
  +    t.tv_usec = usec;
  +    FD_ZERO(&r); FD_ZERO(&w); FD_ZERO(&e);
  +    /* These should be defined in header */
  +    if(which & 1) FD_SET(io->fd, &r);
  +    if(which & 2) FD_SET(io->fd, &w);
  +    if(which & 4) FD_SET(io->fd, &e);
  +AGAIN:
  +    if((select(io->fd+1, &r, &w, &e, &t)) >= 0) {
  +        n = (FD_ISSET(io->fd, &r) ? 1 : 0);
  +        n |= (FD_ISSET(io->fd, &w) ? 2 : 0);
  +        n |= (FD_ISSET(io->fd, &e) ? 4 : 0);
  +        return n;
  +    }
  +    else {
  +        switch(errno) {
  +            case EINTR:        goto AGAIN;
  +            default:           return -1;
  +        }
  +    }
  +}
  +
  +/*
  + * Very limited exec for now.
  + * XXX: Where does this fit, should it belong in the ParrotIOLayerAPI?
  + */
  +static ParrotIO *
  +PIO_unix_pipe(theINTERP, ParrotIOLayer *l, STRING *cmd, int flags)
  +{
  +#if defined (linux) || defined (solaris)
  +    ParrotIO *io;
  +    int pid, err, fds[2];
  +    char *ccmd = string_to_cstring(interpreter, cmd);
  +
  +    if((err = pipe(fds)) < 0) {
  +        perror("pipe:");
  +        return NULL;
  +    }
  +
  +    /* Parent - return IO stream */
  +    if((pid = fork()) > 0) {
  +        io = PIO_new(interpreter, PIO_F_PIPE, 0, PIO_F_READ|PIO_F_WRITE);
  +        io->fd = fds[0];
  +        io->fd2 = fds[1];
  +        return io;
  +    }
  +
  +    /* Child - exec process */
  +    if(pid == 0) {
  +        close(STDIN_FILENO);
  +        close(STDOUT_FILENO);
  +        close(STDERR_FILENO);
  +        if( dup(fds[0]) != STDIN_FILENO || dup(fds[1]) != STDOUT_FILENO
  +               || dup(fds[1]) != STDERR_FILENO )
  +        {
  +            exit(0);
  +        }
  +
  +        execl(ccmd, ccmd, (char*)0);
  +        /* Will never reach this unless exec fails. */
  +        perror("execvp:");
  +        return NULL;
  +    }
  +
  +    perror("fork:");
  +#endif
  +    return NULL;
  +}
  +
  +#endif
  +
  +
  +
  +
  +
   ParrotIOLayerAPI pio_unix_layer_api = {
       PIO_unix_init,
       PIO_base_new_layer,
  @@ -443,7 +685,20 @@
       PIO_null_setlinebuf,
       PIO_null_getcount,
       PIO_null_fill,
  -    PIO_null_eof
  +    PIO_null_eof,
  +#if PARROT_NET_DEVEL
  +    PIO_unix_poll,
  +    PIO_unix_socket,
  +    PIO_unix_connect,
  +    PIO_unix_send,
  +    PIO_unix_recv
  +#else
  +    0, /* no poll */
  +    0, /* no socket */
  +    0, /* no connect */
  +    0, /* no send */
  +    0 /* no recv */
  +#endif
   };
   
   
  
  
  
  1.35      +33 -2     parrot/io/io_win32.c
  
  Index: io_win32.c
  ===================================================================
  RCS file: /cvs/public/parrot/io/io_win32.c,v
  retrieving revision 1.34
  retrieving revision 1.35
  diff -u -w -r1.34 -r1.35
  --- io_win32.c        10 Oct 2003 13:18:56 -0000      1.34
  +++ io_win32.c        11 Oct 2003 07:08:59 -0000      1.35
  @@ -1,7 +1,7 @@
   /* io_win32.c
    *  Copyright: 2001-2003 The Perl Foundation.  All Rights Reserved.
    *  CVS Info
  - *      $Id: io_win32.c,v 1.34 2003/10/10 13:18:56 boemmels Exp $
  + *      $Id: io_win32.c,v 1.35 2003/10/11 07:08:59 mrjoltcola Exp $
    *  Overview:
    *      This is the Parrot IO OS layer for Win32 platforms.
    *  Data Structure and Algorithms:
  @@ -340,6 +340,32 @@
   }
   
   
  +/*
  + * PIO_sockaddr_in is not part of the layer and so must be extern
  + * XXX: We can probably just write our own routines (htons, inet_aton, etc.)
  + * and take this out of platform specific compilation
  + */
  +STRING *
  +PIO_sockaddr_in(theINTERP, unsigned short port, STRING * addr)
  +{       
  +#if 0
  +    /* Not sure if this compiles on Win32 yet, rather not break things */
  +
  +    STRING * packed;
  +    struct sockaddr_in sa;
  +    /* XXX: Fixme, inet_addr obsolete, replace with inet_aton */
  +    sa.sin_addr.s_addr =
  +                inet_addr(string_to_cstring(interpreter, addr));
  +    sa.sin_port = htons(port);
  +    packed = string_make(interpreter, &sa, sizeof(struct sockaddr), NULL, 0,
  +                                NULL);
  +    if(!packed)
  +        PANIC("unix_sockaddr: failed to create string");
  +    return packed;
  +#endif
  +    return NULL;
  +}   
  +
   
   ParrotIOLayerAPI pio_win32_layer_api = {
       PIO_win32_init,
  @@ -364,7 +390,12 @@
       PIO_null_setlinebuf,
       PIO_null_getcount,
       PIO_null_fill,
  -    PIO_null_eof
  +    PIO_null_eof,
  +    0, /* no poll */
  +    0, /* no socket */
  +    0, /* no connect */
  +    0, /* no send */
  +    0 /* no recv */
   };
   
   
  
  
  

Reply via email to