From 43cd66c08de4447998028179d20fd4817aaf16ca Mon Sep 17 00:00:00 2001 From: korovkin Date: Thu, 06 Jul 2006 16:28:08 +0000 Subject: Added OBEX Push functionality for Bluetooth. - Added ObexBase - asic class for IR and BT Obex - Added ObexServer - OBEX Push server. --- (limited to 'core') diff --git a/core/obex/.cvsignore b/core/obex/.cvsignore index ed75078..90f9614 100644 --- a/core/obex/.cvsignore +++ b/core/obex/.cvsignore @@ -2,3 +2,5 @@ Makefile moc_* .moc .obj +obexsendbase.h +obexsendbase.cpp diff --git a/core/obex/btobex.cpp b/core/obex/btobex.cpp index a5bfe5f..212a084 100644 --- a/core/obex/btobex.cpp +++ b/core/obex/btobex.cpp @@ -1,3 +1,33 @@ +/* +               =. This file is part of the OPIE Project +             .=l. Copyright (c) 2002 Maximilian Reiss +           .>+-= + _;:,     .>    :=|. This library is free software; you can +.> <,   >  .   <= redistribute it and/or modify it under +:=1 )Y*s>-.--   : the terms of the GNU Library General Public +.="- .-=="i,     .._ License as published by the Free Software + - .   .-<_>     .<> Foundation; version 2 of the License. +     ._= =}       : +    .%+i>       _;_. +    .i_,=:_.      -: PARTICULAR PURPOSE. See the GNU +..}^=.=       =       ; Library General Public License for more +++=   -.     .     .: details. + :     =  ...= . :.=- + -.   .:....=;==+<; You should have received a copy of the GNU +  -_. . .   )=.  = Library General Public License along with +   --        :-= this library; see the file COPYING.LIB. + If not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + +*/ +/* + * The Bluetooth OBEX manipulating class implementation + */ #include "btobex.h" #include @@ -20,16 +50,10 @@ using namespace Opie::Core; using namespace OpieTooth; BtObex::BtObex( QObject *parent, const char* name ) - : QObject(parent, name ) + : ObexBase(parent, name ) { m_rec = 0; m_send=0; - m_count = 0; - m_receive = false; - connect( this, SIGNAL(error(int) ), // for recovering to receive - SLOT(slotError() ) ); - connect( this, SIGNAL(sent(bool) ), - SLOT(slotError() ) ); btManager = NULL; }; @@ -40,12 +64,11 @@ BtObex::~BtObex() { } void BtObex::receive() { - m_receive = true; - m_outp = QString::null; - m_rec = new OProcess(); + ObexBase::receive(); + m_rec = new ObexServer(); + odebug << "BT OBEX do receive" << oendl; // TODO mbhaynie: No idea if this actually works -- maybe opd is better. - *m_rec << "obexftpd" << "-b"; // connect to the necessary slots connect(m_rec, SIGNAL(processExited(Opie::Core::OProcess*) ), this, SLOT(slotExited(Opie::Core::OProcess*) ) ); @@ -61,10 +84,8 @@ void BtObex::receive() { } void BtObex::send( const QString& fileName, const QString& bdaddr) { + ObexBase::send(fileName, bdaddr); // if currently receiving stop it send receive - m_count = 0; - m_file = fileName; - m_bdaddr = bdaddr; if (m_send != 0) { if (m_send->isSending()) return; @@ -150,6 +171,10 @@ void BtObex::sendNow(){ connect(m_send, SIGNAL(status(QCString&)), this, SLOT(slotPushStatus(QCString&) ) ); + /* + * FIXME: this delay is made because some cell phones understands an error + * later. + */ ::sleep(4); // now start it result = m_send->send(m_bdaddr, m_port, m_file, m_dst); @@ -171,12 +196,15 @@ void BtObex::slotExited(OProcess* proc ){ << proc->exitStatus() << oendl; if (proc == m_rec ) // receive process received(); + } void BtObex::slotStdOut(OProcess* proc, char* buf, int len){ if ( proc == m_rec ) { // only receive QByteArray ar( len ); memcpy( ar.data(), buf, len ); m_outp.append( ar ); + QCString str(buf, len); + odebug << str << oendl; } } @@ -207,6 +235,7 @@ void BtObex::received() { if (m_rec->normalExit() ) { if ( m_rec->exitStatus() == 0 ) { // we got one QString filename = parseOut(); + odebug << "OBEX " << filename << " received" << oendl; emit receivedFile( filename ); } }else{ @@ -240,10 +269,13 @@ QString BtObex::parseOut(){ * when sent is done slotError is called we will start receive again */ void BtObex::slotError() { + ObexBase::slotError(); if ( m_receive ) receive(); }; void BtObex::setReceiveEnabled( bool receive ) { + odebug << "BT OBEX setReceiveEnabled " << receive << oendl; + ObexBase::setReceiveEnabled(receive); if ( !receive ) { // m_receive = false; shutDownReceive(); diff --git a/core/obex/btobex.h b/core/obex/btobex.h index 9c1ab70..7e91c06 100644 --- a/core/obex/btobex.h +++ b/core/obex/btobex.h @@ -1,19 +1,51 @@ +/* +               =. This file is part of the OPIE Project +             .=l. Copyright (c) 2002 Maximilian Reiss +           .>+-= + _;:,     .>    :=|. This library is free software; you can +.> <,   >  .   <= redistribute it and/or modify it under +:=1 )Y*s>-.--   : the terms of the GNU Library General Public +.="- .-=="i,     .._ License as published by the Free Software + - .   .-<_>     .<> Foundation; version 2 of the License. +     ._= =}       : +    .%+i>       _;_. +    .i_,=:_.      -: PARTICULAR PURPOSE. See the GNU +..}^=.=       =       ; Library General Public License for more +++=   -.     .     .: details. + :     =  ...= . :.=- + -.   .:....=;==+<; You should have received a copy of the GNU +  -_. . .   )=.  = Library General Public License along with +   --        :-= this library; see the file COPYING.LIB. + If not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + +*/ +/* + * The Bluetooth OBEX manipulating class declaration + */ #ifndef OpieBtObex_H #define OpieBtObex_H +#include "obexbase.h" #include #include #include #include +#include "obexserver.h" namespace Opie {namespace Core {class OProcess;}} class QCopChannel; using namespace OpieTooth; namespace OpieObex { // Maybe this should be derved from Obex. - class BtObex : public QObject { + class BtObex : public ObexBase { Q_OBJECT public: /** @@ -55,16 +87,12 @@ namespace OpieObex { void done(bool); private: - uint m_count; - QString m_file; - QString m_outp; - QString m_bdaddr; int m_port; ObexPush* m_send; - Opie::Core::OProcess *m_rec; bool m_receive : 1; OpieTooth::Manager* btManager; void shutDownReceive(); + ObexServer* m_rec; private slots: diff --git a/core/obex/obex.cpp b/core/obex/obex.cpp index 36634ec..95c561a 100644 --- a/core/obex/obex.cpp +++ b/core/obex/obex.cpp @@ -1,3 +1,33 @@ +/* +               =. This file is part of the OPIE Project +             .=l. Copyright (c) 2002 Maximilian Reiss +           .>+-= + _;:,     .>    :=|. This library is free software; you can +.> <,   >  .   <= redistribute it and/or modify it under +:=1 )Y*s>-.--   : the terms of the GNU Library General Public +.="- .-=="i,     .._ License as published by the Free Software + - .   .-<_>     .<> Foundation; version 2 of the License. +     ._= =}       : +    .%+i>       _;_. +    .i_,=:_.      -: PARTICULAR PURPOSE. See the GNU +..}^=.=       =       ; Library General Public License for more +++=   -.     .     .: details. + :     =  ...= . :.=- + -.   .:....=;==+<; You should have received a copy of the GNU +  -_. . .   )=.  = Library General Public License along with +   --        :-= this library; see the file COPYING.LIB. + If not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + +*/ +/* + * The Infrared OBEX handling class implementation + */ #include "obex.h" @@ -16,24 +46,17 @@ using namespace Opie::Core; /* TRANSLATOR OpieObex::Obex */ Obex::Obex( QObject *parent, const char* name ) - : QObject(parent, name ) + : ObexBase(parent, name ) { m_rec = 0; m_send=0; - m_count = 0; - m_receive = false; - connect( this, SIGNAL(error(int) ), // for recovering to receive - SLOT(slotError() ) ); - connect( this, SIGNAL(sent(bool) ), - SLOT(slotError() ) ); }; Obex::~Obex() { delete m_rec; delete m_send; } void Obex::receive() { - m_receive = true; - m_outp = QString::null; + ObexBase::receive(); m_rec = new OProcess(); *m_rec << "irobex_palm3"; // connect to the necessary slots @@ -50,9 +73,9 @@ void Obex::receive() { } } -void Obex::send( const QString& fileName) { // if currently receiving stop it send receive - m_count = 0; - m_file = fileName; +// if currently receiving stop it send receive +void Obex::send(const QString& fileName, const QString& addr) { + ObexBase::send(fileName, addr); if (m_rec != 0 ) { if (m_rec->isRunning() ) { emit error(-1 ); @@ -165,10 +188,12 @@ QString Obex::parseOut( ){ * when sent is done slotError is called we will start receive again */ void Obex::slotError() { + ObexBase::slotError(); if ( m_receive ) receive(); }; void Obex::setReceiveEnabled( bool receive ) { + ObexBase::setReceiveEnabled(receive); if ( !receive ) { // m_receive = false; shutDownReceive(); diff --git a/core/obex/obex.h b/core/obex/obex.h index 5993976..36ff29a 100644 --- a/core/obex/obex.h +++ b/core/obex/obex.h @@ -1,14 +1,44 @@ +/* +               =. This file is part of the OPIE Project +             .=l. Copyright (c) 2002 Maximilian Reiss +           .>+-= + _;:,     .>    :=|. This library is free software; you can +.> <,   >  .   <= redistribute it and/or modify it under +:=1 )Y*s>-.--   : the terms of the GNU Library General Public +.="- .-=="i,     .._ License as published by the Free Software + - .   .-<_>     .<> Foundation; version 2 of the License. +     ._= =}       : +    .%+i>       _;_. +    .i_,=:_.      -: PARTICULAR PURPOSE. See the GNU +..}^=.=       =       ; Library General Public License for more +++=   -.     .     .: details. + :     =  ...= . :.=- + -.   .:....=;==+<; You should have received a copy of the GNU +  -_. . .   )=.  = Library General Public License along with +   --        :-= this library; see the file COPYING.LIB. + If not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +/* + * The Infrared OBEX handling class declaration + */ #ifndef OpieObex_H #define OpieObex_H +#include "obexbase.h" #include namespace Opie {namespace Core {class OProcess;}} class QCopChannel; namespace OpieObex { - class Obex : public QObject { + class Obex : public ObexBase { Q_OBJECT public: /** @@ -24,9 +54,9 @@ namespace OpieObex { * Starting listening to irda after enabled by the applet * a signal gets emitted when received a file */ - void receive(); - void send( const QString& ); - void setReceiveEnabled( bool = false ); + virtual void receive(); + virtual void send(const QString& filename, const QString& addr); + virtual void setReceiveEnabled( bool = false ); signals: /** @@ -69,7 +99,7 @@ private slots: // the process exited void slotExited(Opie::Core::OProcess* proc) ; void slotStdOut(Opie::Core::OProcess*, char*, int); - void slotError(); + virtual void slotError(); private: void sendNow(); diff --git a/core/obex/obex.pro b/core/obex/obex.pro index 33cb957..1fc6958 100644 --- a/core/obex/obex.pro +++ b/core/obex/obex.pro @@ -1,14 +1,20 @@ TEMPLATE = lib CONFIG += qt warn_on -HEADERS = obex.h btobex.h obexhandler.h obexsend.h receiver.h obeximpl.h -SOURCES = obex.cpp btobex.cpp obexsend.cpp obexhandler.cpp receiver.cpp obeximpl.cpp +HEADERS = obex.h btobex.h obexhandler.h obexsend.h receiver.h obeximpl.h obexbase.h obexserver.h +SOURCES = obex.cpp btobex.cpp obexsend.cpp obexhandler.cpp receiver.cpp obeximpl.cpp obexbase.cpp obexserver.cpp TARGET = opieobex DESTDIR = $(OPIEDIR)/plugins/obex INTERFACES = obexsendbase.ui -INCLUDEPATH += $(OPIEDIR)/include $(OPIEDIR)/core/launcher $(OPIEDIR)/noncore/net/opietooth/lib +INCLUDEPATH += $(OPIEDIR)/include $(OPIEDIR)/core/launcher DEPENDPATH += -LIBS += -lopietooth1 -lqpe -lopiecore2 -VERSION = 0.0.3 +LIBS += -lqpe -lopiecore2 +VERSION = 0.0.4 include( $(OPIEDIR)/include.pro ) target.path = $$prefix/plugins/applets + +#FIXME: These parameters are used if bluetooth is used +INCLUDEPATH += $(OPIEDIR)/noncore/net/opietooth/lib +LIBS += -lopietooth1 -lbluetooth -lopenobex +DEFINES += BLUETOOTH + diff --git a/core/obex/obexbase.cpp b/core/obex/obexbase.cpp new file mode 100644 index 0000000..8eda04e --- a/dev/null +++ b/core/obex/obexbase.cpp @@ -0,0 +1,74 @@ +/* +               =. This file is part of the OPIE Project +             .=l. Copyright (c) 2002 Maximilian Reiss +           .>+-= + _;:,     .>    :=|. This library is free software; you can +.> <,   >  .   <= redistribute it and/or modify it under +:=1 )Y*s>-.--   : the terms of the GNU Library General Public +.="- .-=="i,     .._ License as published by the Free Software + - .   .-<_>     .<> Foundation; version 2 of the License. +     ._= =}       : +    .%+i>       _;_. +    .i_,=:_.      -: PARTICULAR PURPOSE. See the GNU +..}^=.=       =       ; Library General Public License for more +++=   -.     .     .: details. + :     =  ...= . :.=- + -.   .:....=;==+<; You should have received a copy of the GNU +  -_. . .   )=.  = Library General Public License along with +   --        :-= this library; see the file COPYING.LIB. + If not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + +*/ +/* + * The basic class for OBEX manipulating classes implementation + */ + +#include "obexbase.h" + +/* OPIE */ +#include +#include + +using namespace OpieObex; + +using namespace Opie::Core; + +ObexBase::ObexBase(QObject *parent, const char* name) + : QObject(parent, name) +{ + m_count = 0; + m_receive = false; + connect( this, SIGNAL(error(int) ), // for recovering to receive + SLOT(slotError() ) ); + connect( this, SIGNAL(sent(bool) ), + SLOT(slotError() ) ); +} + +ObexBase::~ObexBase() { +} + +void ObexBase::receive() { + m_receive = true; + m_outp = QString::null; +} + +void ObexBase::send( const QString& fileName, const QString& bdaddr) { + // if currently receiving stop it send receive + m_count = 0; + m_file = fileName; + m_bdaddr = bdaddr; +} + +void ObexBase::setReceiveEnabled(bool) { +} + +void ObexBase::slotError() { +} + +//eof diff --git a/core/obex/obexbase.h b/core/obex/obexbase.h new file mode 100644 index 0000000..f65d922 --- a/dev/null +++ b/core/obex/obexbase.h @@ -0,0 +1,99 @@ +/* +               =. This file is part of the OPIE Project +             .=l. Copyright (c) 2002 Maximilian Reiss +           .>+-= + _;:,     .>    :=|. This library is free software; you can +.> <,   >  .   <= redistribute it and/or modify it under +:=1 )Y*s>-.--   : the terms of the GNU Library General Public +.="- .-=="i,     .._ License as published by the Free Software + - .   .-<_>     .<> Foundation; version 2 of the License. +     ._= =}       : +    .%+i>       _;_. +    .i_,=:_.      -: PARTICULAR PURPOSE. See the GNU +..}^=.=       =       ; Library General Public License for more +++=   -.     .     .: details. + :     =  ...= . :.=- + -.   .:....=;==+<; You should have received a copy of the GNU +  -_. . .   )=.  = Library General Public License along with +   --        :-= this library; see the file COPYING.LIB. + If not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + +*/ +/* + * The basic class for OBEX manipulating classes declaration + */ +#ifndef ObexBase_H +#define ObexBase_H + +#include + +namespace Opie {namespace Core {class OProcess;}} +class QCopChannel; +namespace OpieObex { + class ObexBase : public QObject { + Q_OBJECT + public: + /** + * ObexBase constructor look + */ + ObexBase(QObject *parent, const char* name); + /** + * d'tor + */ + virtual ~ObexBase(); + /** + * Starting listening to an interface after enabled by the applet + * a signal gets emitted when received a file + */ + virtual void receive(); + /** + * Send the file + * @param the name of the file + * @param the address of the device + */ + virtual void send(const QString&, const QString&); + /** + * Stop receiving + * @param if true - does nothing if false - stops receiving + */ + virtual void setReceiveEnabled(bool = false); + signals: + /** + * Notify the upper level that we have received the file + * @param path The path to the received file + */ + void receivedFile(const QString& path); + /** + * error signal if the program couldn't be started or the + * the connection timed out + */ + void error(int); + /** + * The current try to receive data + */ + void currentTry(unsigned int); + /** + * signal sent The file got beamed to the remote location + */ + void sent(bool); + void done(bool); + protected: + uint m_count; + QString m_file; + QString m_outp; + QString m_bdaddr; + bool m_receive : 1; + protected slots: + virtual void slotError(); + }; +}; + +#endif +//eof + diff --git a/core/obex/obexhandler.cpp b/core/obex/obexhandler.cpp index 28f9b5b..5d98ded 100644 --- a/core/obex/obexhandler.cpp +++ b/core/obex/obexhandler.cpp @@ -11,16 +11,20 @@ using namespace OpieObex; /* TRANSLATOR OpieObex::ObexHandler */ ObexHandler::ObexHandler() { - m_wasRec = false; + m_wasRec[REC_IRDA] = false; + m_receiver[REC_IRDA] = 0l; + m_wasRec[REC_BLUETOOTH] = false; + m_receiver[REC_BLUETOOTH] = 0l; m_sender = 0l; - m_receiver = 0l; + m_type = REC_IRDA; //FIXME: Just to init to something QCopChannel* chan = new QCopChannel("QPE/Obex"); connect(chan, SIGNAL(received(const QCString&,const QByteArray&) ), this, SLOT(irdaMessage(const QCString&,const QByteArray&) ) ); } ObexHandler::~ObexHandler() { delete m_sender; - delete m_receiver; + delete m_receiver[REC_IRDA]; + delete m_receiver[REC_BLUETOOTH]; } void ObexHandler::doSend(const QString& str, const QString& desc) { delete m_sender; @@ -31,14 +35,14 @@ void ObexHandler::doSend(const QString& str, const QString& desc) { this, SLOT(slotSent() ) ); m_sender->send( str, desc ); } -void ObexHandler::doReceive(bool b) { - if (m_receiver && b ) return; // we should enable receiver and it is on - else if (!m_receiver && !b ) return; // we should disbale receiver and it is off - else if (m_receiver && !b ) { - delete m_receiver; - m_receiver=0; - }else if (!m_receiver && b ) { - m_receiver= new Receiver; +void ObexHandler::doReceive(RecType type, bool b) { + if (m_receiver[type] && b ) return; // we should enable receiver and it is on + else if (!m_receiver[type] && !b ) return; // we should disbale receiver and it is off + else if (m_receiver[type] && !b ) { + delete m_receiver[type]; + m_receiver[type] = 0; + }else if (!m_receiver[type] && b ) { + m_receiver[type] = new Receiver(type); } } void ObexHandler::slotSent() { @@ -47,8 +51,10 @@ void ObexHandler::slotSent() { m_sender = 0; QCopEnvelope e ("QPE/Obex", "done(QString)" ); e << file; - doReceive(m_wasRec ); - m_wasRec = false; + doReceive(REC_IRDA, m_wasRec[REC_IRDA]); + doReceive(REC_BLUETOOTH, m_wasRec[REC_BLUETOOTH]); + m_wasRec[REC_IRDA] = false; + m_wasRec[REC_BLUETOOTH] = false; } void ObexHandler::irdaMessage( const QCString& msg, const QByteArray& data) { QDataStream stream( data, IO_ReadOnly ); @@ -56,12 +62,18 @@ void ObexHandler::irdaMessage( const QCString& msg, const QByteArray& data) { QString name, desc; stream >> desc; stream >> name; - m_wasRec = (m_receiver != 0 ); - doReceive( false ); + m_wasRec[REC_IRDA] = (m_receiver[REC_IRDA] != 0 ); + m_wasRec[REC_BLUETOOTH] = (m_receiver[REC_BLUETOOTH] != 0 ); + doReceive(REC_IRDA, false); + doReceive(REC_BLUETOOTH, false); doSend(name, desc); }else if (msg == "receive(int)") { int rec; stream >> rec; - doReceive(rec); + doReceive(REC_IRDA, rec); + }else if (msg == "btreceive(int)") { + int rec; + stream >> rec; + doReceive(REC_BLUETOOTH, rec); } } diff --git a/core/obex/obexhandler.h b/core/obex/obexhandler.h index 230c4f0..de2232e 100644 --- a/core/obex/obexhandler.h +++ b/core/obex/obexhandler.h @@ -3,6 +3,7 @@ #include #include +#include "receiver.h" namespace OpieObex { /* @@ -21,7 +22,7 @@ namespace OpieObex { private slots: void doSend(const QString&,const QString& ); - void doReceive(bool b); + void doReceive(RecType type, bool b); void slotSent(); private slots: // QCOP message @@ -29,9 +30,9 @@ namespace OpieObex { private: SendWidget* m_sender; - Receiver* m_receiver; - bool m_wasRec : 1; - + Receiver* m_receiver[2]; //For IRDA and Bluetooth + bool m_wasRec[2]; + RecType m_type; //receiver type (IRDA or Bluetooth) }; } diff --git a/core/obex/obexsend.cpp b/core/obex/obexsend.cpp index 8432d16..9a30a0a 100644 --- a/core/obex/obexsend.cpp +++ b/core/obex/obexsend.cpp @@ -148,7 +148,7 @@ void SendWidget::slotStartIrda() { return; } setReceiverStatus( m_irDaIt.key(), tr("Start sending") ); - m_obex->send( m_file ); + m_obex->send( m_file, tr("noaddress") ); } void SendWidget::dispatchBt( const QCString& str, const QByteArray& ar ) { diff --git a/core/obex/obexserver.cpp b/core/obex/obexserver.cpp new file mode 100644 index 0000000..95196de --- a/dev/null +++ b/core/obex/obexserver.cpp @@ -0,0 +1,514 @@ +/* +               =. This file is part of the OPIE Project +             .=l. Copyright (c) 2002 Maximilian Reiss +           .>+-= + _;:,     .>    :=|. This library is free software; you can +.> <,   >  .   <= redistribute it and/or modify it under +:=1 )Y*s>-.--   : the terms of the GNU Library General Public +.="- .-=="i,     .._ License as published by the Free Software + - .   .-<_>     .<> Foundation; version 2 of the License. +     ._= =}       : +    .%+i>       _;_. +    .i_,=:_.      -: PARTICULAR PURPOSE. See the GNU +..}^=.=       =       ; Library General Public License for more +++=   -.     .     .: details. + :     =  ...= . :.=- + -.   .:....=;==+<; You should have received a copy of the GNU +  -_. . .   )=.  = Library General Public License along with +   --        :-= this library; see the file COPYING.LIB. + If not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + +*/ +/* + * The OBEX server class implementation + * Based on OBEX server from GPE (thanks, guys) + */ + +#include "obexserver.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace Opie::Core; +using namespace Opie::Core::Internal; +using namespace OpieObex; + +ObexServer::ObexServer() : + OProcess(tr("ObexServer"), 0, "ObexServer") +{ + m_obex = NULL; +} + +ObexServer::~ObexServer() +{ + stop(); +} + +/** + * Function handles the file received + * @param name the file name + * @param data the file data + * @param data_len the data length + * @return 0 on success -1 on error + */ +static int file_received(uint8_t* name, const uint8_t* data, size_t data_len) +{ + QString path("/tmp/"); + path += (char*)name; + QFile out(path); + int err = 0; + + if (!out.open(IO_Raw | IO_ReadWrite | IO_Truncate)) { + printf("File %s open error %d\n", (const char*)path, errno); + err = -1; + goto out; + } + if (out.writeBlock((const char*)data, data_len) < 0) { + printf("File %s write error %d\n", (const char*)path, errno); + err = -1; + goto out; + } +out: + out.close(); + if (err == 0) { + printf("Wrote %s (%d bytes)\n", (const char*)path, data_len); + fflush(stdout); + } + return err; +} + +/** + * Function handles the situation when the PUT request has been done + * @param handle OBEX connection handle + * @param object OBEX object itself + */ +static int put_done(obex_t* handle, obex_object_t* object) +{ + obex_headerdata_t hv; //Received file header + uint8_t hi; //Type of the request + uint32_t hlen; //File (file name) length + int err = 0; + + const uint8_t *body = NULL; + int body_len = 0; + uint8_t* name = NULL; + + while (OBEX_ObjectGetNextHeader (handle, object, &hi, &hv, &hlen)) { + switch(hi) { + case OBEX_HDR_BODY: + body = hv.bs; + body_len = hlen; + break; + + case OBEX_HDR_NAME: + name = new uint8_t[(hlen / 2) + 1]; + OBEX_UnicodeToChar(name, hv.bs, hlen); + break; + + default: + break; + } + } + + if (body) + err = file_received(name, body, body_len); + + if (name) + delete[] name; + return err; +} + +/** + * Function handles OBEX request + * @param handle OBEX connection handle + * @param object OBEX object itself + * @param mode + * @param event event code + * @param cmd OBEX command itself + */ +static void handle_request (obex_t* handle, obex_object_t* object, + int event, int cmd) +{ + (void)event; + switch(cmd) { + case OBEX_CMD_SETPATH: + OBEX_ObjectSetRsp (object, OBEX_RSP_CONTINUE, OBEX_RSP_SUCCESS); + break; + case OBEX_CMD_PUT: + if (put_done (handle, object) < 0) + OBEX_ObjectSetRsp (object, OBEX_RSP_INTERNAL_SERVER_ERROR, + OBEX_RSP_INTERNAL_SERVER_ERROR); + else + OBEX_ObjectSetRsp (object, OBEX_RSP_CONTINUE, OBEX_RSP_SUCCESS); + break; + case OBEX_CMD_CONNECT: + OBEX_ObjectSetRsp (object, OBEX_RSP_SUCCESS, OBEX_RSP_SUCCESS); + break; + case OBEX_CMD_DISCONNECT: + OBEX_ObjectSetRsp (object, OBEX_RSP_SUCCESS, OBEX_RSP_SUCCESS); + break; + default: + printf("Denied %02x request\n", cmd); + fflush(stdout); + OBEX_ObjectSetRsp (object, OBEX_RSP_NOT_IMPLEMENTED, + OBEX_RSP_NOT_IMPLEMENTED); + break; + } +} + + +/** + * Function handles OBEX event when a client is connected to the server + * @param handle OBEX connection handle + * @param object OBEX object itself + * @param mode + * @param event event code + * @param obex_cmd OBEX command itself + * @param obex_rsp OBEX responce + */ +static void obex_conn_event (obex_t *handle, obex_object_t *object, + int mode, int event, int obex_cmd, int obex_rsp) +{ + (void)mode; + (void)obex_rsp; + + switch(event) { + case OBEX_EV_REQHINT: + switch(obex_cmd) { + case OBEX_CMD_PUT: + case OBEX_CMD_CONNECT: + case OBEX_CMD_DISCONNECT: + OBEX_ObjectSetRsp (object, OBEX_RSP_CONTINUE, OBEX_RSP_SUCCESS); + break; + default: + OBEX_ObjectSetRsp (object, OBEX_RSP_NOT_IMPLEMENTED, + OBEX_RSP_NOT_IMPLEMENTED); + break; + } + break; + + case OBEX_EV_REQ: + /* Comes when a server-request has been received. */ + handle_request (handle, object, event, obex_cmd); + break; + + case OBEX_EV_LINKERR: + break; + } +} + +/** + * Function handles OBEX event + * @param handle OBEX connection handle + * @param object OBEX object itself + * @param mode + * @param event event code + * @param obex_cmd OBEX command itself + * @param obex_rsp OBEX responce + */ +static void obex_event (obex_t* handle, obex_object_t* object, int mode, + int event, int obex_cmd, int obex_rsp) +{ + + obex_t *obex; //OBEX connection handle + + switch (event) { + case OBEX_EV_ACCEPTHINT: + obex = OBEX_ServerAccept (handle, obex_conn_event, NULL); + break; + + default: + obex_conn_event(handle, object, mode, event, obex_cmd, obex_rsp); + } +} + +/** + * Function registers OBEX push service on a specified channel + * Based on The same function from GPE. + * @param session SDP session + * @param chan channel to listen + * @name name to show + */ +sdp_session_t* ObexServer::addOpushSvc(uint8_t chan, const char* name) +{ + sdp_list_t *svclass_id, *pfseq, *apseq, *root; + uuid_t root_uuid, opush_uuid, l2cap_uuid, rfcomm_uuid, obex_uuid; + sdp_profile_desc_t profile[1]; + sdp_list_t *aproto, *proto[3]; + sdp_record_t record; + sdp_data_t *channel; + uint8_t formats[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 }; + //uint8_t formats[] = { 0xff }; + void *dtds[sizeof(formats)], *values[sizeof(formats)]; + unsigned int i; + uint8_t dtd = SDP_UINT8; + sdp_data_t *sflist; + int err = 0; + sdp_session_t* lsession = 0; + + memset((void *)&record, 0, sizeof(sdp_record_t)); + record.handle = 0xffffffff; + sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); + root = sdp_list_append(0, &root_uuid); + sdp_set_browse_groups(&record, root); + + sdp_uuid16_create(&opush_uuid, OBEX_OBJPUSH_SVCLASS_ID); + svclass_id = sdp_list_append(0, &opush_uuid); + sdp_set_service_classes(&record, svclass_id); + + sdp_uuid16_create(&profile[0].uuid, OBEX_OBJPUSH_PROFILE_ID); + profile[0].version = 0x0100; + pfseq = sdp_list_append(0, profile); + sdp_set_profile_descs(&record, pfseq); + + sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); + proto[0] = sdp_list_append(0, &l2cap_uuid); + apseq = sdp_list_append(0, proto[0]); + + sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID); + proto[1] = sdp_list_append(0, &rfcomm_uuid); + channel = sdp_data_alloc(SDP_UINT8, &chan); + proto[1] = sdp_list_append(proto[1], channel); + apseq = sdp_list_append(apseq, proto[1]); + + sdp_uuid16_create(&obex_uuid, OBEX_UUID); + proto[2] = sdp_list_append(0, &obex_uuid); + apseq = sdp_list_append(apseq, proto[2]); + + aproto = sdp_list_append(0, apseq); + sdp_set_access_protos(&record, aproto); + + for (i = 0; i < sizeof(formats); i++) + { + dtds[i] = &dtd; + values[i] = &formats[i]; + } + sflist = sdp_seq_alloc(dtds, values, sizeof(formats)); + sdp_attr_add(&record, SDP_ATTR_SUPPORTED_FORMATS_LIST, sflist); + + sdp_set_info_attr(&record, name, 0, 0); + + // connect to the local SDP server, register the service record, and + // disconnect + lsession = sdp_connect(BDADDR_ANY, BDADDR_LOCAL, SDP_RETRY_IF_BUSY); + if (lsession == NULL) + goto errout; + err = sdp_record_register(lsession, &record, 0); + if (err) { + sdp_close(lsession); + lsession = NULL; + } +errout: + sdp_data_free(channel); + sdp_list_free(proto[0], 0); + sdp_list_free(proto[1], 0); + sdp_list_free(proto[2], 0); + sdp_list_free(apseq, 0); + sdp_list_free(aproto, 0); + + return lsession; +} + +int ObexServer::initObex(void) +{ + int channel = 10; //Channel on which we do listen + if (m_obex) + return 0; + m_obex = ::OBEX_Init(OBEX_TRANS_BLUETOOTH, obex_event, 0); + if (!m_obex) { + printf("OBEX initialization error %d\n", errno); + return -1; + } + ::BtOBEX_ServerRegister(m_obex, NULL, channel); + m_session = addOpushSvc(channel, "OBEX push service"); + if (!m_session) { + printf("OBEX registration error %d\n", errno); + ::OBEX_Cleanup(m_obex); + m_obex = NULL; + return -1; + } + return 0; +} + +bool ObexServer::start(RunMode runmode, Communication comm) +{ + if ( runs ) + { + return false; // cannot start a process that is already running + // or if no executable has been assigned + } + run_mode = runmode; + status = 0; + + if ( !setupCommunication( comm ) ) + qWarning( "Could not setup Communication!" ); + + // We do this in the parent because if we do it in the child process + // gdb gets confused when the application runs from gdb. + uid_t uid = getuid(); + gid_t gid = getgid(); +#ifdef HAVE_INITGROUPS + + struct passwd *pw = getpwuid( uid ); +#endif + + int fd[ 2 ]; + if ( 0 > pipe( fd ) ) + { + fd[ 0 ] = fd[ 1 ] = 0; // Pipe failed.. continue + } + + runs = true; + + QApplication::flushX(); + + // WABA: Note that we use fork() and not vfork() because + // vfork() has unclear semantics and is not standardized. + pid_ = fork(); + + if ( 0 == pid_ ) + { + if ( fd[ 0 ] ) + close( fd[ 0 ] ); + if ( !runPrivileged() ) + { + setgid( gid ); +#if defined( HAVE_INITGROUPS) + + if ( pw ) + initgroups( pw->pw_name, pw->pw_gid ); +#endif + + setuid( uid ); + } + // The child process + if ( !commSetupDoneC() ) + qWarning( "Could not finish comm setup in child!" ); + + setupEnvironment(); + + // Matthias + if ( run_mode == DontCare ) + setpgid( 0, 0 ); + // restore default SIGPIPE handler (Harri) + struct sigaction act; + sigemptyset( &( act.sa_mask ) ); + sigaddset( &( act.sa_mask ), SIGPIPE ); + act.sa_handler = SIG_DFL; + act.sa_flags = 0; + sigaction( SIGPIPE, &act, 0L ); + + // We set the close on exec flag. + // Closing of fd[1] indicates that the execvp succeeded! + if ( fd[ 1 ] ) + fcntl( fd[ 1 ], F_SETFD, FD_CLOEXEC ); + + if (initObex() == 0) { + do { + int result; //Connection result + if ( fd[ 1 ] ) { + ::close(fd[1]); + fd[1] = 0; + } + if ((result = OBEX_HandleInput(m_obex, 60)) < 0) { + if (errno != ECONNRESET) { + printf("OBEX_HandleInput error %d\n", errno); + fflush(stdout); + _exit(-1); + } + else + _exit(0); + } + } while(1); + } + char resultByte = 1; + if ( fd[ 1 ] ) + write( fd[ 1 ], &resultByte, 1 ); + _exit( -1 ); + } + else if ( -1 == pid_ ) + { + // forking failed + + runs = false; + return false; + } + else + { + if ( fd[ 1 ] ) + close( fd[ 1 ] ); + // the parent continues here + + // Discard any data for stdin that might still be there + input_data = 0; + + // Check whether client could be started. + if ( fd[ 0 ] ) + for ( ;; ) + { + char resultByte; + int n = ::read( fd[ 0 ], &resultByte, 1 ); + if ( n == 1 ) + { + // Error + runs = false; + close( fd[ 0 ] ); + pid_ = 0; + return false; + } + if ( n == -1 ) + { + if ( ( errno == ECHILD ) || ( errno == EINTR ) ) + continue; // Ignore + } + break; // success + } + if ( fd[ 0 ] ) + close( fd[ 0 ] ); + + if ( !commSetupDoneP() ) // finish communication socket setup for the parent + qWarning( "Could not finish comm setup in parent!" ); + + if ( run_mode == Block ) + { + commClose(); + + // The SIGCHLD handler of the process controller will catch + // the exit and set the status + while ( runs ) + { + OProcessController::theOProcessController-> + slotDoHousekeeping( 0 ); + } + runs = FALSE; + emit processExited( this ); + } + } + return true; +} + +/* + * Stop forwarding process + */ +int ObexServer::stop() +{ + kill(SIGTERM); + return 0; +} + +//eof diff --git a/core/obex/obexserver.h b/core/obex/obexserver.h new file mode 100644 index 0000000..8567105 --- a/dev/null +++ b/core/obex/obexserver.h @@ -0,0 +1,83 @@ +/* +               =. This file is part of the OPIE Project +             .=l. Copyright (c) 2002 Maximilian Reiss +           .>+-= + _;:,     .>    :=|. This library is free software; you can +.> <,   >  .   <= redistribute it and/or modify it under +:=1 )Y*s>-.--   : the terms of the GNU Library General Public +.="- .-=="i,     .._ License as published by the Free Software + - .   .-<_>     .<> Foundation; version 2 of the License. +     ._= =}       : +    .%+i>       _;_. +    .i_,=:_.      -: PARTICULAR PURPOSE. See the GNU +..}^=.=       =       ; Library General Public License for more +++=   -.     .     .: details. + :     =  ...= . :.=- + -.   .:....=;==+<; You should have received a copy of the GNU +  -_. . .   )=.  = Library General Public License along with +   --        :-= this library; see the file COPYING.LIB. + If not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + +*/ +/* + * The OBEX server class declaration + * Based on OBEX server from GPE (thanks, guys) + */ +#ifndef ObexServer_H +#define ObexServer_H + +#include +#include + +#include +#include + +#include + +namespace Opie { + namespace Core { + class OProcess; + namespace Internal { + class OProcessController; + } + } +}; + +namespace Opie {namespace Core {class OProcess;}} +namespace OpieObex { + class ObexServer : public Opie::Core::OProcess { + Q_OBJECT + public: + /** + * ObexServer constructor + */ + ObexServer(); + /** + * + */ + ~ObexServer(); + //Function starts the server process + virtual bool start( RunMode runmode = NotifyOnExit, + Communication comm = NoCommunication ); + //Stop the server process + int stop(); + protected: //variables + obex_t* m_obex; //Obex server handler + sdp_session_t* m_session; //SDP session handler; + protected: //functions + //Funtion initializes obex server return 0 on success and -1 on error + int initObex(void); + //Function registers an OBEX push service + sdp_session_t* addOpushSvc(uint8_t chan, const char* name); + signals: + protected slots: + }; +}; + +#endif diff --git a/core/obex/receiver.cpp b/core/obex/receiver.cpp index 7d9a42a..e153152 100644 --- a/core/obex/receiver.cpp +++ b/core/obex/receiver.cpp @@ -1,4 +1,6 @@ #include "obex.h" +#include "btobex.h" +#include "obexbase.h" #include "receiver.h" using namespace OpieObex; @@ -26,8 +28,11 @@ using namespace Opie::Core; /* TRANSLATOR OpieObex::Receiver */ -Receiver::Receiver() { - m_obex = new Obex(this, "Receiver"); +Receiver::Receiver(RecType type) { + if (type == REC_IRDA) + m_obex = new Obex(this, "Receiver"); + else + m_obex = new BtObex(this, "Receiver"); connect(m_obex, SIGNAL(receivedFile(const QString&) ), this, SLOT(slotReceived(const QString&) ) ); m_obex->receive(); diff --git a/core/obex/receiver.h b/core/obex/receiver.h index e1d54df..a10ea13 100644 --- a/core/obex/receiver.h +++ b/core/obex/receiver.h @@ -5,16 +5,22 @@ #include #include +//Receiver type +typedef enum _RecType { + REC_IRDA = 0, + REC_BLUETOOTH = 1 +} RecType; + class QLabel; class QTextView; namespace OpieObex { - class Obex; + class ObexBase; class OtherHandler; class Receiver : public QObject { Q_OBJECT public: enum { Datebook , AddressBook, Other }; - Receiver(); + Receiver(RecType type); ~Receiver(); private: @@ -32,7 +38,7 @@ namespace OpieObex { void slotReceived( const QString& ); private: - Obex* m_obex; + ObexBase* m_obex; //IR obex }; class OtherHandler : public QVBox { -- cgit v0.9.0.2