src/nexus.c
author Tero Marttila <terom@fixme.fi>
Sun, 22 Feb 2009 07:53:34 +0200
changeset 7 844f014409ff
parent 6 240ae8482d64
child 8 be88e543c8ff
permissions -rw-r--r--
and then error_msg
0
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
     1
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
     2
#include <stdlib.h>
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
     3
#include <unistd.h>
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
     4
#include <stdio.h>
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
     5
#include <string.h>
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
     6
#include <event.h>
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
     7
#include <assert.h>
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
     8
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
     9
#include <err.h>
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    10
1
cf0e1bb6bcab a fancy socket abstraction layer, with TCP, next, SSL. Also, .hgignore
Tero Marttila <terom@fixme.fi>
parents: 0
diff changeset
    11
#include "sock.h"
cf0e1bb6bcab a fancy socket abstraction layer, with TCP, next, SSL. Also, .hgignore
Tero Marttila <terom@fixme.fi>
parents: 0
diff changeset
    12
0
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    13
#define CONNECT_HOST "irc.fixme.fi"
7
844f014409ff and then error_msg
Tero Marttila <terom@fixme.fi>
parents: 6
diff changeset
    14
#define CONNECT_SERV "66976"
0
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    15
#define LINE_LENGTH 512
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    16
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    17
struct recvline_state {
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    18
    size_t tail_offset;
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    19
    size_t tail_len;
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    20
};
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    21
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    22
/*
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    23
 * This looks for a full '\r\n' terminated line at the beginning of the given buffer. If found, the \r\n will be
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    24
 * replaced with a '\0', and the offset to the beginning of the next line returned. If not found, zero is returned
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    25
 * (which is never a valid next-line offset).
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    26
 *
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    27
 * The given \a hint is an hint as to the offset at which to start scanning, used for incremental invocations of this
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    28
 * on the same buffer.
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    29
 *
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    30
 */
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    31
int _parse_line (char *buf, size_t len, size_t *hint) {
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    32
    int i;
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    33
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    34
    // empty buffer -> nothing
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    35
    if (len == 0)
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    36
        return 0;
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    37
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    38
    // look for terminating '\r\n' sequence
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    39
    for (i = *hint; i < len - 1; i++) {
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    40
        // match this + next char
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    41
        if (buf[i] == '\r' && buf[i + 1] == '\n')
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    42
            break;
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    43
    }
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    44
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    45
    // incomplete?
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    46
    if (i >= len - 1) {
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    47
        *hint = len - 1;
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    48
        return 0;
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    49
    }
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    50
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    51
    // mangle the newline off
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    52
    buf[i] = '\0';
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    53
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    54
    // return offset to next line
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    55
    return i + 2;
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    56
}
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    57
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    58
/*
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    59
 * Receive one line of data into the buffer of the given length
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    60
 */
1
cf0e1bb6bcab a fancy socket abstraction layer, with TCP, next, SSL. Also, .hgignore
Tero Marttila <terom@fixme.fi>
parents: 0
diff changeset
    61
int recvline (struct sock_stream *sock, char *buf, size_t len, struct recvline_state *ctx) {
0
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    62
    size_t recv_offset = 0, peek_offset = 0, next_offset = 0;
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    63
    int ret;
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    64
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    65
    // adjust offset from previous data
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    66
    recv_offset = ctx->tail_len;
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    67
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    68
    // move trailing data from previous line to front of buffer
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    69
    if (ctx->tail_offset) {
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    70
        // move to front
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    71
        memmove(buf, buf + ctx->tail_offset, ctx->tail_len);
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    72
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    73
        // reset
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    74
        ctx->tail_offset = 0;
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    75
        ctx->tail_len = 0;
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    76
    }
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    77
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    78
    // readline loop
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    79
    do {
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    80
        // parse any line at the beginning of the buffer
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    81
        if ((next_offset = _parse_line(buf, recv_offset, &peek_offset)) > 0)
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    82
            break;
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    83
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    84
        // ensure there's enough space for it
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    85
        assert(recv_offset < len);
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    86
        
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    87
        // otherwise, read more data
1
cf0e1bb6bcab a fancy socket abstraction layer, with TCP, next, SSL. Also, .hgignore
Tero Marttila <terom@fixme.fi>
parents: 0
diff changeset
    88
        if ((ret = sock_stream_read(sock, buf + recv_offset, len - recv_offset)) < 0)
0
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    89
            err(1, "read");
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    90
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    91
        // EOF?
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    92
        if (ret == 0)
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    93
            errx(1, "read: EOF");
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    94
        
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    95
        // update recv_offset
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    96
        recv_offset += ret;
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    97
    } while (1);
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    98
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    99
    // update state for next call
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   100
    ctx->tail_offset = next_offset;
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   101
    ctx->tail_len = recv_offset - next_offset;
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   102
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   103
    // ok
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   104
    return 0;
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   105
}
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   106
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   107
int main (int argc, char **argv) {
1
cf0e1bb6bcab a fancy socket abstraction layer, with TCP, next, SSL. Also, .hgignore
Tero Marttila <terom@fixme.fi>
parents: 0
diff changeset
   108
    struct sock_stream *sock;
0
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   109
    char line_buf[LINE_LENGTH + 1];
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   110
    struct recvline_state recvline_ctx;
4
a3ca0f97a075 change ERROR_* to use pointers again, and implement error_info for sock_init
Tero Marttila <terom@fixme.fi>
parents: 2
diff changeset
   111
    struct error_info err;
0
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   112
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   113
    // initialize
4
a3ca0f97a075 change ERROR_* to use pointers again, and implement error_info for sock_init
Tero Marttila <terom@fixme.fi>
parents: 2
diff changeset
   114
    if (sock_init(&err))
7
844f014409ff and then error_msg
Tero Marttila <terom@fixme.fi>
parents: 6
diff changeset
   115
        errx(1, "sock_init: %s", error_msg(&err));
4
a3ca0f97a075 change ERROR_* to use pointers again, and implement error_info for sock_init
Tero Marttila <terom@fixme.fi>
parents: 2
diff changeset
   116
0
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   117
    memset(&recvline_ctx, 0, sizeof(recvline_ctx));
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   118
    
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   119
    // over-simplified connect
5
a09a0797f6f0 ERROR-ify sock_gnutls
Tero Marttila <terom@fixme.fi>
parents: 4
diff changeset
   120
    if (sock_gnutls_connect(&sock, CONNECT_HOST, CONNECT_SERV, &err))
7
844f014409ff and then error_msg
Tero Marttila <terom@fixme.fi>
parents: 6
diff changeset
   121
        errx(1, "sock_gnutls_connect: %s", error_msg(&err));
0
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   122
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   123
    // read lines and dump them out
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   124
    do {
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   125
        // recv
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   126
        recvline(sock, line_buf, sizeof(line_buf), &recvline_ctx);
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   127
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   128
        // printf
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   129
        printf("<<< %s\n", line_buf);
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   130
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   131
    } while (1);
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   132
    
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   133
    // ok
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   134
    return 0;
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   135
}
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   136