X-Git-Url: http://git.code-monkey.de/?p=umurmur.git;a=blobdiff_plain;f=src%2Fclient.c;h=b69da172cc51324bf87701bbe698d035fa321b55;hp=dc8b1c2d330aa93de0f6851f1daae8252eaf4810;hb=aa21dde5fbd77ecefb946961ea2231d31d8f8e3b;hpb=f437c88e9885c332a11fce2babc53c22dfd6e86e diff --git a/src/client.c b/src/client.c index dc8b1c2..b69da17 100644 --- a/src/client.c +++ b/src/client.c @@ -36,6 +36,7 @@ #include #include #include "log.h" +#include "memory.h" #include "list.h" #include "client.h" #include "ssl.h" @@ -46,12 +47,14 @@ #include "version.h" #include "voicetarget.h" #include "ban.h" +#include "util.h" extern char system_string[], version_string[]; static int Client_read(client_t *client); static int Client_write(client_t *client); static int Client_send_udp(client_t *client, uint8_t *data, int len); +static client_t *Client_find_by_fd(int fd); void Client_free(client_t *client); declare_list(clients); @@ -63,6 +66,7 @@ int iCodecAlpha, iCodecBeta; bool_t bPreferAlpha; extern int* udpsocks; +extern bool_t hasv4; void Client_init() { @@ -113,9 +117,7 @@ void Client_janitor() void Client_codec_add(client_t *client, int codec) { - codec_t *cd = malloc(sizeof(codec_t)); - if (cd == NULL) - Log_fatal("Out of memory"); + codec_t *cd = Memory_safeMalloc(1, sizeof(codec_t)); init_list_entry(&cd->node); cd->codec = codec; list_add_tail(&cd->node, &client->codecs); @@ -155,9 +157,7 @@ void Client_token_add(client_t *client, char *token_string) if (client->tokencount >= MAX_TOKENS) return; - token = malloc(sizeof(token_t)); - if (token == NULL) - Log_fatal("Out of memory"); + token = Memory_safeMalloc(1, sizeof(token_t)); init_list_entry(&token->node); token->token = strdup(token_string); if (token->token == NULL) @@ -166,7 +166,7 @@ void Client_token_add(client_t *client, char *token_string) client->tokencount++; } -bool_t Client_token_match(client_t *client, char *str) +bool_t Client_token_match(client_t *client, char const *str) { token_t *token; struct dlist *itr; @@ -225,10 +225,7 @@ void recheckCodecVersions(client_t *connectingClient) } } if (!found) { - cd = malloc(sizeof(codec_t)); - if (!cd) - Log_fatal("Out of memory"); - memset(cd, 0, sizeof(codec_t)); + cd = Memory_safeCalloc(1, sizeof(codec_t)); init_list_entry(&cd->node); cd->codec = codec_itr->codec; cd->count = 1; @@ -321,32 +318,24 @@ int Client_add(int fd, struct sockaddr_storage *remote) { client_t* newclient; message_t *sendmsg; - char addressPresentation[INET6_ADDRSTRLEN]; - int port; - - if(remote->ss_family == AF_INET) { - inet_ntop(AF_INET, &((struct sockaddr_in*)remote)->sin_addr, addressPresentation, INET6_ADDRSTRLEN); - port = ntohs(((struct sockaddr_in*)remote)->sin_port); - } else { - inet_ntop(AF_INET6, &((struct sockaddr_in6*)remote)->sin6_addr, addressPresentation, INET6_ADDRSTRLEN); - port = ntohs(((struct sockaddr_in6*)remote)->sin6_port); - } + char* addressString = NULL; if (Ban_isBannedAddr(remote)) { - Log_info("Address %s banned. Disconnecting", addressPresentation); + addressString = Util_addressToString(remote); + Log_info("Address %s banned. Disconnecting", addressString); + free(addressString); return -1; } - if ((newclient = calloc(1, sizeof(client_t))) == NULL) - Log_fatal("Out of memory (%s:%s)", __FILE__, __LINE__); - - memcpy(newclient->addressString, addressPresentation, INET6_ADDRSTRLEN); + newclient = Memory_safeCalloc(1, sizeof(client_t)); newclient->tcpfd = fd; memcpy(&newclient->remote_tcp, remote, sizeof(struct sockaddr_storage)); newclient->ssl = SSLi_newconnection(&newclient->tcpfd, &newclient->SSLready); if (newclient->ssl == NULL) { - Log_warn("SSL negotiation failed with %s on port %d", addressPresentation, port); + addressString = Util_addressToString(remote); + Log_warn("SSL negotiation failed with %s on port %d", addressString, Util_addressToPort(remote)); + free(addressString); free(newclient); return -1; } @@ -411,16 +400,12 @@ void Client_free(client_t *client) SSLi_free(client->ssl); close(client->tcpfd); clientcount--; - if (client->release) - free(client->release); - if (client->os) - free(client->os); - if (client->os_version) - free(client->os_version); - if (client->username) - free(client->username); - if (client->context) - free(client->context); + + free(client->release); + free(client->os); + free(client->os_version); + free(client->username); + free(client->context); free(client); if (authenticatedLeft) @@ -442,17 +427,42 @@ void Client_disconnect_all() } } -int Client_read_fd(int fd) +client_t *Client_find_by_session(int session_id) { struct dlist *itr; - client_t *client = NULL; list_iterate(itr, &clients) { - if (fd == list_get_entry(itr, client_t, node)->tcpfd) { - client = list_get_entry(itr, client_t, node); - break; + client_t *client = list_get_entry(itr, client_t, node); + + if (client->sessionId == session_id) { + return client; } } + + return NULL; +} + +client_t *Client_find_by_fd(int fd) +{ + struct dlist *itr; + + list_iterate(itr, &clients) { + client_t *client = list_get_entry(itr, client_t, node); + + if (client->tcpfd == fd) { + return client; + } + } + + return NULL; +} + +int Client_read_fd(int fd) +{ + client_t *client; + + client = Client_find_by_fd(fd); + if (client != NULL) return Client_read(client); else @@ -554,15 +564,10 @@ int Client_read(client_t *client) int Client_write_fd(int fd) { - struct dlist *itr; - client_t *client = NULL; + client_t *client; + + client = Client_find_by_fd(fd); - list_iterate(itr, &clients) { - if(fd == list_get_entry(itr, client_t, node)->tcpfd) { - client = list_get_entry(itr, client_t, node); - break; - } - } if (client != NULL) return Client_write(client); else @@ -623,6 +628,7 @@ int Client_send_message_ver(client_t *client, message_t *msg, uint32_t version) return Client_send_message(client, msg); else Msg_free(msg); + return -1; } int Client_send_message(client_t *client, message_t *msg) @@ -673,24 +679,24 @@ client_t *Client_iterate(client_t **client_itr) return c; } -void Client_textmessage(client_t *client, char *text) +void Client_textmessage(client_t *client, const char *text) { char *message; uint32_t *tree_id; message_t *sendmsg = NULL; - message = malloc(strlen(text) + 1); - if (!message) - Log_fatal("Out of memory"); - tree_id = malloc(sizeof(uint32_t)); - if (!tree_id) + message = strdup(text); + + if (message == NULL) Log_fatal("Out of memory"); + + tree_id = Memory_safeMalloc(1, sizeof(uint32_t)); *tree_id = 0; sendmsg = Msg_create(TextMessage); sendmsg->payload.textMessage->message = message; sendmsg->payload.textMessage->n_tree_id = 1; sendmsg->payload.textMessage->tree_id = tree_id; - strcpy(message, text); + Client_send_message(client, sendmsg); } @@ -698,22 +704,15 @@ void Client_textmessage(client_t *client, char *text) int Client_send_message_except(client_t *client, message_t *msg) { client_t *itr = NULL; - int count = 0; - Msg_inc_ref(msg); /* Make sure a reference is held during the whole iteration. */ while (Client_iterate(&itr) != NULL) { if (itr != client) { - if (count++ > 0) - Msg_inc_ref(msg); /* One extra reference for each new copy */ + Msg_inc_ref(msg); /* One extra reference for each new copy */ Log_debug("Msg %d to %s refcount %d", msg->messageType, itr->username, msg->refcount); Client_send_message(itr, msg); } } - Msg_free(msg); /* Free our reference to the message */ - - if (count == 0) - Msg_free(msg); /* If only 1 client is connected then no message is passed - * to Client_send_message(). Free it here. */ + Msg_free(msg); /* Consume caller's reference. */ return 0; } @@ -721,22 +720,15 @@ int Client_send_message_except(client_t *client, message_t *msg) int Client_send_message_except_ver(client_t *client, message_t *msg, uint32_t version) { client_t *itr = NULL; - int count = 0; - Msg_inc_ref(msg); /* Make sure a reference is held during the whole iteration. */ while (Client_iterate(&itr) != NULL) { if (itr != client) { - if (count++ > 0) - Msg_inc_ref(msg); /* One extra reference for each new copy */ + Msg_inc_ref(msg); /* One extra reference for each new copy */ Log_debug("Msg %d to %s refcount %d", msg->messageType, itr->username, msg->refcount); Client_send_message_ver(itr, msg, version); } } - Msg_free(msg); /* Free our reference to the message */ - - if (count == 0) - Msg_free(msg); /* If only 1 client is connected then no message is passed - * to Client_send_message(). Free it here. */ + Msg_free(msg); /* Consume caller's reference. */ return 0; } @@ -784,34 +776,30 @@ int Client_read_udp(int udpsock) memset(key, 0, KEY_LENGTH); + fromport = Util_addressToPort(&from); + if(from.ss_family == AF_INET) { memcpy(fromaddress, &((struct sockaddr_in*)&from)->sin_addr, sizeof(in_addr_t)); - fromport = ntohs(((struct sockaddr_in*)&from)->sin_port); memcpy(&key[0], &fromport, 2); memcpy(&key[2], fromaddress, sizeof(in_addr_t)); } else { memcpy(fromaddress, &((struct sockaddr_in6*)&from)->sin6_addr, 4 * sizeof(in_addr_t)); - fromport = ntohs(((struct sockaddr_in6*)&from)->sin6_port); memcpy(&key[0], &fromport, 2); memcpy(&key[2], fromaddress, 4 * sizeof(in_addr_t)); } - if (len == 0) { - return -1; - } else if (len < 0) { + if (len <= 0) return -1; - } else if (len < 5) { - // 4 bytes crypt header + type + session - return 0; - } else if (len > UDP_PACKET_SIZE) { + else if (len < 5 || len > UDP_PACKET_SIZE) /* 4 bytes crypt header + type + session */ return 0; - } - /* Ping packet */ + /* + * Reply to ping packet + * The second and third uint32_t are the timestamp, which will be returned unmodified + */ if (len == 12 && *encrypted == 0) { uint32_t *ping = (uint32_t *)encrypted; ping[0] = htonl((uint32_t)PROTOCOL_VERSION); - // 1 and 2 will be the timestamp, which we return unmodified. ping[3] = htonl((uint32_t)clientcount); ping[4] = htonl((uint32_t)getIntConf(MAX_CLIENTS)); ping[5] = htonl((uint32_t)getIntConf(MAX_BANDWIDTH)); @@ -847,7 +835,9 @@ int Client_read_udp(int udpsock) if (memcmp(itraddress, fromaddress, addresslength) == 0) { if (checkDecrypt(itr, encrypted, buffer, len)) { memcpy(itr->key, key, KEY_LENGTH); - Log_info_client(itr, "New UDP connection from %s on port %d", itr->addressString, fromport); + char* clientAddressString = Util_clientAddressToString(itr); + Log_info_client(itr, "New UDP connection from %s on port %d", clientAddressString, fromport); + free(clientAddressString); memcpy(&itr->remote_udp, &from, sizeof(struct sockaddr_storage)); break; } @@ -861,6 +851,9 @@ int Client_read_udp(int udpsock) itr->bUDP = true; len -= 4; /* Adjust for crypt header */ msgType = (UDPMessageType_t)((buffer[0] >> 5) & 0x7); + + char *clientAddressString = NULL; + switch (msgType) { case UDPVoiceSpeex: case UDPVoiceCELTAlpha: @@ -875,7 +868,9 @@ int Client_read_udp(int udpsock) Client_send_udp(itr, buffer, len); break; default: - Log_debug("Unknown UDP message type from %s port %d", itr->addressString, fromport); + clientAddressString = Util_clientAddressToString(itr); + Log_debug("Unknown UDP message type from %s port %d", clientAddressString, fromport); + free(clientAddressString); break; } @@ -907,7 +902,7 @@ int Client_voiceMsg(client_t *client, uint8_t *data, int len) int offset, packetsize; voicetarget_t *vt; - channel_t *ch = (channel_t *)client->channel; + channel_t *ch = client->channel; struct dlist *itr; if (!client->authenticated || client->mute || client->self_mute || ch->silent) @@ -971,8 +966,10 @@ int Client_voiceMsg(client_t *client, uint8_t *data, int len) if (vt->channels[i].linked && !list_empty(&ch->channel_links)) { struct dlist *ch_itr; list_iterate(ch_itr, &ch->channel_links) { + channellist_t *chl; channel_t *ch_link; - ch_link = list_get_entry(ch_itr, channel_t, link_node); + chl = list_get_entry(ch_itr, channellist_t, node); + ch_link = chl->chan; list_iterate(itr, &ch_link->clients) { client_t *c; c = list_get_entry(itr, client_t, chan_node); @@ -1001,7 +998,7 @@ int Client_voiceMsg(client_t *client, uint8_t *data, int len) } /* Sessions */ for (i = 0; i < TARGET_MAX_SESSIONS && vt->sessions[i] != -1; i++) { - client_t *c; + client_t *c = NULL; buffer[0] = (uint8_t) (type | 2); Log_debug("Whisper session %d", vt->sessions[i]); while (Client_iterate(&c) != NULL) { @@ -1022,25 +1019,17 @@ out: static int Client_send_udp(client_t *client, uint8_t *data, int len) { uint8_t *buf, *mbuf; - uint16_t clientport; - int udpsock = (client->remote_udp.ss_family == AF_INET) ? udpsocks[0] : udpsocks[1]; - if (client->remote_udp.ss_family == AF_INET) - clientport = ntohs(((struct sockaddr_in*)&client->remote_udp)->sin_port); - else - clientport = ntohs(((struct sockaddr_in6*)&client->remote_udp)->sin6_port); + int udpsock = (client->remote_udp.ss_family == AF_INET) ? udpsocks[0] : udpsocks[(hasv4) ? 1 : 0]; - if (clientport != 0 && CryptState_isValid(&client->cryptState) && + if (Util_clientAddressToPortUDP(client) != 0 && CryptState_isValid(&client->cryptState) && client->bUDP) { #if defined(__LP64__) - buf = mbuf = malloc(len + 4 + 16); + buf = mbuf = Memory_safeMalloc(1, len + 4 + 16); buf += 4; #else - mbuf = buf = malloc(len + 4); + mbuf = buf = Memory_safeMalloc(1, len + 4); #endif - if (mbuf == NULL) - Log_fatal("Out of memory"); - CryptState_encrypt(&client->cryptState, data, buf, len); #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__APPLE__)