| summaryrefslogtreecommitdiff |
diff options
Diffstat (limited to 'src/io/network.c')
| -rw-r--r-- | src/io/network.c | 417 |
1 files changed, 213 insertions, 204 deletions
diff --git a/src/io/network.c b/src/io/network.c index c8d05a2..d2797c9 100644 --- a/src/io/network.c +++ b/src/io/network.c @@ -13,10 +13,10 @@ #include "network.h" -static int reconnect (struct ZoO_network net [const restrict static 1]) +static int re_create_socket (struct ZoO_network net [const restrict static 1]) { struct timeval timeout; - int old_errno = errno; + const int old_errno = errno; errno = 0; timeout.tv_sec = ZoO_NETWORK_TIMEOUT; @@ -37,19 +37,11 @@ static int reconnect (struct ZoO_network net [const restrict static 1]) if (net->connection == -1) { - ZoO_FATAL - ( - "Could not create socket: %s.", - strerror(errno) - ); + ZoO_ERROR("Could not create socket: %s.", strerror(errno)); - errno = old_errno; - - return -1; + goto RETURN_FAILED; } - errno = 0; - if ( ( @@ -77,13 +69,9 @@ static int reconnect (struct ZoO_network net [const restrict static 1]) { ZoO_ERROR("Could not set timeout on network socket: %s", strerror(errno)); - errno = old_errno; - - return -1; + goto RETURN_FAILED; } - errno = old_errno; - ZoO_S_DEBUG(ZoO_DEBUG_NETWORK, "(Re)connecting to network..."); if @@ -96,73 +84,67 @@ static int reconnect (struct ZoO_network net [const restrict static 1]) ) != 0 ) { - ZoO_ERROR - ( - "Unable to connect to the network: %s", - strerror(errno) - ); + ZoO_ERROR("Could not establish connection: %s", strerror(errno)); - errno = old_errno; - - return -1; + goto RETURN_FAILED; } errno = old_errno; - snprintf - ( - net->msg, - 512, - "USER %s 8 * :%s\r\n", - net->user, - net->name - ); + return 0; - errno = 0; +RETURN_FAILED: + errno = old_errno; - if (write(net->connection, net->msg, strlen(net->msg)) < 1) - { - ZoO_ERROR - ( - "Unable to write to the network: %s", - strerror(errno) - ); + return -1; +} - errno = old_errno; +static int reconnect (struct ZoO_network net [const restrict static 1]) +{ + const int old_errno = errno; + memset(net->in, 0, (sizeof(ZoO_char) * 513)); + memset(net->out, 0, (sizeof(ZoO_char) * 513)); + memset(net->buffer, 0, (sizeof(ZoO_char) * 513)); + + if (re_create_socket(net) < 0) + { return -1; } - snprintf - ( - net->msg, - 512, - "NICK %s\r\n", - net->nick - ); - - errno = 0; + snprintf(net->out, 512, "USER %s 8 * :%s\r\n", net->user, net->name); - if (write(net->connection, net->msg, strlen(net->msg)) < 1) + if (write(net->connection, net->out, strlen(net->out)) < 1) { - ZoO_ERROR - ( - "Unable to write to the network: %s", - strerror(errno) - ); + goto RETURN_WRITE_FAILED; + } - errno = old_errno; + snprintf(net->out, 512, "NICK %s\r\n", net->nick); - return -1; + if (write(net->connection, net->out, strlen(net->out)) < 1) + { + goto RETURN_WRITE_FAILED; } - errno = old_errno; - net->buffer_remaining = 0; net->buffer_index = 0; + ZoO_S_DEBUG(ZoO_DEBUG_NETWORK, "(Re)connected."); + errno = old_errno; + return 0; + +RETURN_WRITE_FAILED: + ZoO_ERROR + ( + "Unable to write to the network: %s", + strerror(errno) + ); + + errno = old_errno; + + return -1; } int ZoO_network_connect @@ -189,7 +171,9 @@ int ZoO_network_connect net->buffer_remaining = 0; memset(&hints, 0, sizeof(struct addrinfo)); - memset(net->msg, 0, (sizeof(ZoO_char) * 513)); + memset(net->in, 0, (sizeof(ZoO_char) * 513)); + memset(net->out, 0, (sizeof(ZoO_char) * 513)); + memset(net->buffer, 0, (sizeof(ZoO_char) * 513)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; @@ -222,215 +206,240 @@ int ZoO_network_connect return -1; } - errno = 0; - + errno = old_errno; reconnect(net); return 0; } -int ZoO_network_receive +static void buffer_msg ( - struct ZoO_network net [const restrict static 1], - size_t msg_offset [const restrict static 1], - size_t msg_size [const restrict static 1] + struct ZoO_network net [const static 1] ) { - int old_errno; - ssize_t in_count, in_index, msg_index, cmd; + ssize_t in_count, i; - old_errno = errno; + if (net->buffer_remaining > 0) + { + in_count = net->buffer_remaining; + net->buffer_remaining = 0; + + goto PARSE_READ; + } - for (;;) +READ_MORE: + in_count = read(net->connection, net->buffer, 512); + + if (in_count < 0) { - msg_index = 0; + ZoO_ERROR("Could not read from network: %s", strerror(errno)); + + reconnect(net); - errno = 0; + goto READ_MORE; + } + +PARSE_READ: + for (i = 0; i < in_count; ++i) + { + net->in[net->buffer_index] = net->buffer[i]; - while + if ( - ( - (in_count = - read( - net->connection, - (net->buffer + net->buffer_index), - (512 - net->buffer_index) - ) - ) > 0 - ) + (net->buffer_index > 0) + && (net->in[net->buffer_index - 1] == '\r') + && (net->in[net->buffer_index] == '\n') ) { - net->buffer_remaining += in_count; + net->buffer_remaining = (in_count - (i + 1)); + net->in_length = (net->buffer_index - 1); + net->buffer_index = 0; - for - ( - in_index = 0; - in_index < net->buffer_remaining; - ++in_index - ) + if (net->buffer_remaining > 0) { - net->msg[msg_index] = net->buffer[net->buffer_index + in_index]; - - if + memmove ( - (msg_index == 511) - || - ( - (msg_index > 0) - && (net->msg[msg_index - 1] == '\r') - && (net->msg[msg_index] == '\n') - ) - ) - { - net->msg[msg_index + 1] = '\0'; + (void *) net->buffer, + (const void *) (net->buffer + (i + 1)), + net->buffer_remaining + ); + } + return; + } - if (net->buffer_index != net->buffer_remaining) - { - memmove - ( - net->buffer, - (net->buffer + net->buffer_index), - (size_t) net->buffer_remaining - ); + net->buffer_index += 1; - net->buffer_index = 0; - } + if (net->buffer_index > 512) + { + ZoO_S_WARNING("Incoming message is too long. Discarded."); - net->buffer_remaining -= (in_index + 1); + net->buffer_index = 0; + net->buffer_remaining = 0; - errno = old_errno; + break; + } + } - goto READ_MSG; - } + goto READ_MORE; +} - ++msg_index; - } +void handle_ping (struct ZoO_network net [const restrict static 1]) +{ + const int old_errno = errno; - net->buffer_remaining = 0; - net->buffer_index = 0; + #if ZoO_DEBUG_NETWORK_PING == 1 + net->in[net->in_length] = '\0'; - errno = 0; - } + ZoO_DEBUG(ZoO_DEBUG_NETWORK, "[NET->in] %s", net->in); - ZoO_ERROR - ( - "Something went wrong while trying to read from the network: %s.", - strerror(errno) - ); + net->in[net->in_length] = '\r'; + #endif + + net->in[1] = 'O'; + + errno = 0; + + if (write(net->connection, net->in, (net->in_length + 2)) < 1) + { + ZoO_ERROR("Could not reply to PING request: %s", strerror(errno)); errno = old_errno; - if (reconnect(net) < 0) + while (reconnect(net) < 0) { - return -1; + sleep(5); } - continue; + return; + } - READ_MSG: + errno = old_errno; - ZoO_DEBUG(ZoO_DEBUG_NETWORK, "[NET->in] %s\n", net->msg); +#if ZoO_DEBUG_NETWORK_PING == 1 + net->in[net->in_length] = '\0'; - /* XXX: doesn't that prevent net [restrict]? */ - if (ZoO_IS_PREFIX("PING", net->msg)) - { - errno = 0; + ZoO_DEBUG(ZoO_DEBUG_NETWORK, "[NET->out] %s", net->in); +#endif - net->msg[1] = 'O'; +} - if (write(net->connection, net->msg, strlen(net->msg)) < 1) - { - ZoO_ERROR("Could not reply to PING request: %s", strerror(errno)); +int ZoO_network_receive +( + struct ZoO_network net [const restrict static 1], + size_t msg_offset [const restrict static 1], + size_t msg_size [const restrict static 1], + enum ZoO_msg_type type [const restrict static 1] +) +{ + const int old_errno = errno; + ssize_t cmd, i; - errno = old_errno; +READ_NEW_MSG: + buffer_msg(net); - if (reconnect(net) < 0) - { - return -1; - } + net->in[net->in_length + 2] = '\0'; - continue; - } + /* XXX: doesn't that prevent net [restrict]? */ + if (ZoO_IS_PREFIX("PING", net->in)) + { - ZoO_DEBUG(ZoO_DEBUG_NETWORK, "[NET->out] %s\n", net->msg); + handle_ping(net); - errno = old_errno; - } - else if (net->msg[0] == ':') - { - cmd = 0; + goto READ_NEW_MSG; + } - for (in_index = 1; in_index < 512; in_index++) - { - if (net->msg[in_index] == ' ') - { - cmd = (in_index + 1); + if (net->in_length == 0) + { + goto READ_NEW_MSG; + } - break; - } - } + net->in[net->in_length] = '\0'; + + ZoO_DEBUG(ZoO_DEBUG_NETWORK, "[NET->in] %s", net->in); + + if (net->in[0] == ':') + { + cmd = 0; - if (cmd == 0) + for (i = 1; i < 512; i++) + { + if (net->in[i] == ' ') { - continue; + cmd = (i + 1); + + break; } + } + + if (ZoO_IS_PREFIX("001", (net->in + cmd))) + { + snprintf + ( + net->out, + 512, + "JOIN :%s\r\n", + net->channel + ); - if (ZoO_IS_PREFIX("001", (net->msg + cmd))) + errno = 0; + + if (write(net->connection, net->out, strlen(net->out)) < 1) { - snprintf + ZoO_ERROR ( - net->msg, - 512, - "JOIN :%s\r\n", - net->channel + "Could not send JOIN request: %s", + strerror(errno) ); - errno = 0; + errno = old_errno; - if (write(net->connection, net->msg, strlen(net->msg)) < 1) + if (reconnect(net) < 0) { - ZoO_ERROR - ( - "Could not send JOIN request: %s", - strerror(errno) - ); - - errno = old_errno; - - if (reconnect(net) < 0) - { - return -1; - } + return -1; } + } - ZoO_DEBUG(ZoO_DEBUG_NETWORK, "[NET->out] %s", net->msg); + errno = old_errno; - continue; - } + ZoO_DEBUG(ZoO_DEBUG_NETWORK, "[NET->out] %s", net->out); - if (ZoO_IS_PREFIX("PRIVMSG", (net->msg + cmd))) + goto READ_NEW_MSG; + } + + if (ZoO_IS_PREFIX("JOIN", (net->in + cmd))) + { + *type = ZoO_JOIN; + + return 0; + } + + if (ZoO_IS_PREFIX("PRIVMSG", (net->in + cmd))) + { + + for (; i < 512; i++) { - for (; in_index < 512; in_index++) + if (net->in[i] == ':') { - if (net->msg[in_index] == ':') - { - cmd = (in_index + 1); + cmd = (i + 1); - break; - } + break; } + } - *msg_offset = cmd; - *msg_size = (msg_index - *msg_offset - 1); + *msg_offset = cmd; + *msg_size = (net->in_length - cmd); - /*net->msg[*msg_size - 1] = '\0'; */ + /*net->in[*msg_size - 1] = '\0'; */ - return 0; - } + *type = ZoO_PRIVMSG; + + return 0; } } + + goto READ_NEW_MSG; } int ZoO_network_send (struct ZoO_network net [const restrict static 1]) @@ -439,16 +448,16 @@ int ZoO_network_send (struct ZoO_network net [const restrict static 1]) snprintf ( - net->buffer, + net->in, 512, "PRIVMSG %s :%s\r\n", net->channel, - net->msg + net->out ); errno = 0; - if (write(net->connection, net->buffer, strlen(net->buffer)) < 1) + if (write(net->connection, net->in, strlen(net->in)) < 1) { ZoO_ERROR ( @@ -470,7 +479,7 @@ int ZoO_network_send (struct ZoO_network net [const restrict static 1]) errno = old_errno; - ZoO_DEBUG(ZoO_DEBUG_NETWORK, "[NET->out] %s", net->buffer); + ZoO_DEBUG(ZoO_DEBUG_NETWORK, "[NET->out] %s", net->in); return 0; } |


