src/line_proto.c
author Tero Marttila <terom@fixme.fi>
Sat, 28 Feb 2009 17:39:37 +0200
changeset 11 14e79683c48c
parent 10 9fe218576d13
child 12 4147fae232d9
permissions -rw-r--r--
working event-based operation for sock_tcp
8
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
     1
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
     2
#include "line_proto.h"
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
     3
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
     4
#include <string.h>
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
     5
#include <stdlib.h>
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
     6
#include <assert.h>
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
     7
10
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
     8
#include <err.h>
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
     9
8
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    10
/*
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    11
 * Our state
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    12
 */
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    13
struct line_proto {
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    14
    /* The sock_stream we read/write with */
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    15
    struct sock_stream *sock;
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    16
10
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    17
    /* The incoming line buffer */
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    18
    char *buf;
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    19
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    20
    /* Incoming buffer size */
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    21
    size_t buf_len;
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    22
8
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    23
    /* Offset of trailing data in buf */
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    24
    size_t tail_offset;
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    25
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    26
    /* Length of trailing data in buf, if any */
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    27
    size_t tail_len;
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    28
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    29
    /* Last error */
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    30
    struct error_info err;
10
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    31
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    32
    /* Callback info */
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    33
    line_proto_read_cb cb_read;
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    34
    void *cb_arg;
8
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    35
};
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    36
10
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    37
// function prototypes
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    38
static err_t line_proto_schedule_events (struct line_proto *lp, short what);
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    39
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    40
/*
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    41
 * Our sock_stream on_read handler
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    42
 */
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    43
static void line_proto_on_read (struct sock_stream *sock, void *arg)
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    44
{
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    45
    struct line_proto *lp = arg;
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    46
    const char *line;
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    47
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    48
    // sanity-check
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    49
    assert(lp->tail_offset < lp->buf_len);
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    50
    
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    51
    do {
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    52
        // attempt to read a line
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    53
        if (line_proto_read(lp, &line))
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    54
            // XXX: fail
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    55
            errx(1, "line_proto_read: %s", error_msg(&lp->err));
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    56
        
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    57
        // got a line?
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    58
        if (line)
11
14e79683c48c working event-based operation for sock_tcp
Tero Marttila <terom@fixme.fi>
parents: 10
diff changeset
    59
            lp->cb_read(line, lp->cb_arg);
10
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    60
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    61
    } while (line);
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    62
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    63
    // reschedule
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    64
    if (line_proto_schedule_events(lp, EV_READ))
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    65
        errx(1, "line_proto_schedule_events: %s", error_msg(&lp->err));
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    66
}
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    67
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    68
/*
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    69
 * Schedule our sock_stream callback
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    70
 */
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    71
static err_t line_proto_schedule_events (struct line_proto *lp, short what) 
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    72
{
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    73
    // just use sock_stream's interface
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    74
    if (sock_stream_event_enable(lp->sock, what))
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    75
        RETURN_SET_ERROR_INFO(&lp->err, sock_stream_error(lp->sock));
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    76
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    77
    return SUCCESS;
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    78
}
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    79
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    80
struct sock_stream_callbacks line_proto_sock_stream_callbacks = {
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    81
    .on_read    = &line_proto_on_read,
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    82
};
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    83
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    84
err_t line_proto_create (struct line_proto **lp_ptr, struct sock_stream *sock, size_t buf_size,
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    85
        line_proto_read_cb cb_func, void *cb_arg, struct error_info *err)
8
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    86
{
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    87
    struct line_proto *lp;
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    88
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    89
    // allocate
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    90
    if ((lp = calloc(1, sizeof(*lp))) == NULL)
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    91
        return SET_ERROR(err, ERR_CALLOC);
10
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    92
    
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    93
    // allocate buffer
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    94
    if ((lp->buf = malloc(buf_size)) == NULL) {
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    95
        free(lp);
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    96
        return SET_ERROR(err, ERR_CALLOC);
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
    97
    }
8
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    98
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    99
    // store
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   100
    lp->sock = sock;
10
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
   101
    lp->buf_len = buf_size;
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
   102
    lp->cb_read = cb_func;
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
   103
    lp->cb_arg = cb_arg;
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
   104
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
   105
    // initialize event-based stuff
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
   106
    sock_stream_event_init(sock, &line_proto_sock_stream_callbacks, lp);
11
14e79683c48c working event-based operation for sock_tcp
Tero Marttila <terom@fixme.fi>
parents: 10
diff changeset
   107
    line_proto_schedule_events(lp, EV_READ);
8
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   108
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   109
    // return
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   110
    *lp_ptr = lp;
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   111
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   112
    return SUCCESS;
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   113
}
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   114
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   115
/*
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   116
 * This looks for a full '\r\n' terminated line at the beginning of the given buffer. If found, the \r\n will be
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   117
 * replaced with a '\0', and the offset to the beginning of the next line returned. If not found, zero is returned
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   118
 * (which is never a valid next-line offset).
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   119
 *
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   120
 * The given \a hint is an hint as to the offset at which to start scanning, used for incremental invocations of this
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   121
 * on the same buffer.
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   122
 *
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   123
 */
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   124
int _parse_line (char *buf, size_t len, size_t *hint) {
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   125
    int i;
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   126
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   127
    // empty buffer -> nothing
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   128
    if (len == 0)
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   129
        return 0;
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   130
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   131
    // look for terminating '\r\n' sequence
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   132
    for (i = *hint; i < len - 1; i++) {
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   133
        // match this + next char
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   134
        if (buf[i] == '\r' && buf[i + 1] == '\n')
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   135
            break;
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   136
    }
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   137
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   138
    // incomplete?
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   139
    if (i >= len - 1) {
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   140
        *hint = len - 1;
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   141
        return 0;
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   142
    }
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   143
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   144
    // mangle the newline off
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   145
    buf[i] = '\0';
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   146
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   147
    // return offset to next line
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   148
    return i + 2;
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   149
}
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   150
10
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
   151
err_t line_proto_read (struct line_proto *lp, const char **line_ptr)
8
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   152
{
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   153
    // offset to recv() new data into, offset to _parse_line hint, offset to next line from _parse_line
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   154
    size_t recv_offset = 0, peek_offset = 0, next_offset = 0;
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   155
    int ret;
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   156
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   157
    // adjust offset from previous data
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   158
    recv_offset = lp->tail_len;
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   159
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   160
    // move trailing data from previous line to front of buffer
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   161
    if (lp->tail_offset) {
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   162
        // move to front
10
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
   163
        memmove(lp->buf, lp->buf + lp->tail_offset, lp->tail_len);
8
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   164
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   165
        // reset
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   166
        lp->tail_offset = 0;
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   167
        lp->tail_len = 0;
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   168
    }
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   169
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   170
    // readline loop
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   171
    do {
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   172
        // parse any line at the beginning of the buffer
10
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
   173
        if ((next_offset = _parse_line(lp->buf, recv_offset, &peek_offset)) > 0) {
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
   174
            // store a valid *line_ptr
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
   175
            *line_ptr = lp->buf;
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
   176
            
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
   177
            // exit loop and return
8
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   178
            break;
10
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
   179
        }
8
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   180
10
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
   181
        // ensure there's enough space for the rest of the line
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
   182
        // XXX: this must be an error, not an assert
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
   183
        assert(recv_offset < lp->buf_len);
8
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   184
        
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   185
        // otherwise, read more data
10
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
   186
        if ((ret = sock_stream_read(lp->sock, lp->buf + recv_offset, lp->buf_len - recv_offset)) < 0) {
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
   187
            // we can special-case EAGAIN, as it's expected
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
   188
            if (MATCH_ERROR(sock_stream_error(lp->sock), ERR_READ, EAGAIN)) {
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
   189
                // return a NULL *line_ptr
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
   190
                *line_ptr = NULL;
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
   191
                break;
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
   192
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
   193
            } else {
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
   194
                // store and return NULL on errors
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
   195
                RETURN_SET_ERROR_INFO(&lp->err, sock_stream_error(lp->sock));
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
   196
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
   197
            }
9fe218576d13 fix sock_stream read/write return value, move line buffer inside of line_proto, add some initial code for event-based non-blocking operation
Tero Marttila <terom@fixme.fi>
parents: 8
diff changeset
   198
        }
8
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   199
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   200
        // EOF?
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   201
        if (ret == 0)
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   202
            return SET_ERROR(&lp->err, ERR_READ_EOF);
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   203
        
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   204
        // update recv_offset
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   205
        recv_offset += ret;
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   206
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   207
    } while (1);
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   208
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   209
    // update state for next call
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   210
    lp->tail_offset = next_offset;
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   211
    lp->tail_len = recv_offset - next_offset;
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   212
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   213
    // ok
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   214
    return SUCCESS;
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   215
}
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   216
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   217
const struct error_info* line_proto_error (struct line_proto *lp)
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   218
{
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   219
    // return pointer
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   220
    return &lp->err;
be88e543c8ff split off line_proto, and make sock_stream_error return a const error_info
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   221
}