You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdegames/lskat/lskat/KRemoteConnect.cpp

335 lines
8.4 KiB

/***************************************************************************
KRemoteConnect.cpp - description
-------------------
begin : Tue May 2 2000
copyright : (C) 2000 by Martin Heni
email : martin@heni-online.de
***************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
/***************************************************************************
FILENAME| - description
-------------------
begin : Tue Apr 4 2000
copyright : (C) |1995-2000 by Martin Heni
email : martin@heni-online.de
***************************************************************************/
/***************************************************************************
* *
* 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 <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include "KRemoteConnect.h"
#include "KRemoteConnect.moc"
const char* LSKAT_SERVICE = "_lskat._tcp";
KRemoteConnect::KRemoteConnect()
: KChildConnect()
{
port=7687;
IP="localhost";
socketStatus=KR_INVALID;
kSocket=0;
service=0;
kServerSocket=0;
bufferMsg=0;
buffer=new char[4097];
inputbuffer="";
input_pending=false;
}
KRemoteConnect::~KRemoteConnect()
{
Exit();
delete buffer;
delete service;
printf("DESTGRUCTING KRemoteConenct\n");
}
KR_STATUS KRemoteConnect::QueryStatus()
{
return socketStatus;
}
bool KRemoteConnect::Init(int id,KEMessage *msg)
{
short prt;
char *p;
int size;
bool tryserver;
SetID(id);
if (msg)
{
if (msg->GetData(TQCString("Port"),prt))
{
port=(unsigned int)prt;
msg->Remove(TQCString("Port"));
}
if (msg->GetData(TQCString("IP"),p,size))
{
IP=TQCString(p);
msg->Remove(TQCString("IP"));
}
if (msg->GetData(TQCString("Name"),p,size))
{
Name=TQString::fromUtf8(p);
msg->Remove(TQCString("Name"));
}
}
/*
printf("Connecting to %s %u (remain=%d)\n",
(const char *)IP,port,msg->QueryNumberOfKeys());
*/
// First try to connect to given host:socket
// if no IP given only offer server
tryserver=false;
if (!IP.isEmpty())
{
kSocket=new TDESocket(IP.latin1(),port);
if (!kSocket) return false;
if (kSocket->socket()!=-1) // success
{
kSocket->enableRead(TRUE);
//kSocket->enableWrite(TRUE);
connect(kSocket,TQ_SIGNAL(closeEvent(TDESocket *)),
this,TQ_SLOT(socketClosed(TDESocket *)));
connect(kSocket,TQ_SIGNAL(readEvent(TDESocket *)),
this,TQ_SLOT(socketRead(TDESocket *)));
/*
connect(kSocket,TQ_SIGNAL(writeEvent(TDESocket *)),
this,TQ_SLOT(socketWrite(TDESocket *)));
*/
/*
printf("Socket(%d) %p connection built to a server\n",
kSocket->socket(),kSocket);
*/
socketStatus=KR_CLIENT;
// Send msg if any
if (msg->QueryNumberOfKeys()>0)
{
msg->AddData(TQCString("Server"),(short)QueryID());
SendMsg(msg);
}
}
else
{
tryserver=true;
}
}
else
{
printf("NO IP given..only server possible\n");
tryserver=true;
}
if (tryserver) // become a server
{
delete kSocket;
kSocket=0;
delete service;
service = 0;
// Store message
if (msg->QueryNumberOfKeys()>0)
{
bufferMsg=new KEMessage;
*bufferMsg=*msg;
}
else
{
bufferMsg=0;
}
socketStatus=KR_WAIT_FOR_CLIENT;
OfferServerSocket();
return false;
}
return true;
}
bool KRemoteConnect::OfferServerSocket()
{
if (kServerSocket)
{
return false;
}
kServerSocket=new KRServerSocket(port,SO_REUSEADDR);
if (!kServerSocket)
{
socketStatus=KR_INVALID;
return false;
}
if (kServerSocket->socket()==-1)
{
socketStatus=KR_NO_SOCKET;
return false;
}
printf("Offering socket and publishing stuff\n");
service = new DNSSD::PublicService(Name,LSKAT_SERVICE,port);
service->publishAsync();
connect(kServerSocket,TQ_SIGNAL(accepted(TDESocket *)),
this,TQ_SLOT(socketRequest(TDESocket *)));
return true;
}
void KRemoteConnect::socketRequest(TDESocket *sock)
{
if (kSocket) // already connected
{
delete sock;
delete kServerSocket;
kServerSocket=0;
return ;
}
kSocket=sock;
if (kSocket->socket()!=-1) // success
{
kSocket->enableRead(TRUE);
//kSocket->enableWrite(TRUE);
connect(kSocket,TQ_SIGNAL(closeEvent(TDESocket *)),
this,TQ_SLOT(socketClosed(TDESocket *)));
connect(kSocket,TQ_SIGNAL(readEvent(TDESocket *)),
this,TQ_SLOT(socketRead(TDESocket *)));
/*
connect(kSocket,TQ_SIGNAL(writeEvent(TDESocket *)),
this,TQ_SLOT(socketWrite(TDESocket *)));
*/
socketStatus=KR_SERVER;
delete kServerSocket; // no more connections
kServerSocket=0;
if (bufferMsg)
{
// Delayed sending of init msg
bufferMsg->AddData(TQCString("Client"),(short)QueryID());
SendMsg(bufferMsg);
delete bufferMsg;
bufferMsg=0;
}
}
}
void KRemoteConnect::socketClosed(TDESocket *sock)
{
delete sock;
kSocket=0;
socketStatus=KR_INVALID;
KEMessage *msg=new KEMessage;
msg->AddData(TQCString("ConnectionLost"),(short)QueryID());
emit signalReceiveMsg(msg,QueryID());
delete msg;
}
void KRemoteConnect::socketRead(TDESocket *sock)
{
ssize_t buflen;
TQString s;
char c;
int pos;
// printf("++++++ Incoming socket read +++++++\n");
if (-1==sock->socket()) return ;
// printf("Read input on socket %p\n",sock);
buflen=read(sock->socket(),buffer,4096);
buffer[buflen]=0;
// printf("Read %d byte <%s>\n",buflen,buffer);
if (buflen<1) return ;
if (buffer[buflen-1]!=0) // shit..we got a not null terminated string
{
c=buffer[buflen-1];
buffer[buflen-1]=0;
s=buffer;
s+=c;
}
else
{
s=buffer;
}
// Append old unresolved input
s=inputbuffer+s;
pos=s.findRev(KEMESSAGE_CR);
// printf("String '%s' pos=%d len=%d\n",(const char *)s,pos,s.length());
if (pos<0)
{
inputbuffer=s;
}
else if (pos+KEMESSAGE_CR.length()==s.length())
{
// CR at the end...calling receive
Receive(s);
}
else
{
inputbuffer=s.right(s.length()-pos-KEMESSAGE_CR.length());
s=s.left(pos+KEMESSAGE_CR.length());
// printf("s='%s' in='%s'\n",(const char *)s,(const char *)inputbuffer);
Receive(s);
}
}
void KRemoteConnect::socketWrite(TDESocket *)
{
// printf("wrtie input on socket %p\n",sock);
}
bool KRemoteConnect::Exit()
{
delete kSocket;
delete kServerSocket;
delete bufferMsg;
kSocket=0;
kServerSocket=0;
bufferMsg=0;
socketStatus=KR_INVALID;
return true;
}
bool KRemoteConnect::Next()
{
bool result;
// printf("+- KRemoteConnect::Next() status=%d\n",socketStatus);
if (socketStatus<=0) return false;
// create and send message
KEMessage *msg=new KEMessage;
// User fills message
emit signalPrepareMove(msg,KG_INPUTTYPE_REMOTE);
result=SendMsg(msg);
delete msg;
return result;
}
// Send string to child
bool KRemoteConnect::Send(TQString str)
{
// connected?
if (!kSocket || kSocket->socket()==-1) return false;
if (socketStatus<=0) return false;
if (-1==write(kSocket->socket(),str.latin1(),str.length()+1))
{
printf("Warning: Problems writing to socket.\n");
return false;
}
return true;;
}