summaryrefslogtreecommitdiffstats
path: root/kbattleship/kbattleship/kbattleshipserver.cpp
blob: 34be153d31abded638c2a0872c58d80529ad6402 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
/***************************************************************************
                            kbattleshipserver.cpp
                             -------------------
    Developers: (c) 2000-2001 Nikolas Zimmermann <wildfox@kde.org>
                (c) 2000-2001 Daniel Molkentin <molkentin@kde.org>

 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#include <config.h>

#include <unistd.h>
#ifdef HAVE_STROPTS_H
#include <stropts.h>
#endif
#ifdef HAVE_SYS_FILIO_H
#include <sys/filio.h>
#endif
#include <sys/ioctl.h>
#include <tqtimer.h>
#include <kmessagebox.h>
#include <klocale.h>
#include "kbattleshipserver.moc"

KBattleshipServer::KBattleshipServer(int port, const TQString& name) 
	: KExtendedSocket(TQString(), port, inetSocket | passiveSocket), m_name(name)
{
	m_port = port;
	m_serverSocket = 0;
}

void KBattleshipServer::init()
{
	if(listen())
	{
		KMessageBox::error(0L, i18n("Failed to bind to local port \"%1\"\n\nPlease check if another KBattleship server instance\nis running or another application uses this port.").tqarg(m_port));
		emit sigServerFailure();
		return;
	}
	m_service.setServiceName(m_name);
	m_service.setType(BATTLESHIP_SERVICE);
	m_service.setPort(m_port);
	m_service.publishAsync();
	m_connectNotifier = new TQSocketNotifier(fd(), TQSocketNotifier::Read, TQT_TQOBJECT(this));
	TQT_BASE_OBJECT_NAME::connect(m_connectNotifier, TQT_SIGNAL(activated(int)), TQT_SLOT(slotNewConnection()));
}

void KBattleshipServer::slotNewConnection()
{
	KExtendedSocket *sock;
	accept(sock);
	if(sock && m_serverSocket == 0)
	{
		m_service.stop();
		m_serverSocket = sock;
		m_readNotifier = new TQSocketNotifier(sock->fd(), TQSocketNotifier::Read, TQT_TQOBJECT(this));
		TQObject::connect(m_readNotifier, TQT_SIGNAL(activated(int)), this, TQT_SLOT(slotReadClient()));
		emit sigNewConnect();
	}
	else
		delete sock;
}

void KBattleshipServer::slotReadClient()
{
	int len;
	ioctl(m_serverSocket->fd(), FIONREAD, &len);
	if(!len)
	{
		slotDiscardClient(i18n("The connection broke down!"), false, true);
		return;
	}

	char *buf = new char[len + 1];
	m_serverSocket->readBlock(buf, len);
	buf[len] = 0;
	m_readBuffer += TQString::fromUtf8(buf);
	delete []buf;
	int pos;
	while ((pos = m_readBuffer.tqfind("</kmessage>")) >= 0) 
	{
		pos += 11; // Length of "</kmessage>"
		KMessage *msg = new KMessage();
		msg->setDataStream(m_readBuffer.left(pos));
		m_readBuffer.remove(0, pos);
		emit sigNewMessage(msg);
	}
}

void KBattleshipServer::sendMessage(KMessage *msg)
{
	TQCString post = msg->sendStream().utf8();
	m_serverSocket->writeBlock(post.data(), post.length());
	emit sigMessageSent(msg);
}

void KBattleshipServer::slotDiscardClient(const TQString &reason, bool kmversion, bool bemit)
{
	KMessage *msg = new KMessage(KMessage::DISCARD);
	msg->addField("reason", reason);
	if(kmversion)
		msg->addField("kmversion", "true");
	else
		msg->addField("kmversion", "false");
	TQCString post = msg->sendStream().utf8();
	m_serverSocket->writeBlock(post.data(), post.length());
	delete msg;

	delete m_readNotifier;
	m_readNotifier = 0;
	delete m_serverSocket;
	m_serverSocket = 0;

	if(bemit)
		emit sigEndConnect();
}