Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  netstring.c

  Sprache: C
 

/*++
/* NAME
/* netstring 3
/* SUMMARY
/* netstring stream I/O support
/* SYNOPSIS
/* #include <netstring.h>
/*
/* void netstring_setup(stream, timeout)
/* VSTREAM *stream;
/* int timeout;
/*
/* void netstring_except(stream, exception)
/* VSTREAM *stream;
/* int exception;
/*
/* const char *netstring_strerror(err)
/* int err;
/*
/* VSTRING *netstring_get(stream, buf, limit)
/* VSTREAM *stream;
/* VSTRING *buf;
/* ssize_t limit;
/*
/* void netstring_put(stream, data, len)
/* VSTREAM *stream;
/* const char *data;
/* ssize_t len;
/*
/* void netstring_put_multi(stream, data, len, data, len, ..., 0)
/* VSTREAM *stream;
/* const char *data;
/* ssize_t len;
/*
/* void NETSTRING_PUT_BUF(stream, buf)
/* VSTREAM *stream;
/* VSTRING *buf;
/*
/* void netstring_fflush(stream)
/* VSTREAM *stream;
/*
/* VSTRING *netstring_memcpy(buf, data, len)
/* VSTRING *buf;
/* const char *data;
/* ssize_t len;
/*
/* VSTRING *netstring_memcat(buf, data, len)
/* VSTRING *buf;
/* const char *src;
/* ssize_t len;
/* AUXILIARY ROUTINES
/* ssize_t netstring_get_length(stream)
/* VSTREAM *stream;
/*
/* VSTRING *netstring_get_data(stream, buf, len)
/* VSTREAM *stream;
/* VSTRING *buf;
/* ssize_t len;
/*
/* void netstring_get_terminator(stream)
/* VSTREAM *stream;
/* DESCRIPTION
/* This module reads and writes netstrings with error detection:
/* timeouts, unexpected end-of-file, or format errors. Netstring
/* is a data format designed by Daniel Bernstein.
/*
/* netstring_setup() arranges for a time limit on the netstring
/* read and write operations described below.
/* This routine alters the behavior of streams as follows:
/* .IP \(bu
/* The read/write timeout is set to the specified value.
/* .IP \(bu
/* The stream is configured to enable exception handling.
/* .PP
/* netstring_except() raises the specified exception on the
/* named stream. See the DIAGNOSTICS section below.
/*
/* netstring_strerror() converts an exception number to string.
/*
/* netstring_get() reads a netstring from the specified stream
/* and extracts its content. The limit specifies a maximal size.
/* Specify zero to disable the size limit. The result is not null
/* terminated.  The result value is the buf argument.
/*
/* netstring_put() encapsulates the specified string as a netstring
/* and sends the result to the specified stream.
/* The stream output buffer is not flushed.
/*
/* netstring_put_multi() encapsulates the content of multiple strings
/* as one netstring and sends the result to the specified stream. The
/* argument list must be terminated with a null data pointer.
/* The stream output buffer is not flushed.
/*
/* NETSTRING_PUT_BUF() is a macro that provides a VSTRING-based
/* wrapper for the netstring_put() routine.
/*
/* netstring_fflush() flushes the output buffer of the specified
/* stream and handles any errors.
/*
/* netstring_memcpy() encapsulates the specified data as a netstring
/* and copies the result over the specified buffer. The result
/* value is the buffer.
/*
/* netstring_memcat() encapsulates the specified data as a netstring
/* and appends the result to the specified buffer. The result
/* value is the buffer.
/*
/* The following routines provide low-level access to a netstring
/* stream.
/*
/* netstring_get_length() reads a length field from the specified
/* stream, and absorbs the netstring length field terminator.
/*
/* netstring_get_data() reads the specified number of bytes from the
/* specified stream into the specified buffer, and absorbs the
/* netstring terminator.  The result value is the buf argument.
/*
/* netstring_get_terminator() reads the netstring terminator from
/* the specified stream.
/* DIAGNOSTICS
/* .fi
/* .ad
/* In case of error, a vstream_longjmp() call is performed to the
/* caller-provided context specified with vstream_setjmp().
/* Error codes passed along with vstream_longjmp() are:
/* .IP NETSTRING_ERR_EOF
/* An I/O error happened, or the peer has disconnected unexpectedly.
/* .IP NETSTRING_ERR_TIME
/* The time limit specified to netstring_setup() was exceeded.
/* .IP NETSTRING_ERR_FORMAT
/* The input contains an unexpected character value.
/* .IP NETSTRING_ERR_SIZE
/* The input is larger than acceptable.
/* BUGS
/* The timeout deadline affects all I/O on the named stream, not
/* just the I/O done on behalf of this module.
/*
/* The timeout deadline overwrites any previously set up state on
/* the named stream.
/*
/* netstrings are not null terminated, which makes printing them
/* a bit awkward.
/* LICENSE
/* .ad
/* .fi
/* The Secure Mailer license must be distributed with this software.
/* SEE ALSO
/* https://cr.yp.to/proto/netstrings.txt, netstring definition
/* AUTHOR(S)
/* Wietse Venema
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*
/* Wietse Venema
/* porcupine.org
/*--*/


/* System library. */

#include <sys_defs.h>
#include <stdarg.h>
#include <ctype.h>
#include <errno.h>

/* Utility library. */

#include <msg.h>
#include <vstream.h>
#include <vstring.h>
#include <compat_va_copy.h>
#include <netstring.h>

/* Application-specific. */

#define STR(x) vstring_str(x)
#define LEN(x) VSTRING_LEN(x)

/* netstring_setup - initialize netstring stream */

void    netstring_setup(VSTREAM *stream, int timeout)
{
    vstream_control(stream,
      CA_VSTREAM_CTL_TIMEOUT(timeout),
      CA_VSTREAM_CTL_EXCEPT,
      CA_VSTREAM_CTL_END);
}

/* netstring_except - process netstring stream exception */

void    netstring_except(VSTREAM *stream, int exception)
{
    vstream_longjmp(stream, exception);
}

/* netstring_get_length - read netstring length + terminator */

ssize_t netstring_get_length(VSTREAM *stream)
{
    const char *myname = "netstring_get_length";
    ssize_t len = 0;
    int     ch;
    int     digit;

    for (;;) {
 switch (ch = VSTREAM_GETC(stream)) {
 case VSTREAM_EOF:
     netstring_except(stream, vstream_ftimeout(stream) ?
        NETSTRING_ERR_TIME : NETSTRING_ERR_EOF);
 case ':':
     if (msg_verbose > 1)
  msg_info("%s: read netstring length %ld", myname, (long) len);
     return (len);
 default:
     if (!ISDIGIT(ch))
  netstring_except(stream, NETSTRING_ERR_FORMAT);
     digit = ch - '0';
     if (len > SSIZE_T_MAX / 10
  || (len *= 10) > SSIZE_T_MAX - digit)
  netstring_except(stream, NETSTRING_ERR_SIZE);
     len += digit;
     break;
 }
    }
}

/* netstring_get_data - read netstring payload + terminator */

VSTRING *netstring_get_data(VSTREAM *stream, VSTRING *buf, ssize_t len)
{
    const char *myname = "netstring_get_data";

    /*
     * Read the payload and absorb the terminator.
     */

    if (vstream_fread_buf(stream, buf, len) != len)
 netstring_except(stream, vstream_ftimeout(stream) ?
    NETSTRING_ERR_TIME : NETSTRING_ERR_EOF);
    if (msg_verbose > 1)
 msg_info("%s: read netstring data %.*s",
   myname, (int) (len < 30 ? len : 30), STR(buf));
    netstring_get_terminator(stream);

    /*
     * Return the buffer.
     */

    return (buf);
}

/* netstring_get_terminator - absorb netstring terminator */

void    netstring_get_terminator(VSTREAM *stream)
{
    if (VSTREAM_GETC(stream) != ',')
 netstring_except(stream, NETSTRING_ERR_FORMAT);
}

/* netstring_get - read string from netstring stream */

VSTRING *netstring_get(VSTREAM *stream, VSTRING *buf, ssize_t limit)
{
    ssize_t len;

    len = netstring_get_length(stream);
    if (ENFORCING_SIZE_LIMIT(limit) && len > limit)
 netstring_except(stream, NETSTRING_ERR_SIZE);
    netstring_get_data(stream, buf, len);
    return (buf);
}

/* netstring_put - send string as netstring */

void    netstring_put(VSTREAM *stream, const char *data, ssize_t len)
{
    const char *myname = "netstring_put";

    if (msg_verbose > 1)
 msg_info("%s: write netstring len %ld data %.*s",
   myname, (long) len, (int) (len < 30 ? len : 30), data);
    vstream_fprintf(stream, "%ld:", (long) len);
    vstream_fwrite(stream, data, len);
    VSTREAM_PUTC(',', stream);
}

/* netstring_put_multi - send multiple strings as one netstring */

void    netstring_put_multi(VSTREAM *stream,...)
{
    const char *myname = "netstring_put_multi";
    ssize_t total;
    char   *data;
    ssize_t data_len;
    va_list ap;
    va_list ap2;

    /*
     * Initialize argument lists.
     */

    va_start(ap, stream);
    VA_COPY(ap2, ap);

    /*
     * Figure out the total result size.
     */

    for (total = 0; (data = va_arg(ap, char *)) != 0; total += data_len)
 if ((data_len = va_arg(ap, ssize_t)) < 0)
     msg_panic("%s: bad data length %ld", myname, (long) data_len);
    va_end(ap);
    if (total < 0)
 msg_panic("%s: bad total length %ld", myname, (long) total);
    if (msg_verbose > 1)
 msg_info("%s: write total length %ld", myname, (long) total);

    /*
     * Send the length, content and terminator.
     */

    vstream_fprintf(stream, "%ld:", (long) total);
    while ((data = va_arg(ap2, char *)) != 0) {
 data_len = va_arg(ap2, ssize_t);
 if (msg_verbose > 1)
     msg_info("%s: write netstring len %ld data %.*s",
       myname, (long) data_len,
       (int) (data_len < 30 ? data_len : 30), data);
 if (vstream_fwrite(stream, data, data_len) != data_len)
     netstring_except(stream, vstream_ftimeout(stream) ?
        NETSTRING_ERR_TIME : NETSTRING_ERR_EOF);
    }
    va_end(ap2);
    vstream_fwrite(stream, ","1);
}

/* netstring_fflush - flush netstring stream */

void    netstring_fflush(VSTREAM *stream)
{
    if (vstream_fflush(stream) == VSTREAM_EOF)
 netstring_except(stream, vstream_ftimeout(stream) ?
    NETSTRING_ERR_TIME : NETSTRING_ERR_EOF);
}

/* netstring_memcpy - copy data as in-memory netstring */

VSTRING *netstring_memcpy(VSTRING *buf, const char *src, ssize_t len)
{
    vstring_sprintf(buf, "%ld:", (long) len);
    vstring_memcat(buf, src, len);
    VSTRING_ADDCH(buf, ',');
    return (buf);
}

/* netstring_memcat - append data as in-memory netstring */

VSTRING *netstring_memcat(VSTRING *buf, const char *src, ssize_t len)
{
    vstring_sprintf_append(buf, "%ld:", (long) len);
    vstring_memcat(buf, src, len);
    VSTRING_ADDCH(buf, ',');
    return (buf);
}

/* netstring_strerror - convert error number to string */

const char *netstring_strerror(int err)
{
    switch (err) {
 case NETSTRING_ERR_EOF:
 return ("unexpected disconnect");
    case NETSTRING_ERR_TIME:
 errno = ETIMEDOUT;
 return ("time limit exceeded");
    case NETSTRING_ERR_FORMAT:
 errno = 0;
 return ("input format error");
    case NETSTRING_ERR_SIZE:
#ifdef EMSGSIZE
 errno = EMSGSIZE;
#endif
 return ("input exceeds size limit");
    default:
 errno = 0;
 return ("unknown netstring error");
    }
}

 /*
  * Proof-of-concept netstring encoder/decoder.
  * 
  * Usage: netstring command...
  * 
  * Run the command as a child process. Then, convert between plain strings on
  * our own stdin/stdout, and netstrings on the child program's stdin/stdout.
  * 
  * Example (socketmap test server): netstring nc -l 9999
  */

#ifdef TEST
#include <unistd.h>
#include <stdlib.h>
#include <events.h>

static VSTRING *stdin_read_buf;  /* stdin line buffer */
static VSTRING *child_read_buf;  /* child read buffer */
static VSTREAM *child_stream;  /* child stream (full-duplex) */

/* stdin_read_event - line-oriented event handler */

static void stdin_read_event(int event, void *context)
{
    int     ch;

    /*
     * Send a netstring to the child when we have accumulated an entire line
     * of input.
     * 
     * Note: the first VSTREAM_GETCHAR() call implicitly fills the VSTREAM
     * buffer. We must drain the entire VSTREAM buffer before requesting the
     * next read(2) event.
     */

    do {
 ch = VSTREAM_GETCHAR();
 switch (ch) {
 default:
     VSTRING_ADDCH(stdin_read_buf, ch);
     break;
 case '\n':
     NETSTRING_PUT_BUF(child_stream, stdin_read_buf);
     vstream_fflush(child_stream);
     VSTRING_RESET(stdin_read_buf);
     break;
 case VSTREAM_EOF:
     /* Better: wait for child to terminate. */
     sleep(1);
     exit(0);
 }
    } while (vstream_peek(VSTREAM_IN) > 0);
}

/* child_read_event - netstring-oriented event handler */

static void child_read_event(int event, void *context)
{

    /*
     * Read an entire netstring from the child and send the result to stdout.
     * 
     * This is a simplistic implementation that assumes a server will not
     * trickle its data.
     * 
     * Note: the first netstring_get() call implicitly fills the VSTREAM buffer.
     * We must drain the entire VSTREAM buffer before requesting the next
     * read(2) event.
     */

    do {
 netstring_get(child_stream, child_read_buf, 10000);
 vstream_fwrite(VSTREAM_OUT, STR(child_read_buf), LEN(child_read_buf));
 VSTREAM_PUTC('\n', VSTREAM_OUT);
 vstream_fflush(VSTREAM_OUT);
    } while (vstream_peek(child_stream) > 0);
}

int     main(int argc, char **argv)
{
    int     err;

    /*
     * Sanity check.
     */

    if (argv[1] == 0)
 msg_fatal("usage: %s command...", argv[0]);

    /*
     * Run the specified command as a child process with stdin and stdout
     * connected to us.
     */

    child_stream = vstream_popen(O_RDWR, CA_VSTREAM_POPEN_ARGV(argv + 1),
     CA_VSTREAM_POPEN_END);
    vstream_control(child_stream, CA_VSTREAM_CTL_DOUBLE, CA_VSTREAM_CTL_END);
    netstring_setup(child_stream, 10);

    /*
     * Buffer plumbing.
     */

    stdin_read_buf = vstring_alloc(100);
    child_read_buf = vstring_alloc(100);

    /*
     * Monitor both the child's stdout stream and our own stdin stream. If
     * there is activity on the child stdout stream, read an entire netstring
     * or EOF. If there is activity on stdin, send a netstring to the child
     * when we have read an entire line, or terminate in case of EOF.
     */

    event_enable_read(vstream_fileno(VSTREAM_IN), stdin_read_event, (void *) 0);
    event_enable_read(vstream_fileno(child_stream), child_read_event,
        (void *) 0);

    if ((err = vstream_setjmp(child_stream)) == 0) {
 for (;;)
     event_loop(-1);
    } else {
 msg_fatal("%s: %s", argv[1], netstring_strerror(err));
    }
}

#endif

Messung V0.5 in Prozent
C=90 H=91 G=90

¤ Dauer der Verarbeitung: 0.14 Sekunden  (vorverarbeitet am  2026-08-10) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Statistik
#Sources=141584
#Domains=738142