src/proto2/NetworkTCP.cc
author terom
Thu, 20 Nov 2008 22:55:28 +0000
branchno-netsession
changeset 39 cfb8b6e2a35f
parent 38 4189b8bf3a5b
permissions -rw-r--r--
almost playable
31
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
     1
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
     2
#include "NetworkTCP.hh"
38
4189b8bf3a5b kind of works
terom
parents: 37
diff changeset
     3
#include "Engine.hh"
31
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
     4
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
     5
#include <cstdlib>
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
     6
#include <cassert>
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
     7
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
     8
NetworkBuffer::NetworkBuffer (NetworkSocket &socket, size_t size_hint) :
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
     9
    socket(socket), buf(0), size(0), offset(0) {
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
    10
    
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
    11
    // allocate initial buffer
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
    12
    if ((buf = (char *) malloc(size_hint)) == NULL)
37
ed2957490bbf compile step complete
terom
parents: 34
diff changeset
    13
       throw NetworkBufferError("malloc failed");
31
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
    14
    
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
    15
    // remember size
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
    16
    size = size_hint;
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
    17
}
32
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
    18
        
37
ed2957490bbf compile step complete
terom
parents: 34
diff changeset
    19
NetworkBuffer::~NetworkBuffer (void) {
32
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
    20
    free(buf);
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
    21
}
31
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
    22
37
ed2957490bbf compile step complete
terom
parents: 34
diff changeset
    23
void NetworkBuffer::resize (size_t item_size) {
32
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
    24
    size_t new_size = size;
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
    25
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
    26
    // grow new_size until item_size fits
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
    27
    while (offset + item_size > new_size)
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
    28
        new_size *= 2;
31
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
    29
    
32
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
    30
    // grow if needed
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
    31
    if (new_size != size) {
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
    32
        // realloc buffer
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
    33
        if ((buf = (char *) realloc((void *) buf, new_size)) == NULL)
37
ed2957490bbf compile step complete
terom
parents: 34
diff changeset
    34
            throw NetworkBufferError("realloc failed");
32
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
    35
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
    36
        // update size
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
    37
        size = new_size;
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
    38
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
    39
    } else if (new_size > (offset + item_size) * 4) {
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
    40
        // XXX: shrink?
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
    41
    }
31
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
    42
}
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
    43
        
32
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
    44
void NetworkBuffer::trim (size_t prefix_size) {
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
    45
    // update offset
37
ed2957490bbf compile step complete
terom
parents: 34
diff changeset
    46
    offset -= prefix_size;
32
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
    47
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
    48
    // shift the buffer forwards from (buf + prefix) -> (buf), copying (old_offset - prefix) bytes
37
ed2957490bbf compile step complete
terom
parents: 34
diff changeset
    49
    memmove(buf, buf + prefix_size, offset);
32
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
    50
}
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
    51
     
37
ed2957490bbf compile step complete
terom
parents: 34
diff changeset
    52
bool NetworkBuffer::try_read (size_t item_size) {
32
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
    53
    int ret;
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
    54
    size_t to_read = item_size;
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
    55
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
    56
    // keept reads at at least NETWORK_CHUNK_SIZE bytes
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
    57
    if (to_read < NETWORK_TCP_CHUNK_SIZE)
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
    58
        to_read = NETWORK_TCP_CHUNK_SIZE;
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
    59
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
    60
    // resize buffer if needed
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
    61
    resize(to_read);
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
    62
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
    63
    // read once
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
    64
    try {
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
    65
        ret = socket.recv(buf + offset, to_read);
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
    66
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
    67
    } catch (CL_Error &e) {
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
    68
        if (errno == EAGAIN)
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
    69
            return false;
38
4189b8bf3a5b kind of works
terom
parents: 37
diff changeset
    70
32
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
    71
        else
38
4189b8bf3a5b kind of works
terom
parents: 37
diff changeset
    72
            throw NetworkSocketOSError(socket, "recv");
32
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
    73
    }
38
4189b8bf3a5b kind of works
terom
parents: 37
diff changeset
    74
    
4189b8bf3a5b kind of works
terom
parents: 37
diff changeset
    75
    // handle EOF
4189b8bf3a5b kind of works
terom
parents: 37
diff changeset
    76
    if (ret == 0)
4189b8bf3a5b kind of works
terom
parents: 37
diff changeset
    77
        throw NetworkSocketEOFError(socket, "recv");
32
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
    78
38
4189b8bf3a5b kind of works
terom
parents: 37
diff changeset
    79
    assert(ret >= 0);
37
ed2957490bbf compile step complete
terom
parents: 34
diff changeset
    80
32
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
    81
    // update offset
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
    82
    offset += ret;
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
    83
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
    84
    // did we get enough?
37
ed2957490bbf compile step complete
terom
parents: 34
diff changeset
    85
    if ((unsigned int) ret < item_size)
32
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
    86
        return false;
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
    87
    else
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
    88
        return true;
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
    89
} 
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
    90
        
37
ed2957490bbf compile step complete
terom
parents: 34
diff changeset
    91
bool NetworkBuffer::peek_prefix (uint16_t &ref) {
32
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
    92
    if (offset < sizeof(uint16_t))
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
    93
        return false;
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
    94
37
ed2957490bbf compile step complete
terom
parents: 34
diff changeset
    95
    ref = ntohs(*((uint16_t *) (buf)));
32
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
    96
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
    97
    return true;
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
    98
}
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
    99
    
37
ed2957490bbf compile step complete
terom
parents: 34
diff changeset
   100
bool NetworkBuffer::peek_prefix (uint32_t &ref) {
32
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   101
    if (offset < sizeof(uint32_t))
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   102
        return false;
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   103
37
ed2957490bbf compile step complete
terom
parents: 34
diff changeset
   104
    ref = ntohl(*((uint32_t *) (buf)));
32
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   105
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   106
    return true;
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   107
}
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   108
37
ed2957490bbf compile step complete
terom
parents: 34
diff changeset
   109
template <typename PrefixType> PrefixType NetworkBuffer::read_prefix (char *buf_ptr, size_t buf_max) {
32
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   110
    PrefixType prefix = 0;
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   111
    size_t missing = 0;
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   112
    
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   113
    do {    
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   114
        // do we have the prefix?
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   115
        if (peek_prefix(prefix)) {
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   116
            // do we already have the payload?
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   117
            if (offset >= sizeof(PrefixType) + prefix) {
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   118
                break;
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   119
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   120
            } else {
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   121
                missing = (sizeof(PrefixType) + prefix) - offset;
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   122
            }
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   123
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   124
        } else {
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   125
            missing = sizeof(PrefixType);
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   126
        }
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   127
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   128
        // sanity-check
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   129
        assert(missing);
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   130
        
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   131
        // try and read the missing data
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   132
        if (try_read(missing) == false) {
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   133
            // if unable to read what we need, return zero.
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   134
            return 0;
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   135
        }
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   136
        
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   137
        // assess the situation again
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   138
    } while (true);
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   139
    
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   140
    // copy the data over, unless it's too large
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   141
    if (prefix <= buf_max) {
39
cfb8b6e2a35f almost playable
terom
parents: 38
diff changeset
   142
        // ...don't copy the prefix, though
cfb8b6e2a35f almost playable
terom
parents: 38
diff changeset
   143
        memcpy(buf_ptr, buf + sizeof(PrefixType), prefix);
32
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   144
    
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   145
        // trim the bytes out
38
4189b8bf3a5b kind of works
terom
parents: 37
diff changeset
   146
        trim(sizeof(PrefixType) + prefix);
32
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   147
        
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   148
        // return
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   149
        return prefix;
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   150
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   151
    } else {
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   152
        // trim the bytes out
38
4189b8bf3a5b kind of works
terom
parents: 37
diff changeset
   153
        trim(sizeof(PrefixType) + prefix);
32
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   154
        
37
ed2957490bbf compile step complete
terom
parents: 34
diff changeset
   155
        throw NetworkBufferError("recv prefix overflow");   
32
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   156
    }
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   157
}
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   158
   
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   159
void NetworkBuffer::push_write (char *buf_ptr, size_t buf_size) {
31
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   160
    int ret;
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   161
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   162
    // try and short-circuit writes unless we have already buffered data
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   163
    if (offset == 0) {
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   164
        try {
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   165
            // attempt to send something
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   166
            ret = socket.send(buf_ptr, buf_size);
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   167
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   168
        } catch (CL_Error &e) {
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   169
            // ignore EAGAIN, detect this by setting ret to -1
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   170
            if (errno != EAGAIN)
38
4189b8bf3a5b kind of works
terom
parents: 37
diff changeset
   171
                throw NetworkSocketOSError(socket, "send");
31
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   172
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   173
            ret = -1;
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   174
        }
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   175
        
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   176
        // if we managed to send something, adjust buf/size and buffer
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   177
        if (ret > 0) {
37
ed2957490bbf compile step complete
terom
parents: 34
diff changeset
   178
            // sanity-check
ed2957490bbf compile step complete
terom
parents: 34
diff changeset
   179
            assert(buf_size >= (unsigned int) ret);
ed2957490bbf compile step complete
terom
parents: 34
diff changeset
   180
31
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   181
            buf_ptr += ret;
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   182
            buf_size -= ret;
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   183
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   184
            // if that was all, we're done
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   185
            if (buf_size == 0)
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   186
                return;
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   187
        }
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   188
    }
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   189
    
32
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   190
    // resize to fit buf_size more bytes
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   191
    resize(buf_size);
31
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   192
    
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   193
    // copy into our internal buffer
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   194
    memcpy(buf + offset, buf_ptr, buf_size);
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   195
}
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   196
        
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   197
void NetworkBuffer::flush_write (void) {
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   198
    int ret;
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   199
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   200
    // ignore if we don't have any data buffered
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   201
    if (offset == 0)
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   202
        return;
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   203
    
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   204
    // attempt to write as much as possible
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   205
    try {
37
ed2957490bbf compile step complete
terom
parents: 34
diff changeset
   206
        ret = socket.send(buf, offset);
31
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   207
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   208
    } catch (CL_Error &e) {
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   209
        // ignore EAGAIN and just return
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   210
        if (errno == EAGAIN)
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   211
            return;
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   212
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   213
        else
38
4189b8bf3a5b kind of works
terom
parents: 37
diff changeset
   214
            throw NetworkSocketOSError(socket, "send");
31
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   215
    }
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   216
32
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   217
    // trim the buffer
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   218
    trim(ret);
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   219
}
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   220
        
38
4189b8bf3a5b kind of works
terom
parents: 37
diff changeset
   221
void NetworkBuffer::write_prefix (char *buf, uint16_t prefix) {
4189b8bf3a5b kind of works
terom
parents: 37
diff changeset
   222
    uint16_t nval = htons(prefix);
4189b8bf3a5b kind of works
terom
parents: 37
diff changeset
   223
4189b8bf3a5b kind of works
terom
parents: 37
diff changeset
   224
    push_write((char*) &nval, sizeof(uint16_t)); 
32
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   225
    push_write(buf, prefix);
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   226
}
31
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   227
38
4189b8bf3a5b kind of works
terom
parents: 37
diff changeset
   228
void NetworkBuffer::write_prefix (char *buf, uint32_t prefix) {
4189b8bf3a5b kind of works
terom
parents: 37
diff changeset
   229
    uint32_t nval = htonl(prefix);
4189b8bf3a5b kind of works
terom
parents: 37
diff changeset
   230
4189b8bf3a5b kind of works
terom
parents: 37
diff changeset
   231
    push_write((char*) &nval, sizeof(uint32_t)); 
4189b8bf3a5b kind of works
terom
parents: 37
diff changeset
   232
    push_write(buf, prefix);
4189b8bf3a5b kind of works
terom
parents: 37
diff changeset
   233
}
31
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   234
37
ed2957490bbf compile step complete
terom
parents: 34
diff changeset
   235
NetworkTCPTransport::NetworkTCPTransport (NetworkSocket socket) :
ed2957490bbf compile step complete
terom
parents: 34
diff changeset
   236
    socket(socket), in(socket, NETWORK_TCP_INITIAL_IN_BUF), out(socket, NETWORK_TCP_INITIAL_OUT_BUF) {
31
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   237
    
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   238
    // connect signals
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   239
    slots.connect(socket.sig_read_triggered(), this, &NetworkTCPTransport::on_read);
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   240
    slots.connect(socket.sig_write_triggered(), this, &NetworkTCPTransport::on_write);
37
ed2957490bbf compile step complete
terom
parents: 34
diff changeset
   241
    slots.connect(socket.sig_disconnected(), this, &NetworkTCPTransport::on_disconnected);
31
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   242
}
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   243
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   244
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   245
void NetworkTCPTransport::on_read (void) {
32
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   246
    uint16_t prefix;
31
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   247
    NetworkPacket packet;
32
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   248
    
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   249
    // let the in stream read length-prefixed packets and pass them on to handle_packet
37
ed2957490bbf compile step complete
terom
parents: 34
diff changeset
   250
    while ((prefix = in.read_prefix<uint16_t>(packet.get_buf(), packet.get_buf_size())) > 0) {
32
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   251
        packet.set_data_size(prefix);
34
1ea6554d703e add even more uncompiled code
terom
parents: 33
diff changeset
   252
        _sig_packet(packet);
32
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   253
    }
31
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   254
}
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   255
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   256
void NetworkTCPTransport::on_write (void) {
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   257
    // just flush the output buffer
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   258
    out.flush_write();
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   259
}
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   260
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   261
void NetworkTCPTransport::on_disconnected (void) {
32
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   262
    // pass right through
34
1ea6554d703e add even more uncompiled code
terom
parents: 33
diff changeset
   263
    _sig_disconnect();
31
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   264
}
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   265
        
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   266
void NetworkTCPTransport::write_packet (const NetworkPacket &packet) {
32
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   267
    uint16_t prefix = packet.get_data_size();
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   268
    
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   269
    if (prefix != packet.get_data_size())
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   270
        throw CL_Error("send prefix overflow");
38
4189b8bf3a5b kind of works
terom
parents: 37
diff changeset
   271
    
4189b8bf3a5b kind of works
terom
parents: 37
diff changeset
   272
    try {
4189b8bf3a5b kind of works
terom
parents: 37
diff changeset
   273
        // just write to the output buffer
4189b8bf3a5b kind of works
terom
parents: 37
diff changeset
   274
        out.write_prefix((char *) packet.get_buf(), prefix);
32
2ff929186c90 write some mode code...
terom
parents: 31
diff changeset
   275
38
4189b8bf3a5b kind of works
terom
parents: 37
diff changeset
   276
    } catch (Error &e) {
4189b8bf3a5b kind of works
terom
parents: 37
diff changeset
   277
        const char *err = e.what();
4189b8bf3a5b kind of works
terom
parents: 37
diff changeset
   278
4189b8bf3a5b kind of works
terom
parents: 37
diff changeset
   279
        Engine::log(ERROR, "tcp.write_packet") << err;
4189b8bf3a5b kind of works
terom
parents: 37
diff changeset
   280
        
4189b8bf3a5b kind of works
terom
parents: 37
diff changeset
   281
        throw;    
4189b8bf3a5b kind of works
terom
parents: 37
diff changeset
   282
    }
31
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   283
}
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   284
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   285
NetworkTCPServer::NetworkTCPServer (const NetworkAddress &listen_addr) :
37
ed2957490bbf compile step complete
terom
parents: 34
diff changeset
   286
    socket(CL_Socket::tcp, CL_Socket::ipv4) {
31
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   287
    
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   288
    // bind
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   289
    socket.bind(listen_addr);
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   290
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   291
    // assign slots
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   292
    slots.connect(socket.sig_read_triggered(), this, &NetworkTCPServer::on_accept);
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   293
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   294
    // listen
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   295
    socket.listen(NETWORK_LISTEN_BACKLOG);
38
4189b8bf3a5b kind of works
terom
parents: 37
diff changeset
   296
    
4189b8bf3a5b kind of works
terom
parents: 37
diff changeset
   297
    // use nonblocking sockets
4189b8bf3a5b kind of works
terom
parents: 37
diff changeset
   298
    socket.set_nonblocking(true);
31
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   299
}
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   300
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   301
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   302
void NetworkTCPServer::on_accept (void) {
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   303
    // accept a new socket
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   304
    NetworkSocket client_sock = socket.accept();
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   305
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   306
    // create a new NetworkTCPTransport
33
e53f09b378f4 more untested, uncompiled code
terom
parents: 32
diff changeset
   307
    NetworkTCPTransport *client = buildTransport(client_sock);
e53f09b378f4 more untested, uncompiled code
terom
parents: 32
diff changeset
   308
        
31
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   309
    // let our user handle it
34
1ea6554d703e add even more uncompiled code
terom
parents: 33
diff changeset
   310
    _sig_client(client);
31
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   311
}
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   312
        
37
ed2957490bbf compile step complete
terom
parents: 34
diff changeset
   313
NetworkTCPTransport* NetworkTCPServer::buildTransport (CL_Socket &socket) {
ed2957490bbf compile step complete
terom
parents: 34
diff changeset
   314
    return new NetworkTCPTransport(socket);
33
e53f09b378f4 more untested, uncompiled code
terom
parents: 32
diff changeset
   315
}
e53f09b378f4 more untested, uncompiled code
terom
parents: 32
diff changeset
   316
        
31
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   317
NetworkTCPClient::NetworkTCPClient (const NetworkAddress &connect_addr) :
37
ed2957490bbf compile step complete
terom
parents: 34
diff changeset
   318
    NetworkTCPTransport(NetworkSocket(CL_Socket::tcp, CL_Socket::ipv4)) {
31
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   319
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   320
    // connect
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   321
    socket.connect(connect_addr);
38
4189b8bf3a5b kind of works
terom
parents: 37
diff changeset
   322
    
4189b8bf3a5b kind of works
terom
parents: 37
diff changeset
   323
    // use nonblocking sockets
4189b8bf3a5b kind of works
terom
parents: 37
diff changeset
   324
    socket.set_nonblocking(true);
31
d0d7489d4e8b add initial code written so far
terom
parents:
diff changeset
   325
}