--- /dev/null
+include $(TOPDIR)/rules.mk
+
+# Name and release number of this package
+PKG_NAME:=umurmur
+PKG_VERSION:=0.1.1
+PKG_RELEASE:=4
+
+
+PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
+
+include $(INCLUDE_DIR)/package.mk
+
+
+define Package/umurmur
+ SECTION:=net
+ CATEGORY:=Network
+ TITLE:=uMurmur
+ DEPENDS:=+libopenssl +libconfig
+endef
+
+
+# Uncomment portion below for Kamikaze and delete DESCRIPTION variable above
+define Package/umurmur/description
+ Minimalistic Mumble server daemon.
+endef
+
+TARGET_CFLAGS := \
+ -DWRT_TARGET \
+ $(TARGET_CFLAGS)
+
+define Build/Prepare
+ mkdir -p $(PKG_BUILD_DIR)
+ $(CP) ./src/* $(PKG_BUILD_DIR)/
+endef
+
+define Build/CompileTarget
+ CFLAGS="$(TARGET_CFLAGS)" LDFLAGS="$(TARGET_LDFLAGS)"\
+ $(MAKE) -C $(PKG_BUILD_DIR)/umurmur.$(1)/umurmur \
+ all
+endef
+
+define Package/umurmur/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/umurmurd $(1)/usr/bin/
+ $(INSTALL_DIR) $(1)/etc
+ $(INSTALL_BIN) ./files/umurmur.conf $(1)/etc/umurmur.conf
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) ./files/umurmur.init $(1)/etc/init.d/umurmur
+ $(INSTALL_DIR) $(1)/etc/umurmur
+endef
+
+$(eval $(call BuildPackage,umurmur))
+
--- /dev/null
+max_bandwidth = 5000;
+welcometext = "Welcome to uMurmur!";
+certificate = "/etc/umurmur/cert.crt";
+private_key = "/etc/umurmur/key.key";
+password = "";
+max_users = 10;
+
+# Root channel must always be defined first.
+# If a channel has a parent, the parent must be defined before the child channel(s).
+channels = ( {
+ name = "Root";
+ parent = "";
+ description = "The Root of all channels";
+ },
+ {
+ name = "Lobby";
+ parent = "Root";
+ description = "Lobby channel";
+ },
+ {
+ name = "Red team";
+ parent = "Lobby";
+ description = "The Red team channel";
+ },
+ {
+ name = "Blue team";
+ parent = "Lobby";
+ description = "The Blue team channel";
+ }
+);
+default_channel = "COH";
--- /dev/null
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2006-2008 OpenWrt.org
+
+START=90
+
+PIDFILE="/var/run/umurmurd.pid"
+
+start() {
+ stop
+ /usr/bin/umurmurd -p $PIDFILE
+}
+
+stop() {
+ [ -f "$PIDFILE" ] && kill $(cat "$PIDFILE") 2>/dev/null >/dev/null
+}
\ No newline at end of file
--- /dev/null
+# build helloworld executable when user executes "make"
+
+SRCS:=client.c main.c messages.c pds.c server.c ssl.c log.c conf.c crypt.c timer.c messagehandler.c channel.c
+OBJS:=$(patsubst %.c, %.o, $(SRCS))
+CFLAGS:=$(CFLAGS) -Wall -Os -g
+LDFLAGS:=$(LDFLAGS) -lcrypto -lssl -lconfig
+
+umurmurd:$(OBJS) depend.mak
+ $(CC) $(LDFLAGS) $(OBJS) -o umurmurd
+
+# remove object files and executable when user executes "make clean"
+clean:
+ rm *.o umurmurd
+
+all: umurmur
+
+$(OBJS): Makefile
+
+depend.mak:
+ $(CC) -M $(SRCS) > depend.mak
+
+include depend.mak
\ No newline at end of file
--- /dev/null
+/* Copyright (C) 2009, Martin Johansson <martin@fatbob.nu>
+ Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ - Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ - Neither the name of the Developers nor the names of its contributors may
+ be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#include "log.h"
+#include "list.h"
+#include "client.h"
+#include "channel.h"
+#include "conf.h"
+
+
+static int nextchanId;
+static channel_t *rootChan;
+channel_t *defaultChan;
+declare_list(channels); /* A flat list of the channels */
+
+static channel_t *createChannel(int id, const char *name, const char *desc)
+{
+ channel_t *ch;
+
+ ch = malloc(sizeof(channel_t));
+ if (ch == NULL)
+ Log_fatal("out of memory");
+ memset(ch, 0, sizeof(channel_t));
+ ch->id = id;
+ strncpy(ch->name, name, MAX_TEXT);
+ strncpy(ch->desc, desc, MAX_TEXT);
+ init_list_entry(&ch->subs);
+ init_list_entry(&ch->node);
+ init_list_entry(&ch->clients);
+ init_list_entry(&ch->flatlist_node);
+ return ch;
+}
+
+#if 0
+/* Might be used when tree travesal becomes neccessary */
+static channel_t *first_subchannel(channel_t *ch)
+{
+ if (list_empty(&ch->subs))
+ return NULL;
+ else
+ return list_get_entry(list_get_first(&ch->subs), channel_t, node);
+}
+
+static channel_t *next_channel(channel_t *ch)
+{
+ if (list_get_next(&ch->node) == &list_get_entry(&ch->node, channel_t, node)->parent->subs)
+ return NULL;
+ else
+ return list_get_entry(list_get_next(&ch->node), channel_t, node);
+}
+#endif
+
+void Chan_iterate(channel_t **channelpptr)
+{
+ channel_t *ch = *channelpptr;
+
+ if (!list_empty(&channels)) {
+ if (ch == NULL)
+ ch = list_get_entry(list_get_first(&channels), channel_t, flatlist_node);
+ else {
+ if (list_get_next(&ch->flatlist_node) == &channels)
+ ch = NULL;
+ else
+ ch = list_get_entry(list_get_next(&ch->flatlist_node), channel_t, flatlist_node);
+ }
+ if (ch)
+ Log_debug("Channel %d", ch->id);
+ }
+
+ *channelpptr = ch;
+}
+
+void Chan_init()
+{
+ int i;
+ conf_channel_t chdesc;
+ const char *defaultChannelName;
+
+ defaultChannelName = getStrConf(DEAFULT_CHANNEL);
+
+ for (i = 0; ; i++) {
+ if (Conf_getNextChannel(&chdesc, i) < 0) {
+ if (i == 0)
+ Log_fatal("No valid channels found in configuration file. Exiting.");
+ break;
+ }
+ if (i == 0) {
+ rootChan = createChannel(0, chdesc.name, chdesc.description);
+ list_add_tail(&rootChan->flatlist_node, &channels);
+ if (strcmp(defaultChannelName, chdesc.name) == 0)
+ defaultChan = rootChan;
+ }
+ else {
+ channel_t *ch, *ch_itr = NULL;
+ ch = Chan_createChannel(chdesc.name, chdesc.description);
+
+ if (strcmp(defaultChannelName, chdesc.name) == 0) {
+ Log_info("Setting default channel %s", ch->name);
+ defaultChan = ch;
+ }
+
+ do {
+ Chan_iterate(&ch_itr);
+ } while (ch_itr != NULL && strcmp(ch_itr->name, chdesc.parent) != 0);
+
+ if (ch_itr == NULL)
+ Log_fatal("Error in channel configuration: parent not found");
+ else {
+ Chan_addChannel(ch_itr, ch);
+ Log_info("Adding channel %s parent %s", ch->name, chdesc.parent);
+ }
+ }
+ }
+ if (defaultChan == NULL)
+ defaultChan = rootChan;
+}
+
+void Chan_free()
+{
+ struct dlist *itr, *save;
+
+ list_iterate_safe(itr, save, &channels) {
+ Log_debug("Free channel %s", list_get_entry(itr, channel_t, flatlist_node)->name);
+ free(list_get_entry(itr, channel_t, flatlist_node));
+ }
+}
+
+channel_t *Chan_createChannel(const char *name, const char *desc)
+{
+ /* Get an ID */
+ nextchanId += 1;
+ return createChannel(nextchanId, name, desc);
+}
+
+void Chan_freeChannel(channel_t *ch)
+{
+ list_del(&ch->node);
+ list_del(&ch->flatlist_node);
+ free(ch);
+}
+
+void Chan_addChannel(channel_t *parent, channel_t *ch)
+{
+ list_add_tail(&ch->node, &parent->subs);
+ ch->parent = parent;
+ list_add_tail(&ch->flatlist_node, &channels);
+}
+
+
+void Chan_playerJoin(channel_t *ch, client_t *client)
+{
+ /* Only allowed in one channel at a time */
+ Log_debug("Add player %s to channel %s", client->playerName, ch->name);
+
+ if (client->channel)
+ list_del(&client->chan_node);
+ list_add_tail(&client->chan_node, &ch->clients);
+ client->channel = (void *)ch;
+
+}
+
+void Chan_playerJoin_id(int channelid, client_t *client)
+{
+ channel_t *ch_itr = NULL;
+ do {
+ Chan_iterate(&ch_itr);
+ } while (ch_itr != NULL && ch_itr->id != channelid);
+ if (ch_itr == NULL)
+ Log_warn("Channel id %d not found - ignoring.", channelid);
+ else
+ Chan_playerJoin(ch_itr, client);
+
+}
+
+void Chan_addChannel_id(int parentId, channel_t *ch)
+{
+ channel_t *ch_itr = NULL;
+ do {
+ Chan_iterate(&ch_itr);
+ } while (ch_itr != NULL && ch_itr->id != parentId);
+ if (ch_itr == NULL)
+ Log_warn("Channel id %d not found - ignoring.", parentId);
+ else
+ list_add_tail(&ch->node, &ch_itr->subs);
+}
+
+void Chan_removeChannel(channel_t *ch)
+{
+ list_del(&ch->node);
+}
--- /dev/null
+/* Copyright (C) 2009, Martin Johansson <martin@fatbob.nu>
+ Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ - Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ - Neither the name of the Developers nor the names of its contributors may
+ be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef CHANNEL_H_8939873
+#define CHANNEL_H_8939873
+
+#include "log.h"
+#include "list.h"
+#include "client.h"
+
+typedef struct channel {
+ int id;
+ char name[MAX_TEXT];
+ char desc[MAX_TEXT];
+ struct channel *parent;
+ struct dlist node;
+ struct dlist subs;
+ struct dlist clients;
+ struct dlist flatlist_node;
+} channel_t;
+
+void Chan_init();
+void Chan_free();
+void Chan_addChannel(channel_t *parent, channel_t *sub);
+void Chan_removeChannel(channel_t *c);
+void Chan_addClient(channel_t *c, client_t *client);
+void Chan_removeClient(channel_t *c, client_t *client);
+void Chan_playerJoin(channel_t *ch, client_t *client);
+void Chan_playerJoin_id(int channelid, client_t *client);
+void Chan_iterate(channel_t **channelpptr);
+channel_t *Chan_createChannel(const char *name, const char *desc);
+void Chan_freeChannel(channel_t *ch);
+
+#endif
--- /dev/null
+/* Copyright (C) 2009, Martin Johansson <martin@fatbob.nu>
+ Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ - Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ - Neither the name of the Developers nor the names of its contributors may
+ be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#include <sys/poll.h>
+#include <sys/socket.h>
+#include <errno.h>
+#include "log.h"
+#include "list.h"
+#include "client.h"
+#include "ssl.h"
+#include "messages.h"
+#include "messagehandler.h"
+#include "pds.h"
+#include "conf.h"
+#include "channel.h"
+
+
+
+static int Client_read(client_t *client);
+static int Client_write(client_t *client);
+static int Client_voiceMsg(client_t *client, pds_t *pds);
+static int Client_send_udp(client_t *client, uint8_t *data, int len);
+static void Client_voiceMsg_tunnel(client_t *client, message_t *msg);
+
+declare_list(clients);
+static int clientcount; /* = 0 */
+static int session = 1;
+static int maxBandwidth;
+
+extern int udpsock;
+
+void Client_init()
+{
+ maxBandwidth = getIntConf(MAX_BANDWIDTH);
+}
+
+int Client_count()
+{
+ return clientcount;
+}
+
+int Client_getfds(struct pollfd *pollfds)
+{
+ struct dlist *itr;
+ int i = 0;
+ list_iterate(itr, &clients) {
+ client_t *c;
+ c = list_get_entry(itr, client_t, node);
+ pollfds[i].fd = c->tcpfd;
+ pollfds[i].events = POLLIN | POLLHUP | POLLERR;
+ if (c->txsize > 0 || c->readBlockedOnWrite) /* Data waiting to be sent? */
+ pollfds[i].events |= POLLOUT;
+ i++;
+ }
+ return i;
+}
+
+void Client_janitor()
+{
+ struct dlist *itr;
+ int bwTop = maxBandwidth + maxBandwidth / 4;
+ list_iterate(itr, &clients) {
+ client_t *c;
+ c = list_get_entry(itr, client_t, node);
+ Log_debug("Client %s BW available %d", c->playerName, c->availableBandwidth);
+ c->availableBandwidth += maxBandwidth;
+ if (c->availableBandwidth > bwTop)
+ c->availableBandwidth = bwTop;
+
+ if (Timer_isElapsed(&c->lastActivity, 1000000LL * INACTICITY_TIMEOUT))
+ Client_close(c);
+ }
+}
+
+int Client_add(int fd, struct sockaddr_in *remote)
+{
+ client_t *newclient;
+
+ newclient = malloc(sizeof(client_t));
+ if (newclient == NULL)
+ Log_fatal("Out of memory");
+ memset(newclient, 0, sizeof(client_t));
+
+ newclient->tcpfd = fd;
+ memcpy(&newclient->remote_tcp, remote, sizeof(struct sockaddr_in));
+ newclient->ssl = SSL_newconnection(newclient->tcpfd, &newclient->SSLready);
+ if (newclient->ssl == NULL) {
+ Log_warn("SSL negotiation failed");
+ free(newclient);
+ return -1;
+ }
+ newclient->availableBandwidth = maxBandwidth;
+ Timer_init(&newclient->lastActivity);
+ newclient->sessionId = session++; /* XXX - more elaborate? */
+
+ init_list_entry(&newclient->txMsgQueue);
+ init_list_entry(&newclient->chan_node);
+ init_list_entry(&newclient->node);
+
+ list_add_tail(&newclient->node, &clients);
+ clientcount++;
+ return 0;
+}
+
+void Client_free(client_t *client)
+{
+ struct dlist *itr, *save;
+ message_t *sendmsg;
+
+ Log_info("Disconnect client ID %d addr %s port %d", client->sessionId,
+ inet_ntoa(client->remote_tcp.sin_addr),
+ ntohs(client->remote_tcp.sin_port));
+
+ if (client->authenticated) {
+ sendmsg = Msg_create(ServerLeave);
+ sendmsg->sessionId = client->sessionId;
+ Client_send_message_except(client, sendmsg);
+ }
+ list_iterate_safe(itr, save, &client->txMsgQueue) {
+ list_del(&list_get_entry(itr, message_t, node)->node);
+ Msg_free(list_get_entry(itr, message_t, node));
+ }
+
+ list_del(&client->node);
+ list_del(&client->chan_node);
+ if (client->ssl)
+ SSL_free(client->ssl);
+ close(client->tcpfd);
+ clientcount--;
+ free(client);
+}
+
+void Client_close(client_t *client)
+{
+ SSL_shutdown(client->ssl);
+ client->shutdown_wait = true;
+}
+
+void Client_disconnect_all()
+{
+ struct dlist *itr, *save;
+
+ list_iterate_safe(itr, save, &clients) {
+ Client_free(list_get_entry(itr, client_t, node));
+ }
+}
+
+int Client_read_fd(int fd)
+{
+ 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;
+ }
+ }
+ if (client == NULL)
+ Log_fatal("No client found for fd %d", fd);
+
+ return Client_read(client);
+}
+
+int Client_read(client_t *client)
+{
+ int rc;
+
+ Timer_restart(&client->lastActivity);
+
+ if (client->writeBlockedOnRead) {
+ client->writeBlockedOnRead = false;
+ Log_debug("Client_read: writeBlockedOnRead == true");
+ return Client_write(client);
+ }
+
+ if (client->shutdown_wait) {
+ Client_free(client);
+ return 0;
+ }
+ if (!client->SSLready) {
+ int rc;
+ rc = SSL_nonblockaccept(client->ssl, &client->SSLready);
+ if (rc < 0) {
+ Client_free(client);
+ return -1;
+ }
+ }
+
+ do {
+ errno = 0;
+ if (!client->msgsize)
+ rc = SSL_read(client->ssl, client->rxbuf, 3 - client->rxcount);
+ else if (client->drainleft > 0)
+ rc = SSL_read(client->ssl, client->rxbuf, client->drainleft > BUFSIZE ? BUFSIZE : client->drainleft);
+ else
+ rc = SSL_read(client->ssl, &client->rxbuf[client->rxcount], client->msgsize);
+ if (rc > 0) {
+ message_t *msg;
+ if (client->drainleft > 0)
+ client->drainleft -= rc;
+ else {
+ client->rxcount += rc;
+ if (!client->msgsize && rc >= 3)
+ client->msgsize = ((client->rxbuf[0] & 0xff) << 16) |
+ ((client->rxbuf[1] & 0xff) << 8) |
+ (client->rxbuf[2] & 0xff);
+ if (client->msgsize > BUFSIZE - 3 && client->drainleft == 0) {
+ Log_warn("Too big message received (%d). Discarding.", client->msgsize);
+ client->rxcount = client->msgsize = 0;
+ client->drainleft = client->msgsize;
+ }
+ else if (client->rxcount == client->msgsize + 3) { /* Got all of the message */
+ msg = Msg_networkToMessage(&client->rxbuf[3], client->msgsize);
+ /* pass messsage to handler */
+ if (msg) {
+ if (msg->messageType == Speex) /* Tunneled voice message */
+ Client_voiceMsg_tunnel(client, msg);
+ else
+ Mh_handle_message(client, msg);
+ }
+ client->rxcount = client->msgsize = 0;
+ }
+ }
+ } else /* rc <= 0 */ {
+ if (SSL_get_error(client->ssl, rc) == SSL_ERROR_WANT_READ) {
+ return 0;
+ }
+ else if (SSL_get_error(client->ssl, rc) == SSL_ERROR_WANT_WRITE) {
+ client->readBlockedOnWrite = true;
+ return 0;
+ }
+ else if (SSL_get_error(client->ssl, rc) == SSL_ERROR_ZERO_RETURN) {
+ Log_warn("Error: Zero return - closing");
+ if (!client->shutdown_wait)
+ Client_close(client);
+ }
+ else {
+ if (SSL_get_error(client->ssl, rc) == SSL_ERROR_SYSCALL) {
+ /* Hmm. This is where we end up when the client closes its connection.
+ * Kind of strange...
+ */
+ Log_info("Connection closed by peer");
+ }
+ else {
+ Log_warn("SSL error: %d - Closing connection.", SSL_get_error(client->ssl, rc));
+ }
+ Client_free(client);
+ return -1;
+ }
+ }
+ } while (SSL_pending(client->ssl));
+ return 0;
+}
+
+int Client_write_fd(int fd)
+{
+ 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;
+ }
+ }
+ if (client == NULL)
+ Log_fatal("No client found for fd %d", fd);
+ Client_write(client);
+ return 0;
+}
+
+int Client_write(client_t *client)
+{
+ int rc;
+
+ if (client->readBlockedOnWrite) {
+ client->readBlockedOnWrite = false;
+ Log_debug("Client_write: readBlockedOnWrite == true");
+ return Client_read(client);
+ }
+ rc = SSL_write(client->ssl, &client->txbuf[client->txcount], client->txsize - client->txcount);
+ if (rc > 0) {
+ client->txcount += rc;
+ if (client->txcount == client->txsize)
+ client->txsize = client->txcount = 0;
+ }
+ else if (rc < 0) {
+ if (SSL_get_error(client->ssl, rc) == SSL_ERROR_WANT_READ) {
+ client->writeBlockedOnRead = true;
+ return 0;
+ }
+ else if (SSL_get_error(client->ssl, rc) == SSL_ERROR_WANT_WRITE) {
+ return 0;
+ }
+ else {
+ if (SSL_get_error(client->ssl, rc) == SSL_ERROR_SYSCALL)
+ Log_warn("Client_write: Error: %s - Closing connection", strerror(errno));
+ else
+ Log_warn("Client_write: SSL error: %d - Closing connection.", SSL_get_error(client->ssl, rc));
+ Client_free(client);
+ return -1;
+ }
+ }
+ if (client->txsize == 0 && !list_empty(&client->txMsgQueue)) {
+ message_t *msg;
+ msg = list_get_entry(list_get_first(&client->txMsgQueue), message_t, node);
+ list_del(list_get_first(&client->txMsgQueue));
+ client->txQueueCount--;
+ Client_send_message(client, msg);
+ }
+ return 0;
+}
+
+int Client_send_message(client_t *client, message_t *msg)
+{
+ if (!client->authenticated || !client->SSLready) {
+ Msg_free(msg);
+ return 0;
+ }
+ if (client->txsize != 0) {
+ /* Queue message */
+ if ((client->txQueueCount > 5 && msg->messageType == Speex) ||
+ client->txQueueCount > 30) {
+ Msg_free(msg);
+ return -1;
+ }
+ client->txQueueCount++;
+ list_add_tail(&msg->node, &client->txMsgQueue);
+ } else {
+ int len;
+ memset(client->txbuf, 0, BUFSIZE);
+ len = Msg_messageToNetwork(msg, &client->txbuf[3], BUFSIZE - 3);
+ doAssert(len < BUFSIZE - 3);
+
+ client->txbuf[0] = (len >> 16) & 0xff;
+ client->txbuf[1] = (len >> 8) & 0xff;
+ client->txbuf[2] = len & 0xff;
+ client->txsize = len + 3;
+ client->txcount = 0;
+ Client_write(client);
+ Msg_free(msg);
+ }
+ return 0;
+}
+
+client_t *Client_iterate(client_t **client_itr)
+{
+ client_t *c = *client_itr;
+
+ if (c == NULL && !list_empty(&clients)) {
+ c = list_get_entry(list_get_first(&clients), client_t, node);
+ } else {
+ if (list_get_next(&c->node) == &clients)
+ c = NULL;
+ else
+ c = list_get_entry(list_get_next(&c->node), client_t, node);
+ }
+ *client_itr = c;
+ return c;
+}
+
+
+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 */
+ Log_debug("Msg %d to %s refcount %d", msg->messageType, itr->playerName, 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. */
+
+ return 0;
+}
+
+static bool_t checkDecrypt(client_t *client, const uint8_t *encrypted, uint8_t *plain, unsigned int len)
+{
+ if (CryptState_isValid(&client->cryptState) &&
+ CryptState_decrypt(&client->cryptState, encrypted, plain, len))
+ return true;
+
+ if (Timer_elapsed(&client->cryptState.tLastGood) > 5000000ULL) {
+ if (Timer_elapsed(&client->cryptState.tLastRequest) > 5000000ULL) {
+ message_t *sendmsg;
+ Timer_restart(&client->cryptState.tLastRequest);
+
+ sendmsg = Msg_create(CryptSync);
+ sendmsg->sessionId = client->sessionId;
+ sendmsg->payload.cryptSync.empty = true;
+ Log_info("Requesting voice channel crypt resync");
+ Client_send_message(client, sendmsg);
+ }
+ }
+ return false;
+}
+
+int Client_read_udp()
+{
+ int len;
+ struct sockaddr_in from;
+ socklen_t fromlen = sizeof(struct sockaddr_in);
+ uint64_t key;
+ client_t *itr;
+ int msgType = 0;
+ uint32_t sessionId = 0;
+ pds_t *pds;
+
+#if defined(__LP64__)
+ uint8_t encbuff[512 + 8];
+ uint8_t *encrypted = encbuff + 4;
+#else
+ uint8_t encrypted[512];
+#endif
+ uint8_t buffer[512];
+
+ len = recvfrom(udpsock, encrypted, 512, MSG_TRUNC, (struct sockaddr *)&from, &fromlen);
+ if (len == 0) {
+ return -1;
+ } else if (len < 0) {
+ return -1;
+ } else if (len < 6) {
+ // 4 bytes crypt header + type + session
+ return 0;
+ } else if (len > 512) {
+ return 0;
+ }
+
+ key = (((uint64_t)from.sin_addr.s_addr) << 16) ^ from.sin_port;
+ pds = Pds_create(buffer, len - 4);
+ itr = NULL;
+
+ while (Client_iterate(&itr) != NULL) {
+ if (itr->key == key) {
+ if (!checkDecrypt(itr, encrypted, buffer, len))
+ goto out;
+ msgType = Pds_get_numval(pds);
+ sessionId = Pds_get_numval(pds);
+ if (itr->sessionId != sessionId)
+ goto out;
+ break;
+ }
+ }
+ if (itr == NULL) { /* Unknown peer */
+ while (Client_iterate(&itr) != NULL) {
+ pds->offset = 0;
+ if (itr->remote_tcp.sin_addr.s_addr == from.sin_addr.s_addr) {
+ if (checkDecrypt(itr, encrypted, buffer, len)) {
+ msgType = Pds_get_numval(pds);
+ sessionId = Pds_get_numval(pds);
+ if (itr->sessionId == sessionId) { /* Found matching client */
+ itr->key = key;
+ Log_info("New UDP connection from %s port %d sessionId %d", inet_ntoa(from.sin_addr), ntohs(from.sin_port), sessionId);
+ memcpy(&itr->remote_udp, &from, sizeof(struct sockaddr_in));
+ break;
+ }
+ }
+ else Log_warn("Bad cryptstate from peer");
+ }
+ } /* while */
+ }
+ if (itr == NULL) {
+ goto out;
+ }
+ len -= 4;
+ if (msgType != Speex && msgType != Ping)
+ goto out;
+
+ if (msgType == Ping) {
+ Client_send_udp(itr, buffer, len);
+ }
+ else {
+ Client_voiceMsg(itr, pds);
+ }
+
+out:
+ Pds_free(pds);
+ return 0;
+}
+
+static void Client_voiceMsg_tunnel(client_t *client, message_t *msg)
+{
+ uint8_t buf[512];
+ pds_t *pds = Pds_create(buf, 512);
+
+ Pds_add_numval(pds, msg->messageType);
+ Pds_add_numval(pds, msg->sessionId);
+ Pds_add_numval(pds, msg->payload.speex.seq);
+ Pds_append_data_nosize(pds, msg->payload.speex.data, msg->payload.speex.size);
+ if (!pds->bOk)
+ Log_warn("Large Speex message from TCP"); /* XXX - pds resize? */
+ pds->maxsize = pds->offset;
+ Client_voiceMsg(client, pds);
+ Pds_free(pds);
+}
+
+static int Client_voiceMsg(client_t *client, pds_t *pds)
+{
+ int seq, flags, msgType, sessionId, packetsize;
+ channel_t *ch = (channel_t *)client->channel;
+ struct dlist *itr;
+
+ if (!client->authenticated || client->mute)
+ return 0;
+
+
+ pds->offset = 0;
+ msgType = Pds_get_numval(pds);
+ sessionId = Pds_get_numval(pds);
+ seq = Pds_get_numval(pds);
+ flags = Pds_get_numval(pds);
+
+ packetsize = 20 + 8 + 4 + pds->maxsize - pds->offset;
+ if (client->availableBandwidth - packetsize < 0)
+ return 0; /* Discard */
+
+ client->availableBandwidth -= packetsize;
+
+ pds->offset = 0;
+
+ if (flags & LoopBack) {
+ Client_send_udp(client, pds->data, pds->maxsize);
+ return 0;
+ }
+ if (ch == NULL)
+ return 0;
+
+ list_iterate(itr, &ch->clients) {
+ client_t *c;
+ c = list_get_entry(itr, client_t, chan_node);
+ if (c != client && !c->deaf) {
+ Client_send_udp(c, pds->data, pds->maxsize);
+ }
+ }
+ return 0;
+}
+
+
+static int Client_send_udp(client_t *client, uint8_t *data, int len)
+{
+ uint8_t *buf, *mbuf;
+ message_t *sendmsg;
+
+ if (client->remote_udp.sin_port != 0 && CryptState_isValid(&client->cryptState)) {
+#if defined(__LP64__)
+ buf = mbuf = malloc(len + 4 + 16);
+ buf += 4;
+#else
+ mbuf = buf = malloc(len + 4);
+#endif
+ if (mbuf == NULL)
+ Log_fatal("Out of memory");
+
+ CryptState_encrypt(&client->cryptState, data, buf, len);
+
+ sendto(udpsock, buf, len + 4, 0, (struct sockaddr *)&client->remote_udp, sizeof(struct sockaddr_in));
+
+ free(mbuf);
+ } else {
+ pds_t *pds = Pds_create(data, len);
+
+ sendmsg = Msg_create(Pds_get_numval(pds));
+ sendmsg->sessionId = Pds_get_numval(pds);
+
+ if (sendmsg->messageType == Speex || sendmsg->messageType == Ping) {
+ if (sendmsg->messageType == Speex) {
+ sendmsg->payload.speex.seq = Pds_get_numval(pds);
+ sendmsg->payload.speex.size = pds->maxsize - pds->offset;
+ doAssert(pds->maxsize - pds->offset <= SPEEX_DATA_SIZE);
+ memcpy(sendmsg->payload.speex.data, data + pds->offset, pds->maxsize - pds->offset);
+ } else { /* Ping */
+ sendmsg->payload.ping.timestamp = Pds_get_numval(pds);
+ }
+ Client_send_message(client, sendmsg);
+ } else {
+ Log_warn("TCP fallback: Unsupported message type %d", sendmsg->messageType);
+ Msg_free(sendmsg);
+ }
+ Pds_free(pds);
+ }
+ return 0;
+}
--- /dev/null
+/* Copyright (C) 2009, Martin Johansson <martin@fatbob.nu>
+ Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ - Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ - Neither the name of the Developers nor the names of its contributors may
+ be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef CLIENT_H_45786678
+#define CLIENT_H_45786678
+
+#include <openssl/ssl.h>
+#include <stdint.h>
+#include <unistd.h> /* close() */
+#include <sys/types.h>
+#include <sys/socket.h> /* socket() */
+#include <netinet/in.h> /* IPPROTO_TCP */
+#include <arpa/inet.h> /* inet_addr() */
+#include <errno.h> /* errno */
+#include <sys/poll.h>
+
+#include "list.h"
+#include "types.h"
+#include "messages.h"
+#include "crypt.h"
+#include "timer.h"
+
+#define BUFSIZE 2048
+#define UDP_BUFSIZE 512
+#define INACTICITY_TIMEOUT 15 /* Seconds */
+
+#define IS_AUTH(_a_) ((_a_)->authenticated)
+
+typedef struct {
+ int tcpfd;
+ SSL *ssl;
+ bool_t SSLready;
+ bool_t shutdown_wait;
+ cryptState_t cryptState;
+ bool_t readBlockedOnWrite, writeBlockedOnRead;
+
+ struct sockaddr_in remote_tcp;
+ struct sockaddr_in remote_udp;
+ uint8_t rxbuf[BUFSIZE], txbuf[BUFSIZE];
+ uint32_t rxcount, msgsize, drainleft, txcount, txsize;
+ int sessionId;
+ uint64_t key;
+ char playerName[MAX_TEXT];
+ int playerId;
+ bool_t authenticated, deaf, mute;
+ int availableBandwidth;
+ etimer_t lastActivity;
+ struct dlist node;
+ struct dlist txMsgQueue;
+ int txQueueCount;
+ /* Channel */
+ void *channel; /*Ugly... */
+ struct dlist chan_node;
+} client_t;
+
+
+void Client_init();
+int Client_getfds(struct pollfd *pollfds);
+void Client_janitor();
+int Client_add(int fd, struct sockaddr_in *remote);
+int Client_read_fd(int fd);
+int Client_write_fd(int fd);
+int Client_send_message(client_t *client, message_t *msg);
+int Client_count(void);
+void Client_close(client_t *client);
+client_t *Client_iterate(client_t **client);
+int Client_send_message_except(client_t *client, message_t *msg);
+int Client_read_udp(void);
+void Client_disconnect_all();
+
+#endif
--- /dev/null
+/* Copyright (C) 2009, Martin Johansson <martin@fatbob.nu>
+ Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ - Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ - Neither the name of the Developers nor the names of its contributors may
+ be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef WRT_TARGET
+#include <libconfig/libconfig.h>
+#else
+#include <libconfig.h>
+#endif
+
+#include "types.h"
+#include "conf.h"
+#include "log.h"
+
+static config_t configuration;
+
+#define DEFAULT_CONFIG "/etc/umurmur.conf"
+#define DEFAULT_WELCOME "Welcome to uMurmur!"
+#define DEFAULT_MAX_CLIENTS 10
+#define DEFAULT_MAX_BANDWIDTH 5000
+#define DEFAULT_BINDPORT 64738
+
+const char defaultconfig[] = DEFAULT_CONFIG;
+
+int Conf_init(const char *conffile)
+{
+ const char *conf;
+
+ config_init(&configuration);
+ if (conffile == NULL)
+ conf = defaultconfig;
+ else
+ conf = conffile;
+ if (config_read_file(&configuration, conf) != CONFIG_TRUE) {
+ fprintf(stderr, "Error in config file %s: %s at line %d\n", conffile,
+ config_error_text(&configuration), config_error_line(&configuration));
+ exit(1);
+ }
+ return 0;
+}
+
+void Conf_deinit()
+{
+ config_destroy(&configuration);
+}
+
+const char *getStrConf(param_t param)
+{
+ config_setting_t *setting = NULL;
+ const char *strsetting = NULL;
+
+ switch (param) {
+ case CERTIFICATE:
+ setting = config_lookup(&configuration, "certificate");
+ if (!setting)
+ return "/etc/umurmur/certificate.crt";
+ else {
+ if ((strsetting = config_setting_get_string(setting)) != NULL)
+ return strsetting;
+ else
+ return "/etc/umurmur/certificate.crt";
+ }
+ break;
+ case KEY:
+ setting = config_lookup(&configuration, "private_key");
+ if (!setting)
+ return "/etc/umurmur/private_key.key";
+ else {
+ if ((strsetting = config_setting_get_string(setting)) != NULL)
+ return strsetting;
+ else
+ return "/etc/umurmur/private_key.key";
+ }
+ break;
+ case PASSPHRASE:
+ setting = config_lookup(&configuration, "password");
+ if (!setting)
+ return "";
+ else {
+ if ((strsetting = config_setting_get_string(setting)) != NULL)
+ return strsetting;
+ else
+ return "";
+ }
+ break;
+ case BINDADDR:
+ setting = config_lookup(&configuration, "bindaddr");
+ if (!setting)
+ return "";
+ else {
+ if ((strsetting = config_setting_get_string(setting)) != NULL)
+ return strsetting;
+ else
+ return "";
+ }
+ break;
+ case WELCOMETEXT:
+ setting = config_lookup(&configuration, "welcometext");
+ if (!setting)
+ return DEFAULT_WELCOME;
+ else {
+ if ((strsetting = config_setting_get_string(setting)) != NULL)
+ return strsetting;
+ else
+ return DEFAULT_WELCOME;
+ }
+ break;
+ case DEAFULT_CHANNEL:
+ setting = config_lookup(&configuration, "default_channel");
+ if (!setting)
+ return "";
+ else {
+ if ((strsetting = config_setting_get_string(setting)) != NULL)
+ return strsetting;
+ else
+ return "";
+ }
+ break;
+ default:
+ doAssert(false);
+ break;
+ }
+ return NULL;
+}
+
+int getIntConf(param_t param)
+{
+ config_setting_t *setting = NULL;
+
+ switch (param) {
+ case BINDPORT:
+ setting = config_lookup(&configuration, "bindport");
+ if (!setting)
+ return DEFAULT_BINDPORT;
+ else {
+ return config_setting_get_int(setting);
+ }
+ break;
+ case MAX_BANDWIDTH:
+ setting = config_lookup(&configuration, "max_bandwidth");
+ if (!setting)
+ return DEFAULT_MAX_BANDWIDTH;
+ else {
+ return config_setting_get_int(setting);
+ }
+ break;
+ case MAX_CLIENTS:
+ setting = config_lookup(&configuration, "max_users");
+ if (!setting)
+ return DEFAULT_MAX_CLIENTS;
+ else {
+ return config_setting_get_int(setting);
+ }
+ break;
+ default:
+ doAssert(false);
+ }
+}
+
+int Conf_getNextChannel(conf_channel_t *chdesc, int index)
+{
+ config_setting_t *setting = NULL;
+ char configstr[64];
+
+ sprintf(configstr, "channels.[%d].name", index);
+ setting = config_lookup(&configuration, configstr);
+ if (setting == NULL)
+ return -1;
+ strncpy(chdesc->name, config_setting_get_string(setting), MAX_TEXT);
+
+ sprintf(configstr, "channels.[%d].parent", index);
+ setting = config_lookup(&configuration, configstr);
+ if (setting == NULL)
+ return -1;
+ strncpy(chdesc->parent, config_setting_get_string(setting), MAX_TEXT);
+
+ sprintf(configstr, "channels.[%d].description", index);
+ setting = config_lookup(&configuration, configstr);
+ if (setting == NULL)
+ return -1;
+ strncpy(chdesc->description, config_setting_get_string(setting), MAX_TEXT);
+
+ return 0;
+}
--- /dev/null
+/* Copyright (C) 2009, Martin Johansson <martin@fatbob.nu>
+ Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ - Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ - Neither the name of the Developers nor the names of its contributors may
+ be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef CONF_H_24564356
+#define CONF_H_24564356
+
+#include "messages.h"
+
+typedef enum param {
+ CERTIFICATE,
+ KEY,
+ PASSPHRASE,
+ BINDPORT,
+ BINDADDR,
+ WELCOMETEXT,
+ MAX_BANDWIDTH,
+ MAX_CLIENTS,
+ DEAFULT_CHANNEL,
+} param_t;
+
+typedef struct {
+ char parent[MAX_TEXT];
+ char name[MAX_TEXT];
+ char description[MAX_TEXT];
+} conf_channel_t;
+
+int Conf_init(const char *conffile);
+void Conf_deinit();
+
+const char *getStrConf(param_t param);
+int getIntConf(param_t param);
+int Conf_getNextChannel(conf_channel_t *chdesc, int index);
+
+#endif
--- /dev/null
+/* Copyright (C) 2009, Martin Johansson <martin@fatbob.nu>
+ Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ - Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ - Neither the name of the Developers nor the names of its contributors may
+ be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * This code implements OCB-AES128.
+ * In the US, OCB is covered by patents. The inventor has given a license
+ * to all programs distributed under the GPL.
+ * uMurmur is BSD (revised) licensed, meaning you can use the code in a
+ * closed-source program. If you do, you'll have to either replace
+ * OCB with something else or get yourself a license.
+ */
+
+#include <string.h>
+#include <arpa/inet.h>
+#include "crypt.h"
+#include "log.h"
+static void CryptState_ocb_encrypt(cryptState_t *cs, const unsigned char *plain, unsigned char *encrypted, unsigned int len, const unsigned char *nonce, unsigned char *tag);
+static void CryptState_ocb_decrypt(cryptState_t *cs, const unsigned char *encrypted, unsigned char *plain, unsigned int len, const unsigned char *nonce, unsigned char *tag);
+
+void CryptState_init(cryptState_t *cs)
+{
+ memset(cs->decrypt_history, 0, 0xff);
+ memset(cs->raw_key, 0, AES_BLOCK_SIZE);
+ memset(cs->encrypt_iv, 0, AES_BLOCK_SIZE);
+ memset(cs->decrypt_iv, 0, AES_BLOCK_SIZE);
+ cs->bInit = false;
+ cs->uiGood = cs->uiLate = cs->uiLost = cs->uiResync = 0;
+ cs->uiRemoteGood = cs->uiRemoteLate = cs->uiRemoteLost = cs->uiRemoteResync = 0;
+ Timer_init(&cs->tLastGood);
+ Timer_init(&cs->tLastRequest);
+}
+
+bool_t CryptState_isValid(cryptState_t *cs)
+{
+ return cs->bInit;
+}
+
+void CryptState_genKey(cryptState_t *cs) {
+ RAND_bytes(cs->raw_key, AES_BLOCK_SIZE);
+ RAND_bytes(cs->encrypt_iv, AES_BLOCK_SIZE);
+ RAND_bytes(cs->decrypt_iv, AES_BLOCK_SIZE);
+ AES_set_encrypt_key(cs->raw_key, 128, &cs->encrypt_key);
+ AES_set_decrypt_key(cs->raw_key, 128, &cs->decrypt_key);
+ cs->bInit = true;
+}
+
+void CryptState_setKey(cryptState_t *cs, const unsigned char *rkey, const unsigned char *eiv, const unsigned char *div)
+{
+ memcpy(cs->raw_key, rkey, AES_BLOCK_SIZE);
+ memcpy(cs->encrypt_iv, eiv, AES_BLOCK_SIZE);
+ memcpy(cs->decrypt_iv, div, AES_BLOCK_SIZE);
+ AES_set_encrypt_key(cs->raw_key, 128, &cs->encrypt_key);
+ AES_set_decrypt_key(cs->raw_key, 128, &cs->decrypt_key);
+ cs->bInit = true;
+}
+
+void CryptState_setDecryptIV(cryptState_t *cs, const unsigned char *iv)
+{
+ memcpy(cs->decrypt_iv, iv, AES_BLOCK_SIZE);
+}
+
+void CryptState_encrypt(cryptState_t *cs, const unsigned char *source, unsigned char *dst, unsigned int plain_length)
+{
+ unsigned char tag[AES_BLOCK_SIZE];
+ int i;
+ // First, increase our IV.
+ for (i = 0; i < AES_BLOCK_SIZE; i++)
+ if (++cs->encrypt_iv[i])
+ break;
+
+ CryptState_ocb_encrypt(cs, source, dst+4, plain_length, cs->encrypt_iv, tag);
+
+ dst[0] = cs->encrypt_iv[0];
+ dst[1] = tag[0];
+ dst[2] = tag[1];
+ dst[3] = tag[2];
+}
+
+bool_t CryptState_decrypt(cryptState_t *cs, const unsigned char *source, unsigned char *dst, unsigned int crypted_length)
+{
+ if (crypted_length < 4)
+ return false;
+
+ unsigned int plain_length = crypted_length - 4;
+
+ unsigned char saveiv[AES_BLOCK_SIZE];
+ unsigned char ivbyte = source[0];
+ bool_t restore = false;
+ unsigned char tag[AES_BLOCK_SIZE];
+
+ int lost = 0;
+ int late = 0;
+
+ memcpy(saveiv, cs->decrypt_iv, AES_BLOCK_SIZE);
+
+ if (((cs->decrypt_iv[0] + 1) & 0xFF) == ivbyte) {
+ // In order as expected.
+ if (ivbyte > cs->decrypt_iv[0]) {
+ cs->decrypt_iv[0] = ivbyte;
+ } else if (ivbyte < cs->decrypt_iv[0]) {
+ int i;
+ cs->decrypt_iv[0] = ivbyte;
+ for (i = 1; i < AES_BLOCK_SIZE; i++)
+ if (++cs->decrypt_iv[i])
+ break;
+ } else {
+ return false;
+ }
+ } else {
+ // This is either out of order or a repeat.
+
+ int diff = ivbyte - cs->decrypt_iv[0];
+ if (diff > 128)
+ diff = diff-256;
+ else if (diff < -128)
+ diff = diff+256;
+
+ if ((ivbyte < cs->decrypt_iv[0]) && (diff > -30) && (diff < 0)) {
+ // Late packet, but no wraparound.
+ late = 1;
+ lost = -1;
+ cs->decrypt_iv[0] = ivbyte;
+ restore = true;
+ } else if ((ivbyte > cs->decrypt_iv[0]) && (diff > -30) && (diff < 0)) {
+ int i;
+ // Last was 0x02, here comes 0xff from last round
+ late = 1;
+ lost = -1;
+ cs->decrypt_iv[0] = ivbyte;
+ for (i = 1; i < AES_BLOCK_SIZE; i++)
+ if (cs->decrypt_iv[i]--)
+ break;
+ restore = true;
+ } else if ((ivbyte > cs->decrypt_iv[0]) && (diff > 0)) {
+ // Lost a few packets, but beyond that we're good.
+ lost = ivbyte - cs->decrypt_iv[0] - 1;
+ cs->decrypt_iv[0] = ivbyte;
+ } else if ((ivbyte < cs->decrypt_iv[0]) && (diff > 0)) {
+ int i;
+ // Lost a few packets, and wrapped around
+ lost = 256 - cs->decrypt_iv[0] + ivbyte - 1;
+ cs->decrypt_iv[0] = ivbyte;
+ for (i = 1; i < AES_BLOCK_SIZE; i++)
+ if (++cs->decrypt_iv[i])
+ break;
+ } else {
+ return false;
+ }
+
+ if (cs->decrypt_history[cs->decrypt_iv[0]] == cs->decrypt_iv[1]) {
+ memcpy(cs->decrypt_iv, saveiv, AES_BLOCK_SIZE);
+ return false;
+ }
+ }
+
+ CryptState_ocb_decrypt(cs, source+4, dst, plain_length, cs->decrypt_iv, tag);
+
+ if (memcmp(tag, source+1, 3) != 0) {
+ memcpy(cs->decrypt_iv, saveiv, AES_BLOCK_SIZE);
+ return false;
+ }
+ cs->decrypt_history[cs->decrypt_iv[0]] = cs->decrypt_iv[1];
+
+ if (restore)
+ memcpy(cs->decrypt_iv, saveiv, AES_BLOCK_SIZE);
+
+ cs->uiGood++;
+ cs->uiLate += late;
+ cs->uiLost += lost;
+
+ Timer_restart(&cs->tLastGood);
+ return true;
+}
+
+#if defined(__LP64__)
+#define BLOCKSIZE 2
+#define SHIFTBITS 63
+typedef uint64_t subblock;
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+#define SWAPPED(x) (x)
+#else
+#ifdef __x86_64__
+#define SWAPPED(x) ({register uint64_t __out, __in = (x); __asm__("bswap %q0" : "=r"(__out) : "0"(__in)); __out;})
+#else
+#include <byteswap.h>
+#define SWAPPED(x) bswap_64(x)
+#endif
+#endif
+
+#else
+
+#define BLOCKSIZE 4
+#define SHIFTBITS 31
+typedef uint32_t subblock;
+#define SWAPPED(x) htonl(x)
+
+#endif
+
+#define HIGHBIT (1<<SHIFTBITS);
+
+
+static void inline XOR(subblock *dst, const subblock *a, const subblock *b) {
+ int i;
+ for (i=0;i<BLOCKSIZE;i++) {
+ dst[i] = a[i] ^ b[i];
+ }
+}
+
+static void inline S2(subblock *block) {
+ subblock carry = SWAPPED(block[0]) >> SHIFTBITS;
+ int i;
+ for (i=0;i<BLOCKSIZE-1;i++)
+ block[i] = SWAPPED((SWAPPED(block[i]) << 1) | (SWAPPED(block[i+1]) >> SHIFTBITS));
+ block[BLOCKSIZE-1] = SWAPPED((SWAPPED(block[BLOCKSIZE-1]) << 1) ^(carry * 0x87));
+}
+
+static void inline S3(subblock *block) {
+ subblock carry = SWAPPED(block[0]) >> SHIFTBITS;
+ int i;
+ for (i=0;i<BLOCKSIZE-1;i++)
+ block[i] ^= SWAPPED((SWAPPED(block[i]) << 1) | (SWAPPED(block[i+1]) >> SHIFTBITS));
+ block[BLOCKSIZE-1] ^= SWAPPED((SWAPPED(block[BLOCKSIZE-1]) << 1) ^(carry * 0x87));
+}
+
+static void inline ZERO(subblock *block) {
+ int i;
+ for (i=0;i<BLOCKSIZE;i++)
+ block[i]=0;
+}
+
+#define AESencrypt(src,dst,key) AES_encrypt((unsigned char *)(src),(unsigned char *)(dst), key);
+#define AESdecrypt(src,dst,key) AES_decrypt((unsigned char *)(src),(unsigned char *)(dst), key);
+
+void CryptState_ocb_encrypt(cryptState_t *cs, const unsigned char *plain, unsigned char *encrypted, unsigned int len, const unsigned char *nonce, unsigned char *tag) {
+ subblock checksum[BLOCKSIZE], delta[BLOCKSIZE], tmp[BLOCKSIZE], pad[BLOCKSIZE];
+
+ // Initialize
+ AESencrypt(nonce, delta, &cs->encrypt_key);
+ ZERO(checksum);
+
+ while (len > AES_BLOCK_SIZE) {
+ S2(delta);
+ XOR(tmp, delta, (const subblock *)(plain));
+ AESencrypt(tmp, tmp, &cs->encrypt_key);
+ XOR((subblock *)(encrypted), delta, tmp);
+ XOR(checksum, checksum, (subblock *)(plain));
+ len -= AES_BLOCK_SIZE;
+ plain += AES_BLOCK_SIZE;
+ encrypted += AES_BLOCK_SIZE;
+ }
+
+ S2(delta);
+ ZERO(tmp);
+ tmp[BLOCKSIZE - 1] = SWAPPED(len * 8);
+ XOR(tmp, tmp, delta);
+ AESencrypt(tmp, pad, &cs->encrypt_key);
+ memcpy(tmp, plain, len);
+ memcpy((unsigned char *)tmp + len, (unsigned char *)pad + len, AES_BLOCK_SIZE - len);
+ XOR(checksum, checksum, tmp);
+ XOR(tmp, pad, tmp);
+ memcpy(encrypted, tmp, len);
+
+ S3(delta);
+ XOR(tmp, delta, checksum);
+ AESencrypt(tmp, tag, &cs->encrypt_key);
+}
+
+void CryptState_ocb_decrypt(cryptState_t *cs, const unsigned char *encrypted, unsigned char *plain, unsigned int len, const unsigned char *nonce, unsigned char *tag) {
+ subblock checksum[BLOCKSIZE], delta[BLOCKSIZE], tmp[BLOCKSIZE], pad[BLOCKSIZE];
+
+ // Initialize
+ AESencrypt(nonce, delta, &cs->encrypt_key);
+ ZERO(checksum);
+
+ while (len > AES_BLOCK_SIZE) {
+ S2(delta);
+ XOR(tmp, delta, (const subblock *)(encrypted));
+ AESdecrypt(tmp, tmp, &cs->decrypt_key);
+ XOR((subblock *)(plain), delta, tmp);
+ XOR(checksum, checksum, (const subblock *)(plain));
+ len -= AES_BLOCK_SIZE;
+ plain += AES_BLOCK_SIZE;
+ encrypted += AES_BLOCK_SIZE;
+ }
+
+ S2(delta);
+ ZERO(tmp);
+ tmp[BLOCKSIZE - 1] = SWAPPED(len * 8);
+ XOR(tmp, tmp, delta);
+ AESencrypt(tmp, pad, &cs->encrypt_key);
+ memset(tmp, 0, AES_BLOCK_SIZE);
+ memcpy(tmp, encrypted, len);
+ XOR(tmp, tmp, pad);
+ XOR(checksum, checksum, tmp);
+ memcpy(plain, tmp, len);
+
+ S3(delta);
+ XOR(tmp, delta, checksum);
+ AESencrypt(tmp, tag, &cs->encrypt_key);
+}
--- /dev/null
+/* Copyright (C) 2009, Martin Johansson <martin@fatbob.nu>
+ Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ - Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ - Neither the name of the Developers nor the names of its contributors may
+ be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef _CRYPTSTATE_H
+#define _CRYPTSTATE_H
+
+#include <openssl/rand.h>
+#include <openssl/aes.h>
+#include <stdint.h>
+#include "timer.h"
+#include "types.h"
+
+typedef struct CryptState {
+ uint8_t raw_key[AES_BLOCK_SIZE];
+ uint8_t encrypt_iv[AES_BLOCK_SIZE];
+ uint8_t decrypt_iv[AES_BLOCK_SIZE];
+ uint8_t decrypt_history[0x100];
+
+ unsigned int uiGood;
+ unsigned int uiLate;
+ unsigned int uiLost;
+ unsigned int uiResync;
+
+ unsigned int uiRemoteGood;
+ unsigned int uiRemoteLate;
+ unsigned int uiRemoteLost;
+ unsigned int uiRemoteResync;
+
+ AES_KEY encrypt_key;
+ AES_KEY decrypt_key;
+ etimer_t tLastGood;
+ etimer_t tLastRequest;
+ bool_t bInit;
+} cryptState_t;
+
+void CryptState_init(cryptState_t *cs);
+bool_t CryptState_isValid(cryptState_t *cs);
+void CryptState_genKey(cryptState_t *cs);
+void CryptState_setKey(cryptState_t *cs, const unsigned char *rkey, const unsigned char *eiv, const unsigned char *div);
+void CryptState_setDecryptIV(cryptState_t *cs, const unsigned char *iv);
+
+bool_t CryptState_decrypt(cryptState_t *cs, const unsigned char *source, unsigned char *dst, unsigned int crypted_length);
+void CryptState_encrypt(cryptState_t *cs, const unsigned char *source, unsigned char *dst, unsigned int plain_length);
+#endif
--- /dev/null
+client.o: client.c /usr/include/sys/poll.h /usr/include/features.h \
+ /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
+ /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h \
+ /usr/include/bits/poll.h /usr/include/sys/socket.h \
+ /usr/include/sys/uio.h /usr/include/sys/types.h \
+ /usr/include/bits/types.h /usr/include/bits/typesizes.h \
+ /usr/include/time.h \
+ /usr/lib/gcc/x86_64-redhat-linux/4.3.2/include/stddef.h \
+ /usr/include/endian.h /usr/include/bits/endian.h \
+ /usr/include/bits/byteswap.h /usr/include/sys/select.h \
+ /usr/include/bits/select.h /usr/include/bits/sigset.h \
+ /usr/include/bits/time.h /usr/include/sys/sysmacros.h \
+ /usr/include/bits/pthreadtypes.h /usr/include/bits/uio.h \
+ /usr/include/bits/socket.h /usr/include/bits/sockaddr.h \
+ /usr/include/asm/socket.h /usr/include/asm/sockios.h \
+ /usr/include/errno.h /usr/include/bits/errno.h \
+ /usr/include/linux/errno.h /usr/include/asm/errno.h \
+ /usr/include/asm-generic/errno.h /usr/include/asm-generic/errno-base.h \
+ log.h types.h list.h client.h /usr/include/openssl/ssl.h \
+ /usr/include/openssl/e_os2.h /usr/include/openssl/opensslconf.h \
+ /usr/include/openssl/opensslconf-x86_64.h /usr/include/openssl/comp.h \
+ /usr/include/openssl/crypto.h /usr/include/stdlib.h \
+ /usr/include/alloca.h /usr/include/stdio.h /usr/include/libio.h \
+ /usr/include/_G_config.h /usr/include/wchar.h \
+ /usr/lib/gcc/x86_64-redhat-linux/4.3.2/include/stdarg.h \
+ /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
+ /usr/include/openssl/stack.h /usr/include/openssl/safestack.h \
+ /usr/include/openssl/opensslv.h /usr/include/openssl/ossl_typ.h \
+ /usr/include/openssl/symhacks.h /usr/include/openssl/bio.h \
+ /usr/include/openssl/x509.h /usr/include/openssl/buffer.h \
+ /usr/include/openssl/evp.h /usr/include/openssl/objects.h \
+ /usr/include/openssl/obj_mac.h /usr/include/openssl/asn1.h \
+ /usr/include/openssl/bn.h /usr/include/openssl/rsa.h \
+ /usr/include/openssl/dsa.h /usr/include/openssl/dh.h \
+ /usr/include/openssl/sha.h /usr/include/openssl/x509_vfy.h \
+ /usr/include/openssl/lhash.h /usr/include/openssl/pkcs7.h \
+ /usr/include/openssl/pem.h /usr/include/openssl/pem2.h \
+ /usr/include/openssl/kssl.h /usr/include/ctype.h /usr/include/krb5.h \
+ /usr/include/krb5/krb5.h \
+ /usr/lib/gcc/x86_64-redhat-linux/4.3.2/include/limits.h \
+ /usr/lib/gcc/x86_64-redhat-linux/4.3.2/include/syslimits.h \
+ /usr/include/limits.h /usr/include/bits/posix1_lim.h \
+ /usr/include/bits/local_lim.h /usr/include/linux/limits.h \
+ /usr/include/bits/posix2_lim.h /usr/include/et/com_err.h \
+ /usr/include/openssl/ssl2.h /usr/include/openssl/ssl3.h \
+ /usr/include/openssl/pq_compat.h /usr/include/openssl/tls1.h \
+ /usr/include/openssl/dtls1.h /usr/include/openssl/pqueue.h \
+ /usr/include/string.h /usr/include/openssl/ssl23.h \
+ /usr/include/stdint.h /usr/include/bits/wchar.h /usr/include/unistd.h \
+ /usr/include/bits/posix_opt.h /usr/include/bits/confname.h \
+ /usr/include/getopt.h /usr/include/netinet/in.h /usr/include/bits/in.h \
+ /usr/include/arpa/inet.h messages.h /usr/include/openssl/aes.h crypt.h \
+ /usr/include/openssl/rand.h timer.h ssl.h /usr/include/openssl/x509v3.h \
+ /usr/include/openssl/conf.h messagehandler.h pds.h conf.h channel.h
+main.o: main.c /usr/include/stdio.h /usr/include/features.h \
+ /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
+ /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h \
+ /usr/lib/gcc/x86_64-redhat-linux/4.3.2/include/stddef.h \
+ /usr/include/bits/types.h /usr/include/bits/typesizes.h \
+ /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
+ /usr/lib/gcc/x86_64-redhat-linux/4.3.2/include/stdarg.h \
+ /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
+ /usr/include/unistd.h /usr/include/bits/posix_opt.h \
+ /usr/include/bits/confname.h /usr/include/getopt.h \
+ /usr/include/sys/types.h /usr/include/time.h /usr/include/endian.h \
+ /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
+ /usr/include/sys/select.h /usr/include/bits/select.h \
+ /usr/include/bits/sigset.h /usr/include/bits/time.h \
+ /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
+ /usr/include/sys/stat.h /usr/include/bits/stat.h /usr/include/fcntl.h \
+ /usr/include/bits/fcntl.h /usr/include/signal.h \
+ /usr/include/bits/signum.h /usr/include/bits/siginfo.h \
+ /usr/include/bits/sigaction.h /usr/include/bits/sigcontext.h \
+ /usr/include/bits/sigstack.h /usr/include/bits/sigthread.h \
+ /usr/include/sched.h /usr/include/bits/sched.h /usr/include/errno.h \
+ /usr/include/bits/errno.h /usr/include/linux/errno.h \
+ /usr/include/asm/errno.h /usr/include/asm-generic/errno.h \
+ /usr/include/asm-generic/errno-base.h server.h ssl.h \
+ /usr/include/openssl/x509v3.h /usr/include/openssl/bio.h \
+ /usr/include/openssl/e_os2.h /usr/include/openssl/opensslconf.h \
+ /usr/include/openssl/opensslconf-x86_64.h /usr/include/openssl/crypto.h \
+ /usr/include/stdlib.h /usr/include/alloca.h \
+ /usr/include/openssl/stack.h /usr/include/openssl/safestack.h \
+ /usr/include/openssl/opensslv.h /usr/include/openssl/ossl_typ.h \
+ /usr/include/openssl/symhacks.h /usr/include/openssl/x509.h \
+ /usr/include/openssl/buffer.h /usr/include/openssl/evp.h \
+ /usr/include/openssl/objects.h /usr/include/openssl/obj_mac.h \
+ /usr/include/openssl/asn1.h /usr/include/openssl/bn.h \
+ /usr/include/openssl/rsa.h /usr/include/openssl/dsa.h \
+ /usr/include/openssl/dh.h /usr/include/openssl/sha.h \
+ /usr/include/openssl/x509_vfy.h /usr/include/openssl/lhash.h \
+ /usr/include/openssl/pkcs7.h /usr/include/openssl/conf.h \
+ /usr/include/openssl/ssl.h /usr/include/openssl/comp.h \
+ /usr/include/openssl/pem.h /usr/include/openssl/pem2.h \
+ /usr/include/openssl/kssl.h /usr/include/ctype.h /usr/include/krb5.h \
+ /usr/include/krb5/krb5.h \
+ /usr/lib/gcc/x86_64-redhat-linux/4.3.2/include/limits.h \
+ /usr/lib/gcc/x86_64-redhat-linux/4.3.2/include/syslimits.h \
+ /usr/include/limits.h /usr/include/bits/posix1_lim.h \
+ /usr/include/bits/local_lim.h /usr/include/linux/limits.h \
+ /usr/include/bits/posix2_lim.h /usr/include/et/com_err.h \
+ /usr/include/openssl/ssl2.h /usr/include/openssl/ssl3.h \
+ /usr/include/openssl/pq_compat.h /usr/include/openssl/tls1.h \
+ /usr/include/openssl/dtls1.h /usr/include/openssl/pqueue.h \
+ /usr/include/string.h /usr/include/openssl/ssl23.h types.h channel.h \
+ log.h list.h client.h /usr/include/stdint.h /usr/include/bits/wchar.h \
+ /usr/include/sys/socket.h /usr/include/sys/uio.h \
+ /usr/include/bits/uio.h /usr/include/bits/socket.h \
+ /usr/include/bits/sockaddr.h /usr/include/asm/socket.h \
+ /usr/include/asm/sockios.h /usr/include/netinet/in.h \
+ /usr/include/bits/in.h /usr/include/arpa/inet.h /usr/include/sys/poll.h \
+ /usr/include/bits/poll.h messages.h /usr/include/openssl/aes.h crypt.h \
+ /usr/include/openssl/rand.h timer.h conf.h
+messages.o: messages.c /usr/include/stdlib.h /usr/include/features.h \
+ /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
+ /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h \
+ /usr/lib/gcc/x86_64-redhat-linux/4.3.2/include/stddef.h \
+ /usr/include/sys/types.h /usr/include/bits/types.h \
+ /usr/include/bits/typesizes.h /usr/include/time.h /usr/include/endian.h \
+ /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
+ /usr/include/sys/select.h /usr/include/bits/select.h \
+ /usr/include/bits/sigset.h /usr/include/bits/time.h \
+ /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
+ /usr/include/alloca.h /usr/include/stdio.h /usr/include/libio.h \
+ /usr/include/_G_config.h /usr/include/wchar.h \
+ /usr/lib/gcc/x86_64-redhat-linux/4.3.2/include/stdarg.h \
+ /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
+ /usr/include/string.h messages.h /usr/include/stdint.h \
+ /usr/include/bits/wchar.h /usr/include/openssl/aes.h \
+ /usr/include/openssl/opensslconf.h \
+ /usr/include/openssl/opensslconf-x86_64.h list.h types.h pds.h log.h
+pds.o: pds.c /usr/include/string.h /usr/include/features.h \
+ /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
+ /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h \
+ /usr/lib/gcc/x86_64-redhat-linux/4.3.2/include/stddef.h \
+ /usr/include/stdlib.h /usr/include/sys/types.h \
+ /usr/include/bits/types.h /usr/include/bits/typesizes.h \
+ /usr/include/time.h /usr/include/endian.h /usr/include/bits/endian.h \
+ /usr/include/bits/byteswap.h /usr/include/sys/select.h \
+ /usr/include/bits/select.h /usr/include/bits/sigset.h \
+ /usr/include/bits/time.h /usr/include/sys/sysmacros.h \
+ /usr/include/bits/pthreadtypes.h /usr/include/alloca.h pds.h \
+ /usr/include/stdint.h /usr/include/bits/wchar.h types.h log.h
+server.o: server.c /usr/include/stdio.h /usr/include/features.h \
+ /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
+ /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h \
+ /usr/lib/gcc/x86_64-redhat-linux/4.3.2/include/stddef.h \
+ /usr/include/bits/types.h /usr/include/bits/typesizes.h \
+ /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
+ /usr/lib/gcc/x86_64-redhat-linux/4.3.2/include/stdarg.h \
+ /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
+ /usr/include/sys/time.h /usr/include/time.h /usr/include/bits/time.h \
+ /usr/include/sys/select.h /usr/include/bits/select.h \
+ /usr/include/bits/sigset.h /usr/include/sys/poll.h \
+ /usr/include/bits/poll.h /usr/include/netinet/tcp.h \
+ /usr/include/sys/types.h /usr/include/endian.h \
+ /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
+ /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
+ /usr/include/sys/socket.h /usr/include/sys/uio.h \
+ /usr/include/bits/uio.h /usr/include/bits/socket.h \
+ /usr/include/bits/sockaddr.h /usr/include/asm/socket.h \
+ /usr/include/asm/sockios.h /usr/include/errno.h \
+ /usr/include/bits/errno.h /usr/include/linux/errno.h \
+ /usr/include/asm/errno.h /usr/include/asm-generic/errno.h \
+ /usr/include/asm-generic/errno-base.h /usr/include/string.h \
+ /usr/lib/gcc/x86_64-redhat-linux/4.3.2/include/limits.h \
+ /usr/lib/gcc/x86_64-redhat-linux/4.3.2/include/syslimits.h \
+ /usr/include/limits.h /usr/include/bits/posix1_lim.h \
+ /usr/include/bits/local_lim.h /usr/include/linux/limits.h \
+ /usr/include/bits/posix2_lim.h /usr/include/unistd.h \
+ /usr/include/bits/posix_opt.h /usr/include/bits/confname.h \
+ /usr/include/getopt.h /usr/include/fcntl.h /usr/include/bits/fcntl.h \
+ client.h /usr/include/openssl/ssl.h /usr/include/openssl/e_os2.h \
+ /usr/include/openssl/opensslconf.h \
+ /usr/include/openssl/opensslconf-x86_64.h /usr/include/openssl/comp.h \
+ /usr/include/openssl/crypto.h /usr/include/stdlib.h \
+ /usr/include/alloca.h /usr/include/openssl/stack.h \
+ /usr/include/openssl/safestack.h /usr/include/openssl/opensslv.h \
+ /usr/include/openssl/ossl_typ.h /usr/include/openssl/symhacks.h \
+ /usr/include/openssl/bio.h /usr/include/openssl/x509.h \
+ /usr/include/openssl/buffer.h /usr/include/openssl/evp.h \
+ /usr/include/openssl/objects.h /usr/include/openssl/obj_mac.h \
+ /usr/include/openssl/asn1.h /usr/include/openssl/bn.h \
+ /usr/include/openssl/rsa.h /usr/include/openssl/dsa.h \
+ /usr/include/openssl/dh.h /usr/include/openssl/sha.h \
+ /usr/include/openssl/x509_vfy.h /usr/include/openssl/lhash.h \
+ /usr/include/openssl/pkcs7.h /usr/include/openssl/pem.h \
+ /usr/include/openssl/pem2.h /usr/include/openssl/kssl.h \
+ /usr/include/ctype.h /usr/include/krb5.h /usr/include/krb5/krb5.h \
+ /usr/include/et/com_err.h /usr/include/openssl/ssl2.h \
+ /usr/include/openssl/ssl3.h /usr/include/openssl/pq_compat.h \
+ /usr/include/openssl/tls1.h /usr/include/openssl/dtls1.h \
+ /usr/include/openssl/pqueue.h /usr/include/openssl/ssl23.h \
+ /usr/include/stdint.h /usr/include/bits/wchar.h \
+ /usr/include/netinet/in.h /usr/include/bits/in.h \
+ /usr/include/arpa/inet.h list.h types.h messages.h \
+ /usr/include/openssl/aes.h crypt.h /usr/include/openssl/rand.h timer.h \
+ conf.h log.h
+ssl.o: ssl.c /usr/include/openssl/x509v3.h /usr/include/openssl/bio.h \
+ /usr/include/openssl/e_os2.h /usr/include/openssl/opensslconf.h \
+ /usr/include/openssl/opensslconf-x86_64.h /usr/include/stdio.h \
+ /usr/include/features.h /usr/include/sys/cdefs.h \
+ /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
+ /usr/include/gnu/stubs-64.h \
+ /usr/lib/gcc/x86_64-redhat-linux/4.3.2/include/stddef.h \
+ /usr/include/bits/types.h /usr/include/bits/typesizes.h \
+ /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
+ /usr/lib/gcc/x86_64-redhat-linux/4.3.2/include/stdarg.h \
+ /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
+ /usr/include/openssl/crypto.h /usr/include/stdlib.h \
+ /usr/include/sys/types.h /usr/include/time.h /usr/include/endian.h \
+ /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
+ /usr/include/sys/select.h /usr/include/bits/select.h \
+ /usr/include/bits/sigset.h /usr/include/bits/time.h \
+ /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
+ /usr/include/alloca.h /usr/include/openssl/stack.h \
+ /usr/include/openssl/safestack.h /usr/include/openssl/opensslv.h \
+ /usr/include/openssl/ossl_typ.h /usr/include/openssl/symhacks.h \
+ /usr/include/openssl/x509.h /usr/include/openssl/buffer.h \
+ /usr/include/openssl/evp.h /usr/include/openssl/objects.h \
+ /usr/include/openssl/obj_mac.h /usr/include/openssl/asn1.h \
+ /usr/include/openssl/bn.h /usr/include/openssl/rsa.h \
+ /usr/include/openssl/dsa.h /usr/include/openssl/dh.h \
+ /usr/include/openssl/sha.h /usr/include/openssl/x509_vfy.h \
+ /usr/include/openssl/lhash.h /usr/include/openssl/pkcs7.h \
+ /usr/include/openssl/conf.h /usr/include/openssl/ssl.h \
+ /usr/include/openssl/comp.h /usr/include/openssl/pem.h \
+ /usr/include/openssl/pem2.h /usr/include/openssl/kssl.h \
+ /usr/include/ctype.h /usr/include/krb5.h /usr/include/krb5/krb5.h \
+ /usr/lib/gcc/x86_64-redhat-linux/4.3.2/include/limits.h \
+ /usr/lib/gcc/x86_64-redhat-linux/4.3.2/include/syslimits.h \
+ /usr/include/limits.h /usr/include/bits/posix1_lim.h \
+ /usr/include/bits/local_lim.h /usr/include/linux/limits.h \
+ /usr/include/bits/posix2_lim.h /usr/include/et/com_err.h \
+ /usr/include/openssl/ssl2.h /usr/include/openssl/ssl3.h \
+ /usr/include/openssl/pq_compat.h /usr/include/openssl/tls1.h \
+ /usr/include/openssl/dtls1.h /usr/include/openssl/pqueue.h \
+ /usr/include/string.h /usr/include/openssl/ssl23.h \
+ /usr/include/openssl/err.h /usr/include/errno.h \
+ /usr/include/bits/errno.h /usr/include/linux/errno.h \
+ /usr/include/asm/errno.h /usr/include/asm-generic/errno.h \
+ /usr/include/asm-generic/errno-base.h conf.h messages.h \
+ /usr/include/stdint.h /usr/include/bits/wchar.h \
+ /usr/include/openssl/aes.h list.h types.h log.h ssl.h
+log.o: log.c /usr/lib/gcc/x86_64-redhat-linux/4.3.2/include/stdarg.h \
+ /usr/include/stdio.h /usr/include/features.h /usr/include/sys/cdefs.h \
+ /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
+ /usr/include/gnu/stubs-64.h \
+ /usr/lib/gcc/x86_64-redhat-linux/4.3.2/include/stddef.h \
+ /usr/include/bits/types.h /usr/include/bits/typesizes.h \
+ /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
+ /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
+ /usr/include/stdlib.h /usr/include/sys/types.h /usr/include/time.h \
+ /usr/include/endian.h /usr/include/bits/endian.h \
+ /usr/include/bits/byteswap.h /usr/include/sys/select.h \
+ /usr/include/bits/select.h /usr/include/bits/sigset.h \
+ /usr/include/bits/time.h /usr/include/sys/sysmacros.h \
+ /usr/include/bits/pthreadtypes.h /usr/include/alloca.h \
+ /usr/include/syslog.h /usr/include/sys/syslog.h \
+ /usr/include/bits/syslog-path.h /usr/include/string.h log.h types.h
+conf.o: conf.c /usr/include/stdio.h /usr/include/features.h \
+ /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
+ /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h \
+ /usr/lib/gcc/x86_64-redhat-linux/4.3.2/include/stddef.h \
+ /usr/include/bits/types.h /usr/include/bits/typesizes.h \
+ /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
+ /usr/lib/gcc/x86_64-redhat-linux/4.3.2/include/stdarg.h \
+ /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
+ /usr/include/stdlib.h /usr/include/sys/types.h /usr/include/time.h \
+ /usr/include/endian.h /usr/include/bits/endian.h \
+ /usr/include/bits/byteswap.h /usr/include/sys/select.h \
+ /usr/include/bits/select.h /usr/include/bits/sigset.h \
+ /usr/include/bits/time.h /usr/include/sys/sysmacros.h \
+ /usr/include/bits/pthreadtypes.h /usr/include/alloca.h \
+ /usr/include/string.h /usr/include/libconfig.h types.h conf.h \
+ messages.h /usr/include/stdint.h /usr/include/bits/wchar.h \
+ /usr/include/openssl/aes.h /usr/include/openssl/opensslconf.h \
+ /usr/include/openssl/opensslconf-x86_64.h list.h log.h
+crypt.o: crypt.c /usr/include/string.h /usr/include/features.h \
+ /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
+ /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h \
+ /usr/lib/gcc/x86_64-redhat-linux/4.3.2/include/stddef.h \
+ /usr/include/arpa/inet.h /usr/include/netinet/in.h \
+ /usr/include/stdint.h /usr/include/bits/wchar.h \
+ /usr/include/sys/socket.h /usr/include/sys/uio.h \
+ /usr/include/sys/types.h /usr/include/bits/types.h \
+ /usr/include/bits/typesizes.h /usr/include/time.h /usr/include/endian.h \
+ /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
+ /usr/include/sys/select.h /usr/include/bits/select.h \
+ /usr/include/bits/sigset.h /usr/include/bits/time.h \
+ /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
+ /usr/include/bits/uio.h /usr/include/bits/socket.h \
+ /usr/include/bits/sockaddr.h /usr/include/asm/socket.h \
+ /usr/include/asm/sockios.h /usr/include/bits/in.h crypt.h \
+ /usr/include/openssl/rand.h /usr/include/stdlib.h /usr/include/alloca.h \
+ /usr/include/openssl/ossl_typ.h /usr/include/openssl/e_os2.h \
+ /usr/include/openssl/opensslconf.h \
+ /usr/include/openssl/opensslconf-x86_64.h /usr/include/openssl/aes.h \
+ timer.h types.h log.h
+timer.o: timer.c /usr/include/sys/time.h /usr/include/features.h \
+ /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
+ /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h \
+ /usr/include/bits/types.h /usr/include/bits/typesizes.h \
+ /usr/include/time.h /usr/include/bits/time.h /usr/include/sys/select.h \
+ /usr/include/bits/select.h /usr/include/bits/sigset.h \
+ /usr/include/stdint.h /usr/include/bits/wchar.h /usr/include/stdio.h \
+ /usr/lib/gcc/x86_64-redhat-linux/4.3.2/include/stddef.h \
+ /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
+ /usr/lib/gcc/x86_64-redhat-linux/4.3.2/include/stdarg.h \
+ /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h timer.h \
+ types.h
+messagehandler.o: messagehandler.c /usr/include/string.h \
+ /usr/include/features.h /usr/include/sys/cdefs.h \
+ /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
+ /usr/include/gnu/stubs-64.h \
+ /usr/lib/gcc/x86_64-redhat-linux/4.3.2/include/stddef.h \
+ /usr/include/openssl/aes.h /usr/include/openssl/opensslconf.h \
+ /usr/include/openssl/opensslconf-x86_64.h log.h types.h list.h client.h \
+ /usr/include/openssl/ssl.h /usr/include/openssl/e_os2.h \
+ /usr/include/openssl/comp.h /usr/include/openssl/crypto.h \
+ /usr/include/stdlib.h /usr/include/sys/types.h \
+ /usr/include/bits/types.h /usr/include/bits/typesizes.h \
+ /usr/include/time.h /usr/include/endian.h /usr/include/bits/endian.h \
+ /usr/include/bits/byteswap.h /usr/include/sys/select.h \
+ /usr/include/bits/select.h /usr/include/bits/sigset.h \
+ /usr/include/bits/time.h /usr/include/sys/sysmacros.h \
+ /usr/include/bits/pthreadtypes.h /usr/include/alloca.h \
+ /usr/include/stdio.h /usr/include/libio.h /usr/include/_G_config.h \
+ /usr/include/wchar.h \
+ /usr/lib/gcc/x86_64-redhat-linux/4.3.2/include/stdarg.h \
+ /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
+ /usr/include/openssl/stack.h /usr/include/openssl/safestack.h \
+ /usr/include/openssl/opensslv.h /usr/include/openssl/ossl_typ.h \
+ /usr/include/openssl/symhacks.h /usr/include/openssl/bio.h \
+ /usr/include/openssl/x509.h /usr/include/openssl/buffer.h \
+ /usr/include/openssl/evp.h /usr/include/openssl/objects.h \
+ /usr/include/openssl/obj_mac.h /usr/include/openssl/asn1.h \
+ /usr/include/openssl/bn.h /usr/include/openssl/rsa.h \
+ /usr/include/openssl/dsa.h /usr/include/openssl/dh.h \
+ /usr/include/openssl/sha.h /usr/include/openssl/x509_vfy.h \
+ /usr/include/openssl/lhash.h /usr/include/openssl/pkcs7.h \
+ /usr/include/openssl/pem.h /usr/include/openssl/pem2.h \
+ /usr/include/openssl/kssl.h /usr/include/ctype.h /usr/include/krb5.h \
+ /usr/include/krb5/krb5.h \
+ /usr/lib/gcc/x86_64-redhat-linux/4.3.2/include/limits.h \
+ /usr/lib/gcc/x86_64-redhat-linux/4.3.2/include/syslimits.h \
+ /usr/include/limits.h /usr/include/bits/posix1_lim.h \
+ /usr/include/bits/local_lim.h /usr/include/linux/limits.h \
+ /usr/include/bits/posix2_lim.h /usr/include/et/com_err.h \
+ /usr/include/openssl/ssl2.h /usr/include/openssl/ssl3.h \
+ /usr/include/openssl/pq_compat.h /usr/include/openssl/tls1.h \
+ /usr/include/openssl/dtls1.h /usr/include/openssl/pqueue.h \
+ /usr/include/openssl/ssl23.h /usr/include/stdint.h \
+ /usr/include/bits/wchar.h /usr/include/unistd.h \
+ /usr/include/bits/posix_opt.h /usr/include/bits/confname.h \
+ /usr/include/getopt.h /usr/include/sys/socket.h /usr/include/sys/uio.h \
+ /usr/include/bits/uio.h /usr/include/bits/socket.h \
+ /usr/include/bits/sockaddr.h /usr/include/asm/socket.h \
+ /usr/include/asm/sockios.h /usr/include/netinet/in.h \
+ /usr/include/bits/in.h /usr/include/arpa/inet.h /usr/include/errno.h \
+ /usr/include/bits/errno.h /usr/include/linux/errno.h \
+ /usr/include/asm/errno.h /usr/include/asm-generic/errno.h \
+ /usr/include/asm-generic/errno-base.h /usr/include/sys/poll.h \
+ /usr/include/bits/poll.h messages.h crypt.h /usr/include/openssl/rand.h \
+ timer.h channel.h conf.h
+channel.o: channel.c log.h types.h list.h client.h \
+ /usr/include/openssl/ssl.h /usr/include/openssl/e_os2.h \
+ /usr/include/openssl/opensslconf.h \
+ /usr/include/openssl/opensslconf-x86_64.h /usr/include/openssl/comp.h \
+ /usr/include/openssl/crypto.h /usr/include/stdlib.h \
+ /usr/include/features.h /usr/include/sys/cdefs.h \
+ /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
+ /usr/include/gnu/stubs-64.h \
+ /usr/lib/gcc/x86_64-redhat-linux/4.3.2/include/stddef.h \
+ /usr/include/sys/types.h /usr/include/bits/types.h \
+ /usr/include/bits/typesizes.h /usr/include/time.h /usr/include/endian.h \
+ /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
+ /usr/include/sys/select.h /usr/include/bits/select.h \
+ /usr/include/bits/sigset.h /usr/include/bits/time.h \
+ /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
+ /usr/include/alloca.h /usr/include/stdio.h /usr/include/libio.h \
+ /usr/include/_G_config.h /usr/include/wchar.h \
+ /usr/lib/gcc/x86_64-redhat-linux/4.3.2/include/stdarg.h \
+ /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
+ /usr/include/openssl/stack.h /usr/include/openssl/safestack.h \
+ /usr/include/openssl/opensslv.h /usr/include/openssl/ossl_typ.h \
+ /usr/include/openssl/symhacks.h /usr/include/openssl/bio.h \
+ /usr/include/openssl/x509.h /usr/include/openssl/buffer.h \
+ /usr/include/openssl/evp.h /usr/include/openssl/objects.h \
+ /usr/include/openssl/obj_mac.h /usr/include/openssl/asn1.h \
+ /usr/include/openssl/bn.h /usr/include/openssl/rsa.h \
+ /usr/include/openssl/dsa.h /usr/include/openssl/dh.h \
+ /usr/include/openssl/sha.h /usr/include/openssl/x509_vfy.h \
+ /usr/include/openssl/lhash.h /usr/include/openssl/pkcs7.h \
+ /usr/include/openssl/pem.h /usr/include/openssl/pem2.h \
+ /usr/include/openssl/kssl.h /usr/include/ctype.h /usr/include/krb5.h \
+ /usr/include/krb5/krb5.h \
+ /usr/lib/gcc/x86_64-redhat-linux/4.3.2/include/limits.h \
+ /usr/lib/gcc/x86_64-redhat-linux/4.3.2/include/syslimits.h \
+ /usr/include/limits.h /usr/include/bits/posix1_lim.h \
+ /usr/include/bits/local_lim.h /usr/include/linux/limits.h \
+ /usr/include/bits/posix2_lim.h /usr/include/et/com_err.h \
+ /usr/include/openssl/ssl2.h /usr/include/openssl/ssl3.h \
+ /usr/include/openssl/pq_compat.h /usr/include/openssl/tls1.h \
+ /usr/include/openssl/dtls1.h /usr/include/openssl/pqueue.h \
+ /usr/include/string.h /usr/include/openssl/ssl23.h \
+ /usr/include/stdint.h /usr/include/bits/wchar.h /usr/include/unistd.h \
+ /usr/include/bits/posix_opt.h /usr/include/bits/confname.h \
+ /usr/include/getopt.h /usr/include/sys/socket.h /usr/include/sys/uio.h \
+ /usr/include/bits/uio.h /usr/include/bits/socket.h \
+ /usr/include/bits/sockaddr.h /usr/include/asm/socket.h \
+ /usr/include/asm/sockios.h /usr/include/netinet/in.h \
+ /usr/include/bits/in.h /usr/include/arpa/inet.h /usr/include/errno.h \
+ /usr/include/bits/errno.h /usr/include/linux/errno.h \
+ /usr/include/asm/errno.h /usr/include/asm-generic/errno.h \
+ /usr/include/asm-generic/errno-base.h /usr/include/sys/poll.h \
+ /usr/include/bits/poll.h messages.h /usr/include/openssl/aes.h crypt.h \
+ /usr/include/openssl/rand.h timer.h channel.h conf.h
--- /dev/null
+#ifndef LIST_H_87698769870987
+#define LIST_H_87698769870987
+
+struct dlist {
+ struct dlist *next, *prev;
+};
+
+#define init_list_entry(ptr) \
+ do { \
+ (ptr)->prev = ptr; (ptr)->next = ptr; } \
+ while(0);
+#define declare_list(_name_) struct dlist _name_ = {&(_name_), &(_name_) }
+
+static inline void list_add_head(struct dlist *new, struct dlist *list)
+{
+ list->next->prev = new;
+ new->prev = list;
+ new->next = list->next;
+ list->next = new;
+}
+
+static inline void list_add_tail(struct dlist *new, struct dlist *list)
+{
+ list->prev->next = new;
+ new->prev = list->prev;
+ new->next = list;
+ list->prev = new;
+}
+static inline void list_del(struct dlist *entry)
+{
+ entry->next->prev = entry->prev;
+ entry->prev->next = entry->next;
+}
+
+static inline int list_empty(struct dlist *list)
+{
+ return list->next == list;
+}
+
+#define list_get_first(listhead) \
+ ((listhead)->next)
+
+#define list_get_next(_entry_) \
+ ((_entry_)->next)
+
+#define list_get_entry(entry, type, structmember) \
+ ((type *) ((char *)(entry) - (unsigned long)(&((type *)0)->structmember)))
+
+#define list_iterate(entry, listhead) \
+ for(entry = (listhead)->next; entry != (listhead); entry = entry->next)
+
+#define list_iterate_safe(entry, save, listhead) \
+ for(entry = (listhead)->next, save = entry->next; entry != (listhead); \
+ entry = save, save = save->next)
+
+
+#endif /* #ifndef LIST_H_87698769870987 */
--- /dev/null
+/* Copyright (C) 2009, Martin Johansson <martin@fatbob.nu>
+ Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ - Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ - Neither the name of the Developers nor the names of its contributors may
+ be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <syslog.h>
+#include <string.h>
+
+#include "log.h"
+
+#define BUFSIZE 254
+
+static bool_t termprint;
+
+void Log_init(bool_t terminal)
+{
+ termprint = terminal;
+ if (!termprint)
+ openlog("uMurmud", LOG_PID, LOG_DAEMON);
+}
+
+void Log_free()
+{
+ if (!termprint)
+ closelog();
+}
+
+
+void logthis(const char *logstring, ...)
+{
+ va_list argp;
+ char buf[BUFSIZE + 2];
+
+ va_start(argp, logstring);
+ vsnprintf(&buf[0], BUFSIZE, logstring, argp);
+ va_end(argp);
+ strcat(buf, "\n");
+ if (termprint)
+ fprintf(stderr, "%s", buf); /* XXX - other targets for logging */
+ else
+ syslog(LOG_INFO, buf);
+}
+
+void Log_warn(const char *logstring, ...)
+{
+ va_list argp;
+ char buf[BUFSIZE + 2];
+ int offset = 0;
+
+ va_start(argp, logstring);
+ offset = sprintf(buf, "WARN: ");
+ vsnprintf(&buf[offset], BUFSIZE - offset, logstring, argp);
+ va_end(argp);
+ strcat(buf, "\n");
+ if (termprint)
+ fprintf(stderr, "%s", buf); /* XXX - other targets for logging */
+ else
+ syslog(LOG_ALERT, buf);
+}
+
+void Log_info(const char *logstring, ...)
+{
+ va_list argp;
+ char buf[BUFSIZE + 2];
+ int offset = 0;
+
+ va_start(argp, logstring);
+ offset = sprintf(buf, "INFO: ");
+ vsnprintf(&buf[offset], BUFSIZE - offset, logstring, argp);
+ va_end(argp);
+ strcat(buf, "\n");
+ if (termprint)
+ fprintf(stderr, "%s", buf); /* XXX - other targets for logging */
+ else
+ syslog(LOG_ALERT, buf);
+}
+
+#ifdef DEBUG
+void Log_debug(const char *logstring, ...)
+{
+ va_list argp;
+ char buf[BUFSIZE + 2];
+ int offset = 0;
+
+ va_start(argp, logstring);
+ offset = sprintf(buf, "DEBUG: ");
+ vsnprintf(&buf[offset], BUFSIZE - offset, logstring, argp);
+ va_end(argp);
+ strcat(buf, "\n");
+ if (termprint)
+ fprintf(stderr, "%s", buf); /* XXX - other targets for logging */
+ else
+ syslog(LOG_INFO, buf);
+}
+#endif
+
+void Log_fatal(const char *logstring, ...)
+{
+ va_list argp;
+ char buf[BUFSIZE + 2];
+ int offset = 0;
+ va_start(argp, logstring);
+ offset = sprintf(buf, "FATAL: ");
+ vsnprintf(&buf[offset], BUFSIZE - offset, logstring, argp);
+ va_end(argp);
+ strcat(buf, "\n");
+ if (termprint)
+ fprintf(stderr, "%s", buf); /* XXX - other targets for logging */
+ else
+ syslog(LOG_INFO, buf);
+ exit(1);
+}
--- /dev/null
+/* Copyright (C) 2009, Martin Johansson <martin@fatbob.nu>
+ Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ - Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ - Neither the name of the Developers nor the names of its contributors may
+ be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef LOG_H_2435642356
+#define LOG_H_2435642356
+
+#include "types.h"
+
+#define doAssert(_cond_) do { \
+ if (!(_cond_)) { \
+ logthis("Assertion failed in %s: Line: %d Function: %s", __FILE__, __LINE__, __FUNCTION__); \
+ abort(); \
+ } \
+ } while (0)
+
+
+void logthis(const char *logstring, ...);
+
+#ifdef DEBUG
+void Log_debug(const char *logstring, ...);
+#else
+#define Log_debug(_args_, ...) ((void)0)
+#endif
+
+void Log_warn(const char *logstring, ...);
+void Log_info(const char *logstring, ...);
+void Log_fatal(const char *logstring, ...);
+
+void Log_init(bool_t terminal);
+void Log_free();
+
+#endif
+
--- /dev/null
+/* Copyright (C) 2009, Martin Johansson <martin@fatbob.nu>
+ Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ - Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ - Neither the name of the Developers nor the names of its contributors may
+ be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sched.h>
+#include <errno.h>
+
+#include "server.h"
+#include "ssl.h"
+#include "channel.h"
+#include "log.h"
+#include "client.h"
+#include "conf.h"
+
+#define UMURMUR_VERSION "0.1.0"
+
+void lockfile(const char *pidfile)
+{
+ int lfp;
+ char str[16];
+
+ lfp = open(pidfile, O_RDWR|O_CREAT, 0640);
+
+ if (lfp < 0)
+ Log_fatal("Cannot open PID-file %s for writing", pidfile);
+ sprintf(str,"%d\n",getpid());
+ write(lfp, str, strlen(str)); /* record pid to lockfile */
+ Log_info("PID-file: %s", pidfile);
+}
+
+
+void signal_handler(int sig)
+{
+ switch(sig) {
+ case SIGHUP:
+ /* XXX - do stuff? */
+ Log_info("HUP signal");
+ break;
+ case SIGTERM:
+ Log_info("TERM signal. Shutting down.");
+ Server_shutdown();
+ break;
+ }
+}
+
+void daemonize()
+{
+ int i;
+
+ if (getppid() == 1)
+ return; /* already a daemon */
+ i = fork();
+ if ( i < 0) {
+ fprintf(stderr, "Fork error. Exiting\n");
+ exit(1); /* fork error */
+ }
+ if ( i > 0)
+ exit(0); /* parent exits */
+
+ /* child (daemon) continues */
+ setsid(); /* obtain a new process group */
+ for (i = getdtablesize(); i >= 0; --i)
+ close(i); /* close all descriptors */
+
+ i = open("/dev/null",O_RDWR);
+ dup(i);
+ dup(i);
+
+ umask(027); /* set newly created file permissions */
+ chdir("/");
+
+}
+
+void setscheduler()
+{
+ int rc;
+ struct sched_param sp;
+
+ sp.sched_priority = sched_get_priority_min(SCHED_RR); /* Should suffice */
+ Log_info("Setting SCHED_RR prio %d", sp.sched_priority);
+ rc = sched_setscheduler(0, SCHED_RR, &sp);
+ if (rc < 0)
+ Log_warn("Failed to set scheduler: %s", strerror(errno));
+}
+
+void printhelp()
+{
+ printf("uMurmur version %s. Mumble protocol %d\n", UMURMUR_VERSION, MESSAGE_STREAM_VERSION);
+ printf("Usage: umurmurd [-d] [-p <pidfile>] [-c <conf file>] [-h]\n");
+ printf(" -d - Do not deamonize\n");
+ printf(" -p <pidfile> - Write PID to this file\n");
+ printf(" -c <conf file> - Specify configuration file\n");
+ printf(" -h - Print this help\n");
+ exit(0);
+}
+
+int main(int argc, char **argv)
+{
+ bool_t nodaemon = false;
+ char *conffile = NULL, *pidfile = NULL;
+ int c;
+
+ /* Arguments */
+ while ((c = getopt(argc, argv, "dp:c:h")) != EOF) {
+ switch(c) {
+ case 'c':
+ conffile = optarg;
+ break;
+ case 'p':
+ pidfile = optarg;
+ break;
+ case 'd':
+ nodaemon = true;
+ break;
+ case 'h':
+ printhelp();
+ break;
+ default:
+ fprintf(stderr, "Unrecognized option\n");
+ printhelp();
+ break;
+ }
+ }
+
+ if (Conf_init(conffile) != 0) {
+ fprintf(stderr, "Configuration error\n");
+ exit(1);
+ }
+
+ if (!nodaemon) {
+ Log_init(false);
+ daemonize();
+ if (pidfile != NULL)
+ lockfile(pidfile);
+ }
+ else
+ Log_init(true);
+
+ signal(SIGCHLD, SIG_IGN); /* ignore child */
+ signal(SIGTSTP, SIG_IGN); /* ignore tty signals */
+ signal(SIGTTOU, SIG_IGN);
+ signal(SIGTTIN, SIG_IGN);
+ signal(SIGHUP, signal_handler); /* catch hangup signal */
+ signal(SIGTERM, signal_handler); /* catch kill signal */
+
+ /* Initializing */
+ SSL_init();
+ Chan_init();
+ Client_init();
+
+ setscheduler();
+ Server_run();
+
+ SSL_deinit();
+ Chan_free();
+ Log_free();
+ Conf_deinit();
+
+ if (pidfile != NULL)
+ unlink(pidfile);
+
+ return 0;
+}
--- /dev/null
+/* Copyright (C) 2009, Martin Johansson <martin@fatbob.nu>
+ Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ - Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ - Neither the name of the Developers nor the names of its contributors may
+ be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#include <string.h>
+#include <openssl/aes.h>
+
+#include "log.h"
+#include "list.h"
+#include "client.h"
+#include "messages.h"
+#include "crypt.h"
+#include "channel.h"
+#include "conf.h"
+
+extern channel_t *defaultChan;
+
+static void sendServerReject(client_t *client, const char *reason, rejectType_t type)
+{
+ message_t *msg = Msg_create(ServerReject);
+ msg->sessionId = client->sessionId;
+ strcpy(msg->payload.serverReject.reason, reason);
+ msg->payload.serverReject.type = type;
+ Client_send_message(client, msg);
+}
+
+static void sendPermissionDenied(client_t *client, const char *reason)
+{
+ message_t *msg = Msg_create(PermissionDenied);
+ msg->sessionId = client->sessionId;
+ strncpy(msg->payload.permissionDenied.reason, reason, MAX_TEXT);
+ Client_send_message(client, msg);
+}
+
+void Mh_handle_message(client_t *client, message_t *msg)
+{
+ message_t *sendmsg;
+ channel_t *ch_itr = NULL;
+ client_t *client_itr;
+
+ switch (msg->messageType) {
+ case ServerAuthenticate:
+ /*
+ * 1. Check stuff, Serverreject if not ok
+ * 2. Setup UDP encryption -> MessageCryptSetup
+ * 3. (Enter channel)
+ * 4. MessageChannelAdd + MessageChannelDescUpdate for all channels
+ * 5. (MessageChannelLink)
+ * 6. MessageServerJoin
+ * 7. MessagePlayerMove
+ * 8. MessageServerJoin for all connected users
+ * 9. PlayerDeaf/PlayerMute/PlayerSelfMuteDeaf for all users it applies to
+ * 10. MessageServerSync
+ */
+ if (msg->payload.serverAuthenticate.version != MESSAGE_STREAM_VERSION) {
+ char buf[64];
+ sprintf(buf, "Wrong version of mumble protocol (client: %d, server: %d)",
+ msg->payload.serverAuthenticate.version, MESSAGE_STREAM_VERSION);
+ sendServerReject(client, buf, WrongVersion);
+ goto disconnect;
+ }
+
+ client_itr = NULL;
+ while (Client_iterate(&client_itr) != NULL) {
+ if (!IS_AUTH(client_itr))
+ continue;
+ if (strncmp(client_itr->playerName, msg->payload.serverAuthenticate.userName, MAX_TEXT) == 0) {
+ char buf[64];
+ sprintf(buf, "Username already in use");
+ sendServerReject(client, buf, UsernameInUse);
+ goto disconnect;
+ }
+ }
+
+ if (strncmp(getStrConf(PASSPHRASE), msg->payload.serverAuthenticate.password, MAX_TEXT) != 0) {
+ char buf[64];
+ sprintf(buf, "Wrong server password");
+ sendServerReject(client, buf, WrongServerPW);
+ goto disconnect;
+ }
+
+ if (strlen(msg->payload.serverAuthenticate.userName) == 0) { /* XXX - other invalid names? */
+ char buf[64];
+ sprintf(buf, "Invalid username");
+ sendServerReject(client, buf, InvalidUsername);
+ goto disconnect;
+ }
+
+ if (Client_count() >= getIntConf(MAX_CLIENTS)) {
+ char buf[64];
+ sprintf(buf, "Server is full (max %d users)", getIntConf(MAX_CLIENTS));
+ sendServerReject(client, buf, ServerFull);
+ goto disconnect;
+ }
+
+ /* Name & password */
+ strncpy(client->playerName, msg->payload.serverAuthenticate.userName, MAX_TEXT);
+ client->playerId = client->sessionId;
+
+ client->authenticated = true;
+
+ /* XXX - Kick ghost */
+
+ /* Setup UDP encryption */
+ CryptState_init(&client->cryptState);
+ CryptState_genKey(&client->cryptState);
+ sendmsg = Msg_create(CryptSetup);
+ sendmsg->sessionId = client->sessionId;
+ memcpy(sendmsg->payload.cryptSetup.key, client->cryptState.raw_key, AES_BLOCK_SIZE);
+ memcpy(sendmsg->payload.cryptSetup.serverNonce, client->cryptState.encrypt_iv, AES_BLOCK_SIZE);
+ memcpy(sendmsg->payload.cryptSetup.clientNonce, client->cryptState.decrypt_iv, AES_BLOCK_SIZE);
+ Client_send_message(client, sendmsg);
+
+ /* Channel stuff */
+ Chan_playerJoin(defaultChan, client); /* Join default channel */
+
+ /* Iterate channels and send channel info */
+ ch_itr = NULL;
+ Chan_iterate(&ch_itr);
+ do {
+ sendmsg = Msg_create(ChannelAdd);
+ sendmsg->sessionId = 0;
+ sendmsg->payload.channelAdd.id = ch_itr->id;
+ if (ch_itr->id == 0)
+ sendmsg->payload.channelAdd.parentId = -1;
+ else
+ sendmsg->payload.channelAdd.parentId = ch_itr->parent->id;
+ strcpy(sendmsg->payload.channelAdd.name, ch_itr->name);
+ Client_send_message(client, sendmsg);
+
+ sendmsg = Msg_create(ChannelDescUpdate);
+ sendmsg->sessionId = 0;
+ sendmsg->payload.channelDescUpdate.id = ch_itr->id;
+ strcpy(sendmsg->payload.channelDescUpdate.desc, ch_itr->desc);
+ Client_send_message(client, sendmsg);
+
+ Chan_iterate(&ch_itr);
+ } while (ch_itr != NULL);
+
+ /* Not supporting channel link for now */
+
+ /* Server join for connecting user */
+ sendmsg = Msg_create(ServerJoin);
+ sendmsg->sessionId = client->sessionId;
+ sendmsg->payload.serverJoin.id = client->playerId;
+ strcpy(sendmsg->payload.serverJoin.playerName, client->playerName);
+ Client_send_message_except(client, sendmsg);
+
+ /* Player move for connecting user */
+ if (((channel_t *)client->channel)->id != 0) {
+ sendmsg = Msg_create(PlayerMove);
+ sendmsg->sessionId = client->sessionId;
+ sendmsg->payload.playerMove.victim = client->playerId;
+ sendmsg->payload.playerMove.channel = ((channel_t *)client->channel)->id;
+ Client_send_message_except(client, sendmsg);
+ }
+ client_itr = NULL;
+ while (Client_iterate(&client_itr) != NULL) {
+ if (!IS_AUTH(client_itr))
+ continue;
+ sendmsg = Msg_create(ServerJoin);
+ sendmsg->sessionId = client_itr->sessionId;
+ sendmsg->payload.serverJoin.id = client_itr->playerId;
+ strncpy(sendmsg->payload.serverJoin.playerName, client_itr->playerName, MAX_TEXT);
+ Client_send_message(client, sendmsg);
+
+ sendmsg = Msg_create(PlayerMove);
+ sendmsg->sessionId = client_itr->sessionId;
+ sendmsg->payload.playerMove.victim = client_itr->playerId;
+ sendmsg->payload.playerMove.channel = ((channel_t *)client_itr->channel)->id;
+ Client_send_message(client, sendmsg);
+ }
+
+ sendmsg = Msg_create(ServerSync);
+ sendmsg->sessionId = client->sessionId;
+ strcpy(sendmsg->payload.serverSync.welcomeText, getStrConf(WELCOMETEXT));
+ sendmsg->payload.serverSync.maxBandwidth = getIntConf(MAX_BANDWIDTH);
+ Client_send_message(client, sendmsg);
+
+ Log_info("Player %s authenticated", client->playerName);
+
+ break;
+
+ case PingStats:
+ client->cryptState.uiRemoteGood = msg->payload.pingStats.good;
+ client->cryptState.uiRemoteLate = msg->payload.pingStats.late;
+ client->cryptState.uiRemoteLost = msg->payload.pingStats.lost;
+ client->cryptState.uiRemoteResync = msg->payload.pingStats.resync;
+
+ Log_debug("Pingstats <-: %d %d %d %d",
+ client->cryptState.uiRemoteGood, client->cryptState.uiRemoteLate,
+ client->cryptState.uiRemoteLost, client->cryptState.uiRemoteResync);
+
+ /* Ignoring the double values since they don't seem to be used */
+ sendmsg = Msg_create(PingStats);
+ sendmsg->sessionId = client->sessionId;
+ sendmsg->payload.pingStats.timestamp = msg->payload.pingStats.timestamp;
+
+ sendmsg->payload.pingStats.good = client->cryptState.uiGood;
+ sendmsg->payload.pingStats.late = client->cryptState.uiLate;
+ sendmsg->payload.pingStats.lost = client->cryptState.uiLost;
+ sendmsg->payload.pingStats.resync = client->cryptState.uiResync;
+
+ Client_send_message(client, sendmsg);
+ Log_debug("Pingstats ->: %d %d %d %d",
+ client->cryptState.uiGood, client->cryptState.uiLate,
+ client->cryptState.uiLost, client->cryptState.uiResync);
+
+ break;
+ case Ping:
+ sendmsg = Msg_create(Ping);
+ sendmsg->sessionId = client->sessionId;
+ sendmsg->payload.ping.timestamp = msg->payload.ping.timestamp;
+ Client_send_message(client, sendmsg);
+ break;
+ case CryptSync:
+ Log_debug("Voice channel crypt resync requested");
+ if (msg->payload.cryptSync.empty) {
+ sendmsg = Msg_create(CryptSync);
+ sendmsg->sessionId = msg->sessionId;
+ sendmsg->payload.cryptSync.empty = false;
+ memcpy(sendmsg->payload.cryptSync.nonce, client->cryptState.decrypt_iv, AES_BLOCK_SIZE);
+ Client_send_message(client, sendmsg);
+ } else {
+ memcpy(client->cryptState.decrypt_iv, msg->payload.cryptSync.nonce, AES_BLOCK_SIZE);
+ client->cryptState.uiResync++;
+ }
+ break;
+ case PlayerMute:
+ if (msg->payload.playerMute.victim != client->playerId) {
+ sendPermissionDenied(client, "Permission denied");
+ } else {
+ Log_debug("Player ID %d muted", msg->payload.playerMute.victim);
+ client->mute = msg->payload.playerMute.bMute;
+ }
+ break;
+ case PlayerDeaf:
+ if (msg->payload.playerDeaf.victim != client->playerId) {
+ sendPermissionDenied(client, "Permission denied");
+ } else {
+ Log_debug("Player ID %d deaf", msg->payload.playerDeaf.victim);
+ client->deaf = msg->payload.playerDeaf.bDeaf;
+ }
+ break;
+ case TextMessage:
+ if (msg->payload.textMessage.bTree)
+ sendPermissionDenied(client, "Tree message not supported");
+ else if (msg->payload.textMessage.channel != -1) { /* To channel */
+ channel_t *ch_itr = NULL;
+ do {
+ Chan_iterate(&ch_itr);
+ } while (ch_itr != NULL && ch_itr->id != msg->payload.textMessage.channel);
+ if (ch_itr == NULL)
+ Log_warn("Channel id %d not found - ignoring.", msg->payload.textMessage.channel);
+ else {
+ struct dlist *itr;
+ list_iterate(itr, &ch_itr->clients) {
+ client_t *c;
+ c = list_get_entry(itr, client_t, chan_node);
+ if (c != client && !c->deaf) {
+ Msg_inc_ref(msg);
+ Client_send_message(c, msg);
+ Log_debug("Text message to player ID %d", c->playerId);
+ }
+ }
+ }
+ } else { /* To player */
+ client_t *itr = NULL;
+ while (Client_iterate(&itr) != NULL) {
+ if (!IS_AUTH(itr))
+ continue;
+ if (itr->playerId == msg->payload.textMessage.victim) {
+ if (!itr->deaf) {
+ Msg_inc_ref(msg);
+ Client_send_message(itr, msg);
+ }
+ break;
+ }
+ }
+ if (itr == NULL)
+ Log_warn("TextMessage: Player ID %d not found", msg->payload.textMessage.victim);
+ }
+ break;
+ case PlayerSelfMuteDeaf:
+ client->deaf = msg->payload.playerSelfMuteDeaf.bDeaf;
+ client->mute = msg->payload.playerSelfMuteDeaf.bMute;
+ Log_debug("Player ID %d %s and %s", client->playerId, client->deaf ? "deaf": "not deaf",
+ client->mute ? "mute" : "not mute");
+ break;
+ case PlayerMove:
+ Msg_inc_ref(msg); /* Re-use message */
+ Client_send_message_except(NULL, msg);
+ Chan_playerJoin_id(msg->payload.playerMove.channel, client);
+ break;
+
+ /* Permission denied for all these messages. Not implemented. */
+ case PlayerRename:
+ case ChannelAdd:
+ case ChannelDescUpdate:
+ case ContextAction:
+ case ContextAddAction:
+ case ServerBanList:
+ case PlayerKick:
+ case PlayerBan:
+ case ChannelRemove:
+ case ChannelMove:
+ case ChannelLink:
+ case ChannelRename:
+ case EditACL:
+ sendPermissionDenied(client, "Not supported by uMurmur");
+ break;
+
+ case PlayerTexture: /* Ignore */
+ break;
+
+ default:
+ Log_warn("Message %d not handled", msg->messageType);
+ break;
+ }
+ Msg_free(msg);
+ return;
+disconnect:
+ Msg_free(msg);
+ Client_close(client);
+}
--- /dev/null
+/* Copyright (C) 2009, Martin Johansson <martin@fatbob.nu>
+ Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ - Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ - Neither the name of the Developers nor the names of its contributors may
+ be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef MESSAGEHANDLER_H_8907
+#define MESSAGEHANDLER_H_8907
+
+void Mh_handle_message(client_t *client, message_t *msg);
+
+#endif
--- /dev/null
+/* Copyright (C) 2009, Martin Johansson <martin@fatbob.nu>
+ Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ - Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ - Neither the name of the Developers nor the names of its contributors may
+ be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "messages.h"
+#include "pds.h"
+#include "log.h"
+
+
+void dumpmsg(uint8_t *data, int size);
+
+int Msg_messageToNetwork(message_t *msg, uint8_t *buffer, int bufsize)
+{
+ pds_t *pds = Pds_create(buffer, bufsize);
+ int len;
+
+ Pds_add_numval(pds, msg->messageType);
+ Pds_add_numval(pds, msg->sessionId);
+
+ switch (msg->messageType) {
+ case Speex:
+ Pds_add_numval(pds, msg->payload.speex.seq);
+ Pds_append_data_nosize(pds, msg->payload.speex.data, msg->payload.speex.size);
+ break;
+ case ServerReject:
+ Pds_add_string(pds, msg->payload.serverReject.reason);
+ Pds_add_numval(pds, msg->payload.serverReject.type);
+ break;
+ case ServerSync:
+ Pds_add_numval(pds, msg->payload.serverSync.maxBandwidth);
+ Pds_add_string(pds, msg->payload.serverSync.welcomeText);
+ break;
+ case ServerJoin:
+ Pds_add_string(pds, msg->payload.serverJoin.playerName);
+ Pds_add_numval(pds, msg->payload.serverJoin.id);
+ break;
+ case ChannelDescUpdate:
+ Pds_add_numval(pds, msg->payload.channelDescUpdate.id);
+ Pds_add_string(pds, msg->payload.channelDescUpdate.desc);
+ break;
+ case ChannelAdd:
+ Pds_add_numval(pds, msg->payload.channelAdd.id);
+ Pds_add_numval(pds, msg->payload.channelAdd.parentId);
+ Pds_add_string(pds, msg->payload.channelAdd.name);
+ break;
+ case PlayerMove:
+ Pds_add_numval(pds, msg->payload.playerMove.victim);
+ Pds_add_numval(pds, msg->payload.playerMove.channel);
+ break;
+ case QueryUsers:
+ break;
+ case Ping:
+ Pds_add_numval(pds, msg->payload.ping.timestamp);
+ break;
+ case PingStats:
+ Pds_add_numval(pds, msg->payload.pingStats.timestamp);
+ Pds_add_numval(pds, msg->payload.pingStats.good);
+ Pds_add_numval(pds, msg->payload.pingStats.late);
+ Pds_add_numval(pds, msg->payload.pingStats.lost);
+ Pds_add_numval(pds, msg->payload.pingStats.resync);
+ Pds_add_double(pds, msg->payload.pingStats.dUDPPingAvg);
+ Pds_add_double(pds, msg->payload.pingStats.dUDPPingVar);
+ Pds_add_numval(pds, msg->payload.pingStats.UDPPackets);
+ Pds_add_double(pds, msg->payload.pingStats.dTCPPingAvg);
+ Pds_add_double(pds, msg->payload.pingStats.dTCPPingVar);
+ Pds_add_numval(pds, msg->payload.pingStats.TCPPackets);
+ break;
+ case PlayerMute:
+ break;
+ case PlayerDeaf:
+ break;
+ case PlayerSelfMuteDeaf:
+ break;
+ case TextMessage:
+ Pds_add_numval(pds, msg->payload.textMessage.victim);
+ Pds_add_numval(pds, msg->payload.textMessage.channel);
+ Pds_add_numval(pds, msg->payload.textMessage.bTree);
+ Pds_add_string(pds, msg->payload.textMessage.message);
+ break;
+ case PermissionDenied:
+ Pds_add_string(pds, msg->payload.permissionDenied.reason);
+ break;
+ case CryptSetup:
+ Pds_append_data(pds, msg->payload.cryptSetup.key, AES_BLOCK_SIZE);
+ Pds_append_data(pds, msg->payload.cryptSetup.serverNonce, AES_BLOCK_SIZE);
+ Pds_append_data(pds, msg->payload.cryptSetup.clientNonce, AES_BLOCK_SIZE);
+ break;
+ case CryptSync:
+ if (!msg->payload.cryptSync.empty)
+ Pds_append_data(pds, msg->payload.cryptSync.nonce, AES_BLOCK_SIZE);
+ break;
+ case ServerLeave:
+ /* No info to add */
+ break;
+
+ default:
+ Log_warn("Unsupported message %d", msg->messageType);
+ break;
+ }
+ len = pds->offset;
+ Pds_free(pds);
+ return len;
+}
+
+message_t *Msg_create(messageType_t messageType)
+{
+ message_t *msg = malloc(sizeof(message_t));
+
+ if (msg == NULL)
+ Log_fatal("Out of memory");
+ memset(msg, 0, sizeof(message_t));
+ msg->refcount = 1;
+ msg->messageType = messageType;
+ init_list_entry(&msg->node);
+
+ if (msg->messageType == Speex) {
+ msg->payload.speex.data = malloc(SPEEX_DATA_SIZE);
+ if (msg->payload.speex.data == NULL)
+ Log_fatal("Out of memory");
+ }
+ return msg;
+}
+
+void Msg_inc_ref(message_t *msg)
+{
+ msg->refcount++;
+}
+
+void Msg_free(message_t *msg)
+{
+ if (msg->refcount) msg->refcount--;
+ if (msg->refcount > 0)
+ return;
+ if (msg->messageType == Speex)
+ free(msg->payload.speex.data);
+ free(msg);
+}
+
+void dumpmsg(uint8_t *data, int size)
+{
+ int i, r = 0, offset = 0;
+ char buf[512];
+
+ while (r * 8 + i < size) {
+ for (i = 0; i < 8 && r * 8 + i < size; i++) {
+ offset += sprintf(buf + offset, "%x ", data[r * 8 + i]);
+ }
+ sprintf(buf + offset, "\n");
+ printf(buf);
+ offset = 0;
+ r++;
+ i = 0;
+ }
+}
+
+message_t *Msg_networkToMessage(uint8_t *data, int size)
+{
+ message_t *msg = NULL;
+ int messageType;
+ int sessionId;
+ pds_t *pds;
+
+ pds = Pds_create(data, size);
+ messageType = Pds_get_numval(pds);
+ sessionId = Pds_get_numval(pds);
+
+ switch (messageType) {
+ case Speex:
+ msg = Msg_create(Speex);
+ msg->payload.speex.seq = Pds_get_numval(pds);
+ msg->payload.speex.size = pds->maxsize - pds->offset;
+ memcpy(msg->payload.speex.data, &pds->data[pds->offset], pds->maxsize - pds->offset);
+ break;
+ case ServerAuthenticate:
+ msg = Msg_create(ServerAuthenticate);
+ msg->payload.serverAuthenticate.version = Pds_get_numval(pds);
+ Pds_get_string(pds, msg->payload.serverAuthenticate.userName, MAX_TEXT);
+ Pds_get_string(pds, msg->payload.serverAuthenticate.password, MAX_TEXT);
+ break;
+ case ServerReject:
+ msg = Msg_create(ServerReject);
+ break;
+ case ServerSync:
+ msg = Msg_create(ServerSync);
+ break;
+ case ServerJoin:
+ msg = Msg_create(ServerJoin);
+ break;
+ case ServerLeave:
+ msg = Msg_create(ServerLeave);
+ break;
+ case QueryUsers:
+ msg = Msg_create(QueryUsers);
+ break;
+ case Ping:
+ msg = Msg_create(Ping);
+ msg->payload.ping.timestamp = Pds_get_numval(pds);
+ break;
+ case PingStats:
+ msg = Msg_create(PingStats);
+ msg->payload.pingStats.timestamp = Pds_get_numval(pds);
+ msg->payload.pingStats.good = Pds_get_numval(pds);
+ msg->payload.pingStats.late = Pds_get_numval(pds);
+ msg->payload.pingStats.lost = Pds_get_numval(pds);
+ msg->payload.pingStats.resync = Pds_get_numval(pds);
+ msg->payload.pingStats.dUDPPingAvg = Pds_get_double(pds);
+ msg->payload.pingStats.dUDPPingVar = Pds_get_double(pds);
+ msg->payload.pingStats.UDPPackets = Pds_get_numval(pds);
+ msg->payload.pingStats.dTCPPingAvg = Pds_get_double(pds);
+ msg->payload.pingStats.dTCPPingVar = Pds_get_double(pds);
+ msg->payload.pingStats.TCPPackets = Pds_get_numval(pds);
+ break;
+ case PlayerMute:
+ msg = Msg_create(PlayerMute);
+ msg->payload.playerMute.victim = Pds_get_numval(pds);
+ msg->payload.playerMute.bMute = Pds_get_numval(pds);
+ break;
+ case PlayerDeaf:
+ msg = Msg_create(PlayerDeaf);
+ msg->payload.playerDeaf.victim = Pds_get_numval(pds);
+ msg->payload.playerDeaf.bDeaf = Pds_get_numval(pds);
+ break;
+ case PlayerSelfMuteDeaf:
+ msg = Msg_create(PlayerSelfMuteDeaf);
+ msg->payload.playerSelfMuteDeaf.bMute = Pds_get_numval(pds);
+ msg->payload.playerSelfMuteDeaf.bDeaf = Pds_get_numval(pds);
+ break;
+ case TextMessage:
+ msg = Msg_create(TextMessage);
+ msg->payload.textMessage.victim = Pds_get_numval(pds);
+ msg->payload.textMessage.channel = Pds_get_numval(pds);
+ msg->payload.textMessage.bTree = Pds_get_numval(pds);
+ Pds_get_string(pds, msg->payload.textMessage.message, MAX_TEXT);
+ break;
+ case PermissionDenied:
+ Log_warn("Ignoring message PermissionDenied - not supported");
+ break;
+ case CryptSetup:
+ Log_warn("Ignoring message CryptSetup - not supported");
+ break;
+ case CryptSync:
+ msg = Msg_create(CryptSync);
+ if (Pds_get_data(pds, msg->payload.cryptSync.nonce, AES_BLOCK_SIZE) == 0)
+ msg->payload.cryptSync.empty = true;
+ else
+ msg->payload.cryptSync.empty = false;
+ break;
+ case PlayerMove:
+ msg = Msg_create(PlayerMove);
+ msg->payload.playerMove.victim = Pds_get_numval(pds);
+ msg->payload.playerMove.channel = Pds_get_numval(pds);
+ break;
+
+ /* The commands below are not supported -> no need to read the parameters */
+ case PlayerRename:
+ msg = Msg_create(PlayerRename);
+ break;
+ case ChannelAdd:
+ msg = Msg_create(ChannelAdd);
+ break;
+ case ChannelDescUpdate:
+ msg = Msg_create(ChannelDescUpdate);
+ break;
+ case ContextAction:
+ msg = Msg_create(ContextAction);
+ break;
+ case ContextAddAction:
+ msg = Msg_create(ContextAddAction);
+ break;
+ case ServerBanList:
+ msg = Msg_create(ServerBanList);
+ break;
+ case PlayerKick:
+ msg = Msg_create(PlayerKick);
+ break;
+ case PlayerBan:
+ msg = Msg_create(PlayerBan);
+ break;
+ case ChannelRemove:
+ msg = Msg_create(ChannelRemove);
+ break;
+ case ChannelMove:
+ msg = Msg_create(ChannelMove);
+ break;
+ case ChannelLink:
+ msg = Msg_create(ChannelLink);
+ break;
+ case ChannelRename:
+ msg = Msg_create(ChannelRename);
+ break;
+ case EditACL:
+ msg = Msg_create(EditACL);
+ break;
+ case PlayerTexture:
+ msg = Msg_create(PlayerTexture);
+ break;
+ default:
+ Log_warn("Message: Type %d (session %d) is unknown type", messageType, sessionId);
+ }
+ if (msg) {
+ msg->sessionId = sessionId;
+#if 0
+ if (!pds->bOk) {
+ Msg_free(msg);
+ msg = NULL;
+ Log_warn("Message: Type %d (session %d, size %d) corrupt or short packet",
+ messageType, sessionId, pds->offset);
+ } else if (pds->maxsize - pds->offset != 0) {
+ Msg_free(msg);
+ msg = NULL;
+ Log_warn("Message: Type %d (session %d) Long packet: %d/%d leftover bytes",
+ messageType, sessionId, pds->overshoot, pds->offset);
+ } else if (!pds->bOk) {
+ Msg_free(msg);
+ msg = NULL;
+ Log_warn("Message: Type %d (session %d, size %d) failed to validate", messageType, sessionId, pds->maxsize);
+ }
+#endif
+ }
+ Pds_free(pds);
+ return msg;
+}
--- /dev/null
+/* Copyright (C) 2009, Martin Johansson <martin@fatbob.nu>
+ Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ - Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ - Neither the name of the Developers nor the names of its contributors may
+ be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef MESSAGES_H_89768
+#define MESSAGES_H_89768
+
+#include <stdint.h>
+#include <openssl/aes.h>
+#include "list.h"
+#include "types.h"
+
+#define MAX_TEXT 64
+#define SPEEX_DATA_SIZE 1024
+#define MESSAGE_STREAM_VERSION 4
+
+typedef enum {
+ ServerReject,
+ ServerAuthenticate,
+ Speex,
+ ServerSync,
+ ServerJoin,
+ ServerLeave,
+ ServerBanList,
+ PlayerMute,
+ PlayerDeaf,
+ PlayerKick,
+ PlayerRename, /*10 */
+ PlayerBan,
+ PlayerMove,
+ PlayerSelfMuteDeaf,
+ ChannelAdd,
+ ChannelRemove,
+ ChannelMove,
+ ChannelLink,
+ ChannelRename,
+ PermissionDenied,
+ EditACL, /* 20 */
+ QueryUsers,
+ Ping,
+ TextMessage,
+ PlayerTexture,
+ CryptSetup,
+ CryptSync,
+ PingStats,
+ ContextAction,
+ ContextAddAction,
+ ChannelDescUpdate,
+} messageType_t;
+
+
+typedef enum {
+ AltSpeak = 0x01,
+ LoopBack = 0x02,
+ EndSpeech = 0x04,
+ FrameCountMask = 0x30
+} speexflag_t;
+
+typedef struct {
+ int speexflag;
+ int seq;
+ uint8_t *data;
+ int size;
+} speex_t;
+
+typedef struct {
+ int maxBandwidth;
+ char welcomeText[MAX_TEXT];
+} serverSync_t;
+
+typedef struct {
+ char playerName[MAX_TEXT];
+ int id;
+} serverLeave_t;
+
+typedef enum {
+ None,
+ WrongVersion,
+ InvalidUsername,
+ WrongUserPW,
+ WrongServerPW,
+ UsernameInUse,
+ ServerFull
+} rejectType_t;
+
+typedef struct {
+ char reason[MAX_TEXT];
+ rejectType_t type;
+} serverReject_t;
+
+typedef struct {
+ int version;
+ char userName[MAX_TEXT];
+ char password[MAX_TEXT];
+} serverAuthenticate_t;
+
+typedef struct {
+ int id;
+ int parentId;
+ char name[MAX_TEXT];
+} channelAdd_t;
+
+typedef struct {
+ int id;
+ char desc[MAX_TEXT];
+} channelDescUpdate_t;
+
+typedef struct {
+ char playerName[MAX_TEXT];
+ int id;
+} serverJoin_t;
+
+typedef struct {
+ int victim;
+ int channel;
+} playerMove_t;
+
+typedef struct {
+ uint8_t key[AES_BLOCK_SIZE];
+ uint8_t clientNonce[AES_BLOCK_SIZE];
+ uint8_t serverNonce[AES_BLOCK_SIZE];
+} cryptSetup_t;
+
+typedef struct {
+ bool_t empty;
+ uint8_t nonce[AES_BLOCK_SIZE];
+} cryptSync_t;
+
+typedef struct {
+ uint64_t timestamp;
+} ping_t;
+
+typedef struct {
+ uint64_t timestamp;
+ uint32_t good;
+ uint32_t late;
+ uint32_t lost;
+ uint32_t resync;
+ double dUDPPingAvg;
+ double dUDPPingVar;
+ uint32_t UDPPackets;
+ double dTCPPingAvg;
+ double dTCPPingVar;
+ uint32_t TCPPackets;
+} pingStats_t;
+
+typedef struct {
+ char reason[MAX_TEXT];
+} permissionDenied_t;
+
+typedef struct {
+ uint32_t victim;
+ bool_t bMute;
+} playerMute_t;
+
+typedef struct {
+ uint32_t victim;
+ bool_t bDeaf;
+} playerDeaf_t;
+
+typedef struct {
+ bool_t bMute;
+ bool_t bDeaf;
+} playerSelfMuteDeaf_t;
+
+typedef struct {
+ int32_t victim;
+ int32_t channel;
+ bool_t bTree;
+ char message[MAX_TEXT];
+} textMessage_t;
+
+typedef union payload {
+ speex_t speex;
+ serverSync_t serverSync;
+ serverJoin_t serverJoin;
+ serverLeave_t serverLeave;
+ serverReject_t serverReject;
+ serverAuthenticate_t serverAuthenticate;
+ cryptSetup_t cryptSetup;
+ cryptSync_t cryptSync;
+ pingStats_t pingStats;
+ ping_t ping;
+ channelAdd_t channelAdd;
+ channelDescUpdate_t channelDescUpdate;
+ playerMove_t playerMove;
+ permissionDenied_t permissinDenied;
+ playerMute_t playerMute;
+ playerDeaf_t playerDeaf;
+ playerSelfMuteDeaf_t playerSelfMuteDeaf;
+ permissionDenied_t permissionDenied;
+ textMessage_t textMessage;
+} payload_t;
+
+typedef struct message {
+ messageType_t messageType;
+ uint32_t sessionId;
+ int refcount;
+ struct dlist node;
+ payload_t payload;
+} message_t;
+
+
+
+int Msg_messageToNetwork(message_t *msg, uint8_t *buffer, int bufsize);
+message_t *Msg_networkToMessage(uint8_t *data, int size);
+void Msg_free(message_t *msg);
+void Msg_inc_ref(message_t *msg);
+
+message_t *Msg_create(messageType_t messageType);
+
+#endif
--- /dev/null
+/* Copyright (C) 2009, Martin Johansson <martin@fatbob.nu>
+ Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ - Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ - Neither the name of the Developers nor the names of its contributors may
+ be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#include <string.h>
+#include <stdlib.h>
+#include "pds.h"
+#include "log.h"
+
+/*
+ * Data serialization functions below
+ */
+
+typedef union double64u {
+ uint64_t u64;
+ double dval;
+} double64u_t;
+
+static inline void append_val(pds_t *pds, uint64_t val)
+{
+ if (pds->offset < pds->maxsize)
+ pds->data[pds->offset++] = ((uint8_t)(val));
+ else {
+ pds->bOk = false;
+ pds->overshoot++;
+ }
+}
+
+void Pds_append_data(pds_t *pds, const uint8_t *data, uint32_t len)
+{
+ int left;
+ Pds_add_numval(pds, len);
+ left = pds->maxsize - pds->offset;
+ if (left >= len) {
+ memcpy(&pds->data[pds->offset], data, len);
+ pds->offset += len;
+ } else {
+ memset(&pds->data[pds->offset], 0, left);
+ pds->offset += left;
+ pds->overshoot += len - left;
+ pds->bOk = false;
+ }
+}
+
+void Pds_append_data_nosize(pds_t *pds, const uint8_t *data, uint32_t len)
+{
+ int left;
+ left = pds->maxsize - pds->offset;
+ if (left >= len) {
+ memcpy(&pds->data[pds->offset], data, len);
+ pds->offset += len;
+ } else {
+ memset(&pds->data[pds->offset], 0, left);
+ pds->offset += left;
+ pds->overshoot += len - left;
+ pds->bOk = false;
+ }
+}
+
+static inline uint64_t next(pds_t *pds)
+{
+ if (pds->offset < pds->maxsize)
+ return pds->data[pds->offset++];
+ else {
+ pds->bOk = false;
+ return 0;
+ }
+}
+
+pds_t *Pds_create(uint8_t *buf, int size)
+{
+ pds_t *pds = malloc(sizeof(pds_t));
+ if (pds == NULL)
+ Log_fatal("Out of memory");
+ pds->data = buf;
+ pds->offset = pds->overshoot = 0;
+ pds->maxsize = size;
+ pds->bOk = true;
+ return pds;
+}
+
+void Pds_free(pds_t *pds)
+{
+ free(pds);
+}
+
+void Pds_add_double(pds_t *pds, double value)
+{
+ double64u_t u;
+
+ u.dval = value;
+
+ Pds_add_numval(pds, u.u64);
+}
+
+double Pds_get_double(pds_t *pds)
+{
+ double64u_t u;
+ u.u64 = Pds_get_numval(pds);
+ return u.dval;
+}
+void Pds_add_numval(pds_t *pds, const uint64_t value)
+{
+ uint64_t i = value;
+
+ if ((i & 0x8000000000000000LL) && (~i < 0x100000000LL)) {
+ // Signed number.
+ i = ~i;
+ if (i <= 0x3) {
+ // Shortcase for -1 to -4
+ append_val(pds, 0xFC | i);
+ return;
+ } else {
+ append_val(pds, 0xF8);
+ }
+ }
+ if (i < 0x80) {
+ // Need top bit clear
+ append_val(pds, i);
+ } else if (i < 0x4000) {
+ // Need top two bits clear
+ append_val(pds, (i >> 8) | 0x80);
+ append_val(pds, i & 0xFF);
+ } else if (i < 0x200000) {
+ // Need top three bits clear
+ append_val(pds, (i >> 16) | 0xC0);
+ append_val(pds, (i >> 8) & 0xFF);
+ append_val(pds, i & 0xFF);
+ } else if (i < 0x10000000) {
+ // Need top four bits clear
+ append_val(pds, (i >> 24) | 0xE0);
+ append_val(pds, (i >> 16) & 0xFF);
+ append_val(pds, (i >> 8) & 0xFF);
+ append_val(pds, i & 0xFF);
+ } else if (i < 0x100000000LL) {
+ // It's a full 32-bit integer.
+ append_val(pds, 0xF0);
+ append_val(pds, (i >> 24) & 0xFF);
+ append_val(pds, (i >> 16) & 0xFF);
+ append_val(pds, (i >> 8) & 0xFF);
+ append_val(pds, i & 0xFF);
+ } else {
+ // It's a 64-bit value.
+ append_val(pds, 0xF4);
+ append_val(pds, (i >> 56) & 0xFF);
+ append_val(pds, (i >> 48) & 0xFF);
+ append_val(pds, (i >> 40) & 0xFF);
+ append_val(pds, (i >> 32) & 0xFF);
+ append_val(pds, (i >> 24) & 0xFF);
+ append_val(pds, (i >> 16) & 0xFF);
+ append_val(pds, (i >> 8) & 0xFF);
+ append_val(pds, i & 0xFF);
+ }
+}
+
+uint64_t Pds_get_numval(pds_t *pds)
+{
+ uint64_t i = 0;
+ uint64_t v = next(pds);
+
+ if ((v & 0x80) == 0x00) {
+ i=(v & 0x7F);
+ } else if ((v & 0xC0) == 0x80) {
+ i=(v & 0x3F) << 8 | next(pds);
+ } else if ((v & 0xF0) == 0xF0) {
+ switch (v & 0xFC) {
+ case 0xF0:
+ i=next(pds) << 24 | next(pds) << 16 | next(pds) << 8 | next(pds);
+ break;
+ case 0xF4:
+ i=next(pds) << 56 | next(pds) << 48 | next(pds) << 40 | next(pds) << 32 | next(pds) << 24 | next(pds) << 16 | next(pds) << 8 | next(pds);
+ break;
+ case 0xF8:
+ i = Pds_get_numval(pds);
+ i = ~i;
+ break;
+ case 0xFC:
+ i=v & 0x03;
+ i = ~i;
+ break;
+ default:
+ //ok = false;
+ i = 0;
+ break;
+ }
+ } else if ((v & 0xF0) == 0xE0) {
+ i=(v & 0x0F) << 24 | next(pds) << 16 | next(pds) << 8 | next(pds);
+ } else if ((v & 0xE0) == 0xC0) {
+ i=(v & 0x1F) << 16 | next(pds) << 8 | next(pds);
+ }
+ return i;
+}
+
+void Pds_add_string(pds_t *pds, const char *str)
+{
+ Pds_append_data(pds, (uint8_t *)str, strlen(str));
+}
+
+void Pds_get_string(pds_t *pds, char *str, int maxlen)
+{
+ int len = Pds_get_numval(pds);
+ if (len < maxlen) {
+ memcpy(str, &pds->data[pds->offset], len);
+ str[len] = '\0';
+ pds->offset += len;
+ } else {
+ Log_warn("Too long string from network");
+ strcpy(str, "N/A");
+ }
+}
+
+int Pds_get_data(pds_t *pds, uint8_t *data, int maxlen)
+{
+ int len = Pds_get_numval(pds);
+ if (len < maxlen) {
+ memcpy(data, &pds->data[pds->offset], len);
+ pds->offset += len;
+ return len;
+ } else {
+ Log_warn("Pds_get_data: Too much data from network");
+ return -1;
+ }
+}
--- /dev/null
+/* Copyright (C) 2009, Martin Johansson <martin@fatbob.nu>
+ Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ - Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ - Neither the name of the Developers nor the names of its contributors may
+ be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef PDS_H_457865876
+#define PDS_H_457865876
+
+#include <stdint.h>
+#include "types.h"
+
+typedef struct {
+ uint8_t *data;
+ uint32_t maxsize;
+ uint32_t offset;
+ uint32_t overshoot;
+ bool_t bOk;
+} pds_t;
+
+void Pds_append_data(pds_t *pds, const uint8_t *data, uint32_t len);
+void Pds_append_data_nosize(pds_t *pds, const uint8_t *data, uint32_t len);
+uint64_t Pds_get_numval(pds_t *pds);
+void Pds_add_numval(pds_t *pds, const uint64_t value);
+pds_t *Pds_create(uint8_t *buf, int size);
+void Pds_free(pds_t *pds);
+void Pds_add_string(pds_t *pds, const char *str);
+void Pds_get_string(pds_t *pds, char *str, int maxlen);
+void Pds_add_double(pds_t *pds, double value);
+double Pds_get_double(pds_t *pds);
+int Pds_get_data(pds_t *pds, uint8_t *data, int maxlen);
+
+
+#endif
--- /dev/null
+/* Copyright (C) 2009, Martin Johansson <martin@fatbob.nu>
+ Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ - Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ - Neither the name of the Developers nor the names of its contributors may
+ be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#include <stdio.h>
+#include <sys/time.h>
+#include <sys/poll.h>
+#include <netinet/tcp.h>
+#include <sys/socket.h>
+#include <errno.h>
+#include <string.h>
+#include <limits.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include "client.h"
+#include "conf.h"
+#include "log.h"
+#include "timer.h"
+
+#define LISTEN_SOCK 0
+#define TCP_SOCK 0
+#define UDP_SOCK 1
+
+int udpsock; /* XXX restructure! */
+bool_t shutdown_server;
+
+void Server_run()
+{
+ int timeout = 1000, rc;
+ struct pollfd *pollfds;
+ int tcpsock, sockopt = 1;
+ struct sockaddr_in sin;
+ int val, clientcount;
+ etimer_t janitorTimer;
+
+ /* max clients + listen sock + udp sock + client connecting that will be disconnected */
+ pollfds = malloc((getIntConf(MAX_CLIENTS) + 3) * sizeof(struct pollfd));
+ if (pollfds == NULL)
+ Log_fatal("out of memory");
+
+ /* Prepare TCP socket */
+ memset(&sin, 0, sizeof(sin));
+ tcpsock = socket(PF_INET, SOCK_STREAM, 0);
+ if (tcpsock < 0)
+ Log_fatal("socket");
+ if (setsockopt(tcpsock, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof(int)) != 0)
+ Log_fatal("setsockopt: %s", strerror(errno));
+ sin.sin_family = AF_INET;
+ sin.sin_port = htons(getIntConf(BINDPORT));
+ sin.sin_addr.s_addr = inet_addr(getStrConf(BINDADDR)) == -1 ? inet_addr("0.0.0.0") : inet_addr(getStrConf(BINDADDR));
+ rc = bind(tcpsock, (struct sockaddr *) &sin, sizeof (struct sockaddr_in));
+ if (rc < 0) Log_fatal("bind: %s", strerror(errno));
+ rc = listen(tcpsock, 3);
+ if (rc < 0) Log_fatal("listen");
+ fcntl(tcpsock, F_SETFL, O_NONBLOCK);
+
+ pollfds[LISTEN_SOCK].fd = tcpsock;
+ pollfds[LISTEN_SOCK].events = POLLIN;
+
+ /* Prepare UDP socket */
+ memset(&sin, 0, sizeof(sin));
+ udpsock = socket(PF_INET, SOCK_DGRAM, 0);
+ sin.sin_family = AF_INET;
+ sin.sin_port = htons(getIntConf(BINDPORT));
+ sin.sin_addr.s_addr = inet_addr(getStrConf(BINDADDR)) == -1 ? inet_addr("0.0.0.0") : inet_addr(getStrConf(BINDADDR));
+ rc = bind(udpsock, (struct sockaddr *) &sin, sizeof (struct sockaddr_in));
+ if (rc < 0)
+ Log_fatal("bind %d %s: %s", getIntConf(BINDPORT), getStrConf(BINDADDR), strerror(errno));
+ val = 0xe0;
+ rc = setsockopt(udpsock, IPPROTO_IP, IP_TOS, &val, sizeof(val));
+ if (rc < 0)
+ Log_fatal("Server: Failed to set TOS for UDP Socket");
+ val = 0x80;
+ rc = setsockopt(udpsock, IPPROTO_IP, IP_TOS, &val, sizeof(val));
+ if (rc < 0)
+ Log_fatal("Server: Failed to set TOS for UDP Socket");
+
+ fcntl(udpsock, F_SETFL, O_NONBLOCK);
+ pollfds[UDP_SOCK].fd = udpsock;
+ pollfds[UDP_SOCK].events = POLLIN | POLLHUP | POLLERR;
+
+ Timer_init(&janitorTimer);
+
+ /* Main server loop */
+ while (!shutdown_server) {
+ struct sockaddr_in remote;
+ int i;
+
+ pollfds[UDP_SOCK].revents = 0;
+ pollfds[TCP_SOCK].revents = 0;
+ clientcount = Client_getfds(&pollfds[2]);
+
+ timeout = (int)(1000000LL - (int64_t)Timer_elapsed(&janitorTimer)) / 1000LL;
+ if (timeout <= 0) {
+ Client_janitor();
+ Timer_restart(&janitorTimer);
+ timeout = (int)(1000000LL - (int64_t)Timer_elapsed(&janitorTimer)) / 1000LL;
+ }
+ rc = poll(pollfds, clientcount + 2, timeout);
+ if (rc == 0) { /* Timeout */
+ /* Do maintenance */
+ Timer_restart(&janitorTimer);
+ Client_janitor();
+ continue;
+ }
+ if (rc < 0) {
+ if (errno == EINTR) /* signal */
+ continue;
+ else
+ Log_fatal("poll: error %d", errno);
+ }
+ if (pollfds[LISTEN_SOCK].revents) { /* New tcp connection */
+ int tcpfd, flag = 1;
+ uint32_t addrlen;
+ addrlen = sizeof(struct sockaddr_in);
+ tcpfd = accept(pollfds[LISTEN_SOCK].fd, (struct sockaddr*)&remote, &addrlen);
+ fcntl(tcpfd, F_SETFL, O_NONBLOCK);
+ setsockopt(tcpfd, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int));
+ Log_info("Connection from %s port %d\n", inet_ntoa(remote.sin_addr),
+ ntohs(remote.sin_port));
+ Client_add(tcpfd, &remote);
+ }
+
+ if (pollfds[UDP_SOCK].revents) {
+ Client_read_udp();
+ }
+ for (i = 0; i < clientcount; i++) {
+ if (pollfds[i + 2].revents & POLLIN) {
+ Client_read_fd(pollfds[i + 2].fd);
+ }
+ if (pollfds[i + 2].revents & POLLOUT) {
+ Client_write_fd(pollfds[i + 2].fd);
+ }
+ }
+ }
+
+ /* Disconnect clients */
+ Client_disconnect_all();
+ free(pollfds);
+}
+
+void Server_shutdown()
+{
+ shutdown_server = true;
+}
--- /dev/null
+/* Copyright (C) 2009, Martin Johansson <martin@fatbob.nu>
+ Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ - Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ - Neither the name of the Developers nor the names of its contributors may
+ be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef SERVER_H_347563
+#define SERVER_H_347563
+
+void Server_run();
+void Server_shutdown();
+
+#endif
--- /dev/null
+/* Copyright (C) 2009, Martin Johansson <martin@fatbob.nu>
+ Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ - Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ - Neither the name of the Developers nor the names of its contributors may
+ be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#include <openssl/x509v3.h>
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+#include <openssl/safestack.h>
+#include <string.h>
+
+#include "conf.h"
+#include "log.h"
+#include "ssl.h"
+
+static X509 *x509;
+static RSA *rsa;
+static SSL_CTX *context;
+static EVP_PKEY *pkey;
+
+static int SSL_add_ext(X509 * crt, int nid, char *value) {
+ X509_EXTENSION *ex;
+ X509V3_CTX ctx;
+ X509V3_set_ctx_nodb(&ctx);
+ X509V3_set_ctx(&ctx, crt, crt, NULL, NULL, 0);
+ ex = X509V3_EXT_conf_nid(NULL, &ctx, nid, value);
+ if (!ex)
+ return 0;
+
+ X509_add_ext(crt, ex, -1);
+ X509_EXTENSION_free(ex);
+ return 1;
+}
+
+static X509 *SSL_readcert(char *certfile)
+{
+ FILE *fp;
+ X509 *x509;
+
+ /* open the private key file */
+ fp = fopen(certfile, "r");
+ if (fp == NULL) {
+ Log_warn("Unable to open the X509 file %s for reading.", certfile);
+ return NULL;
+ }
+
+ /* allocate memory for the cert structure */
+ x509 = X509_new();
+
+ if (PEM_read_X509(fp, &x509, NULL, NULL) == 0) {
+ /* error reading the x509 information - check the error stack */
+ Log_warn("Error trying to read X509 info.");
+ fclose(fp);
+ X509_free(x509);
+ return NULL;
+ }
+ fclose(fp);
+ return x509;
+}
+
+static RSA *SSL_readprivatekey(char *keyfile)
+{
+ FILE *fp;
+ RSA *rsa;
+
+/* open the private key file for reading */
+ fp = fopen(keyfile, "r");
+ if (fp == NULL) {
+ Log_warn("Unable to open the private key file %s for reading.", keyfile);
+ return NULL;
+ }
+
+/* allocate memory for the RSA structure */
+ rsa = RSA_new();
+
+ /* assign a callback function for the password */
+
+ /* read a private key from file */
+ if (PEM_read_RSAPrivateKey(fp, &rsa, NULL, NULL) <= 0) {
+ /* error reading the key - check the error stack */
+ Log_warn("Error trying to read private key.");
+ RSA_free(rsa);
+ fclose(fp);
+ return NULL;
+ }
+ fclose(fp);
+ return rsa;
+}
+
+void SSL_writecert(char *certfile, X509 *x509)
+{
+ FILE *fp;
+ BIO *err_output;
+
+ /* prepare a BIO for outputting error messages */
+
+ err_output = BIO_new_fp(stderr,BIO_NOCLOSE);
+
+ /* open the private key file */
+ fp = fopen(certfile, "w");
+ if (fp == NULL) {
+ BIO_printf(err_output, "Unable to open the X509 file for writing.\n");
+ BIO_free(err_output);
+ return;
+ }
+
+ if (PEM_write_X509(fp, x509) == 0) {
+ BIO_printf(err_output, "Error trying to write X509 info.\n");
+ ERR_print_errors(err_output);
+ }
+ fclose(fp);
+}
+
+void SSL_writekey(char *keyfile, RSA *rsa)
+{
+ FILE *fp;
+ BIO *err_output;
+ /* prepare a BIO for outputing error messages */
+ err_output = BIO_new_fp(stderr, BIO_NOCLOSE);
+
+ /* open the private key file for reading */
+ fp = fopen(keyfile, "w");
+ if (fp == NULL) {
+ BIO_printf(err_output, "Unable to open the private key file %s for writing.\n", keyfile);
+ BIO_free(err_output);
+ return;
+ }
+
+ if (PEM_write_RSAPrivateKey(fp, rsa, NULL, NULL, 0, NULL, NULL) == 0) {
+ /* error reading the key - check the error stack */
+ BIO_printf(err_output, "Error trying to write private key\n");
+ ERR_print_errors(err_output);
+ }
+ fclose(fp);
+}
+
+void SSL_initializeCert() {
+ char *crt, *key, *pass;
+
+ crt = (char *)getStrConf(CERTIFICATE);
+ key = (char *)getStrConf(KEY);
+ pass = (char *)getStrConf(PASSPHRASE);
+
+ x509 = SSL_readcert(crt);
+ rsa = SSL_readprivatekey(key);
+ if (rsa != NULL) {
+ pkey = EVP_PKEY_new();
+ EVP_PKEY_assign_RSA(pkey, rsa);
+ }
+
+#if 0
+ /* Later ... */
+ if (key && !x509) {
+ qscCert = QSslCertificate(key);
+ if (! qscCert.isNull()) {
+ logthis("Using certificate from key.");
+ }
+ }
+
+ if (! qscCert.isNull()) {
+ QSsl::KeyAlgorithm alg = qscCert.publicKey().algorithm();
+ /* Fetch algorith from cert */
+ if (! key.isEmpty()) {
+ /* get key */
+ qskKey = QSslKey(key, alg, QSsl::Pem, QSsl::PrivateKey, pass);
+ if (qskKey.isNull()) {
+ logthis("Failed to parse key.");
+ }
+ }
+
+ if (! crt.isEmpty() && qskKey.isNull()) {
+ /* get key from certificate */
+ qskKey = QSslKey(crt, alg, QSsl::Pem, QSsl::PrivateKey, pass);
+ if (! qskKey.isNull()) {
+ logthis("Using key from certificate.");
+ }
+ }
+
+ }
+#endif
+
+ if (!rsa || !x509) {
+ logthis("Generating new server certificate.");
+
+ BIO *bio_err;
+
+ CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
+
+ bio_err=BIO_new_fp(stderr, BIO_NOCLOSE);
+
+ x509 = X509_new();
+ pkey = EVP_PKEY_new();
+ rsa = RSA_generate_key(1024,RSA_F4,NULL,NULL);
+ EVP_PKEY_assign_RSA(pkey, rsa);
+
+ X509_set_version(x509, 2);
+ ASN1_INTEGER_set(X509_get_serialNumber(x509),1);
+ X509_gmtime_adj(X509_get_notBefore(x509),0);
+ X509_gmtime_adj(X509_get_notAfter(x509),60*60*24*365);
+ X509_set_pubkey(x509, pkey);
+
+ X509_NAME *name=X509_get_subject_name(x509);
+
+ X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (const uint8_t *)"Murmur Autogenerated Certificate v2", -1, -1, 0);
+ X509_set_issuer_name(x509, name);
+ SSL_add_ext(x509, NID_basic_constraints, "critical,CA:FALSE");
+ SSL_add_ext(x509, NID_ext_key_usage, "serverAuth,clientAuth");
+ SSL_add_ext(x509, NID_subject_key_identifier, "hash");
+ SSL_add_ext(x509, NID_netscape_comment, "Generated from umurmur");
+
+ X509_sign(x509, pkey, EVP_md5());
+
+ SSL_writecert(crt, x509);
+ SSL_writekey(key, rsa);
+ }
+
+}
+
+void SSL_getdigest(char *s, int l)
+{
+ unsigned char md[EVP_MAX_MD_SIZE];
+ unsigned int n;
+ int j;
+
+ if (!X509_digest (x509, EVP_md5(), md, &n))
+ {
+ snprintf (s, l, "[unable to calculate]");
+ }
+ else
+ {
+ for (j = 0; j < (int) n; j++)
+ {
+ char ch[8];
+ snprintf(ch, 8, "%02X%s", md[j], (j % 2 ? " " : ""));
+ strcat(s, ch);
+ }
+ }
+}
+
+void SSL_init(void)
+{
+ SSL_METHOD *method;
+ SSL *ssl;
+ int i, offset = 0;
+ STACK_OF(SSL_CIPHER) *cipherlist = NULL, *cipherlist_new = NULL;
+ SSL_CIPHER *cipher;
+ char cipherstring[1024];
+
+ SSL_library_init();
+ OpenSSL_add_all_algorithms(); /* load & register all cryptos, etc. */
+ SSL_load_error_strings(); /* load all error messages */
+ ERR_load_crypto_strings(); /* load all error messages */
+ method = SSLv23_server_method(); /* create new server-method instance */
+ context = SSL_CTX_new(method); /* create new context from method */
+ if (context == NULL)
+ {
+ ERR_print_errors_fp(stderr);
+ abort();
+ }
+ SSL_initializeCert();
+ if (SSL_CTX_use_certificate(context, x509) <= 0)
+ Log_fatal("Failed to initialize cert");
+ if (SSL_CTX_use_PrivateKey(context, pkey) <= 0) {
+ ERR_print_errors_fp(stderr);
+ Log_fatal("Failed to initialize private key");
+ }
+
+ /* Set cipher list */
+ ssl = SSL_new(context);
+ cipherlist = (STACK_OF(SSL_CIPHER) *) SSL_get_ciphers(ssl);
+ cipherlist_new = (STACK_OF(SSL_CIPHER) *) sk_SSL_CIPHER_new_null();
+
+ for ( i = 0; (cipher = sk_SSL_CIPHER_value(cipherlist, i)) != NULL; i++) {
+ if (SSL_CIPHER_get_bits(cipher, NULL) >= 128) {
+ sk_SSL_CIPHER_push(cipherlist_new, cipher);
+ }
+ }
+ Log_info("List of ciphers:");
+ if (cipherlist_new) {
+ for ( i = 0; (cipher = sk_SSL_CIPHER_value(cipherlist_new, i)) != NULL; i++) {
+ Log_info("%s", SSL_CIPHER_get_name(cipher));
+ offset += snprintf(cipherstring + offset, 1024 - offset, "%s:", SSL_CIPHER_get_name(cipher));
+ }
+ cipherstring[offset - 1] = '\0';
+ }
+
+ if (cipherlist_new)
+ sk_SSL_CIPHER_free(cipherlist_new);
+
+ if (strlen(cipherstring) == 0)
+ Log_fatal("No suitable ciphers found!");
+
+ if (SSL_CTX_set_cipher_list(context, cipherstring) == 0)
+ Log_fatal("Failed to set cipher list!");
+
+
+ SSL_free(ssl);
+}
+
+void SSL_deinit(void)
+{
+ SSL_CTX_free(context);
+ EVP_cleanup();
+}
+
+int SSL_nonblockaccept(SSL *ssl, bool_t *SSLready)
+{
+ int rc;
+ rc = SSL_accept(ssl);
+ if (rc < 0) {
+ if (SSL_get_error(ssl, rc) == SSL_ERROR_WANT_READ ||
+ SSL_get_error(ssl, rc) == SSL_ERROR_WANT_WRITE) {
+ Log_debug("SSL not ready");
+ return 0;
+ } else {
+ Log_warn("SSL error: %s", ERR_error_string(SSL_get_error(ssl, rc), NULL));
+ return -1;
+ }
+ }
+ *SSLready = true;
+ return 0;
+}
+
+SSL *SSL_newconnection(int fd, bool_t *SSLready)
+{
+ SSL *ssl;
+
+ *SSLready = false;
+ ssl = SSL_new(context);
+ SSL_set_fd(ssl, fd);
+ if (SSL_nonblockaccept(ssl, SSLready) < 0) {
+ SSL_free(ssl);
+ return NULL;
+ }
+ return ssl;
+}
+
+void SSL_closeconnection(SSL *ssl)
+{
+ SSL_free(ssl);
+}
+
+
--- /dev/null
+/* Copyright (C) 2009, Martin Johansson <martin@fatbob.nu>
+ Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ - Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ - Neither the name of the Developers nor the names of its contributors may
+ be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#include <openssl/x509v3.h>
+#include <openssl/ssl.h>
+#include "types.h"
+
+void SSL_init(void);
+void SSL_deinit(void);
+SSL *SSL_newconnection(int fd, bool_t *SSLready);
+void SSL_closeconnection(SSL *ssl);
+int SSL_nonblockaccept(SSL *ssl, bool_t *SSLready);
--- /dev/null
+/* Copyright (C) 2009, Martin Johansson <martin@fatbob.nu>
+ Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ - Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ - Neither the name of the Developers nor the names of its contributors may
+ be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#include <sys/time.h>
+#include <stdint.h>
+#include <stdio.h>
+
+#include "timer.h"
+
+static uint64_t Timer_now()
+{
+ struct timeval tv;
+ uint64_t e;
+
+ gettimeofday(&tv, NULL);
+ e = tv.tv_sec * 1000000LL;
+ e += tv.tv_usec;
+ return e;
+}
+
+
+void Timer_init(etimer_t *t)
+{
+ *t = Timer_now();
+}
+
+bool_t Timer_isElapsed(etimer_t *t, uint64_t us)
+{
+ if (Timer_elapsed(t) > us) {
+ *t += us;
+ return true;
+ }
+ return false;
+
+}
+
+uint64_t Timer_elapsed(etimer_t *t)
+{
+ return Timer_now() - *t;
+}
+
+uint64_t Timer_restart(etimer_t *t)
+{
+ uint64_t n = Timer_now();
+ uint64_t e = n - *t;
+ *t = n;
+ return e;
+}
--- /dev/null
+/* Copyright (C) 2009, Martin Johansson <martin@fatbob.nu>
+ Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ - Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ - Neither the name of the Developers nor the names of its contributors may
+ be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef TIMER_H_2766562
+#define TIMER_H_2766562
+
+#include <stdint.h>
+#include "types.h"
+
+typedef uint64_t etimer_t;
+
+void Timer_init(etimer_t *t);
+bool_t Timer_isElapsed(etimer_t *t, uint64_t us);
+uint64_t Timer_elapsed(etimer_t *t);
+uint64_t Timer_restart(etimer_t *t);
+
+#endif
+
--- /dev/null
+#ifndef TYPES_H_90878954
+#define TYPES_H_90878954
+
+typedef enum {
+ false,
+ true
+} bool_t;
+
+#endif
+