src/nexus.c
author Tero Marttila <terom@fixme.fi>
Sun, 22 Feb 2009 02:00:34 +0200
changeset 0 317e5bc59627
child 1 cf0e1bb6bcab
permissions -rw-r--r--
initial code...
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 <sys/types.h>
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
     4
#include <sys/socket.h>
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
     5
#include <unistd.h>
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
     6
#include <stdio.h>
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
     7
#include <netdb.h>
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
     8
#include <string.h>
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
     9
#include <event.h>
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    10
#include <assert.h>
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    11
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    12
#include <err.h>
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    13
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    14
#define CONNECT_HOST "irc.fixme.fi"
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    15
#define CONNECT_SERV "6667"
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    16
#define LINE_LENGTH 512
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    17
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    18
/*
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    19
 * Simple getaddrinfo() connect
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    20
 */
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    21
int sock_connect (const char *host, const char *service) {
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    22
    struct addrinfo hints, *res, *r;
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    23
    int _err, sock = -1;
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    24
    
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    25
    // hints
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    26
    memset(&hints, 0, sizeof(hints));
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    27
    hints.ai_family = AF_UNSPEC;
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    28
    hints.ai_socktype = SOCK_STREAM;
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    29
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    30
    // resolve
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    31
    if ((_err = getaddrinfo(host, service, &hints, &res)))
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    32
        errx(1, "getaddrinfo: %s", gai_strerror(_err));
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    33
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    34
    // use
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    35
    for (r = res; r; r = r->ai_next) {
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    36
        // XXX: wrong
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    37
        if ((sock = socket(r->ai_family, r->ai_socktype, r->ai_protocol)) < 0)
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    38
            err(1, "socket");
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    39
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    40
        if (connect(sock, r->ai_addr, r->ai_addrlen))
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    41
            err(1, "connect");
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    42
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    43
        break;
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    44
    }
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    45
    
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    46
    // ensure we got some valid socket
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    47
    if (sock < 0)
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    48
        errx(1, "no valid socket");
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    49
    
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    50
    // ok
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    51
    return sock;
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    52
}
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    53
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    54
struct recvline_state {
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    55
    size_t tail_offset;
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    56
    size_t tail_len;
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
/*
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    60
 * 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
    61
 * 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
    62
 * (which is never a valid next-line offset).
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    63
 *
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    64
 * 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
    65
 * on the same buffer.
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    66
 *
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    67
 */
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    68
int _parse_line (char *buf, size_t len, size_t *hint) {
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    69
    int i;
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    70
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    71
    // empty buffer -> nothing
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    72
    if (len == 0)
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    73
        return 0;
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    74
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    75
    // look for terminating '\r\n' sequence
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    76
    for (i = *hint; i < len - 1; i++) {
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    77
        // match this + next char
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    78
        if (buf[i] == '\r' && buf[i + 1] == '\n')
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    79
            break;
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    80
    }
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    81
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    82
    // incomplete?
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    83
    if (i >= len - 1) {
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    84
        *hint = len - 1;
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    85
        return 0;
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    86
    }
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    87
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    88
    // mangle the newline off
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    89
    buf[i] = '\0';
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    90
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    91
    // return offset to next line
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    92
    return i + 2;
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    93
}
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    94
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    95
/*
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    96
 * Receive one line of data into the buffer of the given length
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    97
 */
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    98
int recvline (int sock, char *buf, size_t len, struct recvline_state *ctx) {
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    99
    size_t recv_offset = 0, peek_offset = 0, next_offset = 0;
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   100
    int ret;
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   101
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   102
    // adjust offset from previous data
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   103
    recv_offset = ctx->tail_len;
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   104
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   105
    // move trailing data from previous line to front of buffer
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   106
    if (ctx->tail_offset) {
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   107
        // move to front
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   108
        memmove(buf, buf + ctx->tail_offset, ctx->tail_len);
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   109
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   110
        // reset
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   111
        ctx->tail_offset = 0;
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   112
        ctx->tail_len = 0;
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   113
    }
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   114
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   115
    // readline loop
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   116
    do {
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   117
        // parse any line at the beginning of the buffer
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   118
        if ((next_offset = _parse_line(buf, recv_offset, &peek_offset)) > 0)
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   119
            break;
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   120
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   121
        // ensure there's enough space for it
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   122
        assert(recv_offset < len);
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   123
        
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   124
        // otherwise, read more data
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   125
        if ((ret = read(sock, buf + recv_offset, len - recv_offset)) < 0)
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   126
            err(1, "read");
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   127
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   128
        // EOF?
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   129
        if (ret == 0)
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   130
            errx(1, "read: EOF");
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   131
        
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   132
        // update recv_offset
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   133
        recv_offset += ret;
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   134
    } while (1);
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   135
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   136
    // update state for next call
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   137
    ctx->tail_offset = next_offset;
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   138
    ctx->tail_len = recv_offset - next_offset;
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   139
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   140
    // ok
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   141
    return 0;
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   142
}
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   143
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   144
int main (int argc, char **argv) {
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   145
    int sock;
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   146
    char line_buf[LINE_LENGTH + 1];
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   147
    struct recvline_state recvline_ctx;
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   148
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   149
    // initialize
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   150
    memset(&recvline_ctx, 0, sizeof(recvline_ctx));
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   151
    
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   152
    // over-simplified connect
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   153
    sock = sock_connect(CONNECT_HOST, CONNECT_SERV);
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   154
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   155
    // read lines and dump them out
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   156
    do {
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   157
        // recv
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   158
        recvline(sock, line_buf, sizeof(line_buf), &recvline_ctx);
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   159
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   160
        // printf
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   161
        printf("<<< %s\n", line_buf);
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   162
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   163
    } while (1);
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   164
    
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   165
    // ok
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   166
    return 0;
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   167
}
317e5bc59627 initial code...
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   168