📄 qirserver.cpp
字号:
/************************************************************************ Copyright (C) 2000-2002 Trolltech AS. All rights reserved.**** This file is part of the Qtopia Environment.**** Licensees holding valid Qtopia Developer license may use this** file in accordance with the Qtopia Developer License Agreement** provided with the Software.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING** THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR** PURPOSE.**** email sales@trolltech.com for information about Qtopia License** Agreements.**** Contact info@trolltech.com if any conditions of this licensing are** not clear to you.************************************************************************/#include "qirserver.h"#include <qtopia/mimetype.h>#include <qtopia/qcopenvelope_qws.h>#include <qtopia/private/task.h>#include <qsocketnotifier.h>#include <qfile.h>#include <qtimer.h>#include <sys/stat.h>#include <sys/types.h>#include <fcntl.h>#include <unistd.h>#include <stdlib.h>//#define QTOPIA_DEBUG_OBEXextern "C" { #include "openobex/obex.h"}class QObexBase :public QObject{ Q_OBJECT;public: QObexBase( QObject *parent = 0, const char *name = 0 ); ~QObexBase();signals: void error(); void statusMsg(const QString &);public slots: void abort();protected slots: void deleteMeLater(); void processInput(); protected: virtual void doPending() = 0; void connectSocket(); obex_t *self; bool finished; bool aborted;private slots: void deleteThis();};QObexBase::QObexBase( QObject *parent , const char *name ) :QObject( parent, name ){ finished = FALSE; aborted = FALSE;}QObexBase::~QObexBase(){ OBEX_Cleanup( self );}void QObexBase::connectSocket(){ QSocketNotifier *sn = new QSocketNotifier( OBEX_GetFD( self ), QSocketNotifier::Read, this ); connect( sn, SIGNAL(activated(int)), this, SLOT(processInput()) );}void QObexBase::deleteMeLater(){ QTimer::singleShot( 0, this, SLOT(deleteThis()) );}void QObexBase::deleteThis(){ delete this;}void QObexBase::abort(){ aborted = TRUE; finished = TRUE;}void QObexBase::processInput(){ if ( !aborted ) OBEX_HandleInput( self, 0 ); if ( aborted ) deleteMeLater(); else if ( finished ) doPending();}static void qobex_sender_callback(obex_t *handle, obex_object_t *obj, gint mode, gint event, gint obex_cmd, gint obex_rsp);class QObexSender : public QObexBase{ Q_OBJECT;public: QObexSender( QObject *parent = 0, const char *name = 0 ); ~QObexSender(); void beam( const QString& filename, const QString& mimetype );signals: void done(); void progress(int);private slots: void tryConnecting(); private: friend void qobex_sender_callback(obex_t *handle, obex_object_t *obj, gint mode, gint event, gint obex_cmd, gint obex_rsp); enum State { Init, Connecting, Streaming, Disconnecting, Error }; void process( obex_object_t *object ) { if( object && OBEX_Request(self, object) < 0) { /* Error */ qWarning( "could not request" ); state = Error; finished = TRUE; } else { finished = FALSE; } } void feedStream( obex_object_t *); void updateProgress( obex_object_t *); void doPending(); void putFile( const QString&, const QString& ); QString file_to_send; QString mime_to_send; QFile *file_being_sent; State state; int connectCount;};class QObexReceiver;static void qobex_server_callback(obex_t *handle, obex_object_t *object, gint mode, gint event, gint obex_cmd, gint obex_rsp);class QObexServer : public QObexBase{ Q_OBJECT;public: QObexServer( QObject *parent = 0, const char *name = 0 ); ~QObexServer();protected: void doPending();signals: void receiving(bool); void receiving( int size, const QString & name ); void received( const QString & name );private: friend void qobex_server_callback(obex_t *handle, obex_object_t *object, gint mode, gint event, gint obex_cmd, gint obex_rs); void spawnReceiver( obex_t *handle ); enum State { Init, Connecting, Receiving, Disconnecting, Finished, Error, Aborted }; State state;};static void qobex_receiver_callback(obex_t *handle, obex_object_t *object, gint mode, gint event, gint obex_cmd, gint obex_rsp);class QObexReceiver : public QObexBase{ Q_OBJECT;public: QObexReceiver( obex_t *handle, QObject *parent = 0, const char *name = 0 ); ~QObexReceiver();protected: void doPending();signals: void receiving(bool); void receiving( int size, const QString & name, const QString & mime ); void progress( int size ); void received( const QString & name, const QString & mime );private: friend void qobex_receiver_callback(obex_t *handle, obex_object_t *object, gint mode, gint event, gint obex_cmd, gint obex_rsp); enum State { Init, Connecting, Receiving, Disconnecting, Finished, Error, Aborted }; void readData( obex_object_t *); void updateProgress( obex_object_t *); void getHeaders( obex_object_t *object ); State state; QString filename; QString mimetype; int reclen; QFile outfile;};/* QObexSender functions */void QObexSender::feedStream( obex_object_t *object ){ static char buf[4096]; ASSERT( state == Streaming && file_being_sent ); obex_headerdata_t hd; int len = file_being_sent->readBlock( buf, 4096 ); if ( len > 0 ) { hd.bs = (uchar*)buf; OBEX_ObjectAddHeader(self, object, OBEX_HDR_BODY, hd, len, OBEX_FL_STREAM_DATA); } else { /* EOF */ hd.bs = 0; OBEX_ObjectAddHeader(self, object, OBEX_HDR_BODY, hd, 0, OBEX_FL_STREAM_DATAEND); file_being_sent->close(); delete file_being_sent; file_being_sent = 0; } }void QObexSender::updateProgress( obex_object_t * /* obj */){ emit progress( file_being_sent->at() );}static bool hasTasks( const QString &filename ){ QValueList<Task> tasks = Task::readVCalendar( filename ); return tasks.count();}void QObexSender::putFile( const QString &filename, const QString& mimetype ){ obex_headerdata_t hd; obex_object_t *object = OBEX_ObjectNew(self, OBEX_CMD_PUT); if (object == NULL) { /* Error */ qWarning( "null object" ); state = Error; finished = TRUE; return; } file_being_sent = new QFile( filename ); if ( file_being_sent->open(IO_ReadOnly) ) { int body_size = file_being_sent->size(); /* Add length header */ hd.bq4 = body_size; OBEX_ObjectAddHeader(self, object, OBEX_HDR_LENGTH, hd, 4, 0); /* Add type header */ hd.bs = (uchar*)mimetype.latin1(); OBEX_ObjectAddHeader(self, object, OBEX_HDR_TYPE, hd, mimetype.length()+1, 0); /* Add PalmOS-style application id header */ // ####### if more PalmOS applications have this problem, // ####### a more general solution is required. if ( mimetype == "text/x-vCalendar" ) { if ( hasTasks( filename ) ) hd.bq4 = 0x746F646F; // "todo" else hd.bq4 = 0x64617465; // "date" OBEX_ObjectAddHeader(self, object, 0xcf, hd, 4, 0); } /* Add unicode name header*/ QString uc = filename + QChar( 0x0 ); uc = uc.mid( uc.findRev("/")+1 ); int name_size = uc.length() * 2; hd.bs = (uchar*) uc.unicode(); OBEX_ObjectAddHeader(self, object, OBEX_HDR_NAME, hd, name_size, 0); state = Streaming; hd.bs = 0; OBEX_ObjectAddHeader(self, object, OBEX_HDR_BODY, hd, 0, OBEX_FL_STREAM_START); process( object ); }}static bool transmitDone = FALSE;void QObexSender::doPending(){ //qDebug( "QObexSender::doPending %d", state ); if ( state == Connecting ) { //qDebug( "state Connecting" ); // finished connecting; time to send putFile( file_to_send, mime_to_send ); file_to_send = QString::null; } else if ( state == Streaming ) { //qDebug( "state Streaming" ); //finished streaming obex_object_t *object = OBEX_ObjectNew(self, OBEX_CMD_DISCONNECT); process( object ); state = Disconnecting; } else if ( state == Disconnecting ) { //qDebug( "state Disconnecting" ); OBEX_TransportDisconnect(self); state = Init; emit done(); deleteMeLater(); }}static void qobex_sender_callback(obex_t *handle, obex_object_t *obj, gint /* mode */ , gint event, gint obex_cmd, gint /* obex_rsp */){ QObexSender *sender = (QObexSender*)OBEX_GetUserData( handle );// qDebug( "qobex_sender_callback %p, %p, %p, %d, event %x, cmd %x, rsp %x",// sender, handle, obj, mode, event, obex_cmd, obex_rsp ); switch (event) { case OBEX_EV_REQDONE: sender->finished = TRUE; if ( obex_cmd == OBEX_CMD_DISCONNECT ) { transmitDone = TRUE; } // else if OBEX_CMD_CONNECT, we could give feedback break; case OBEX_EV_LINKERR: // sometime we get a link error after we believed the connection was done. Ignore this // as emitting an error after done does not make sense if ( !transmitDone ) { emit sender->error(); sender->abort(); sender->state = QObexSender::Error; } else { sender->abort(); qDebug("QIrServer:: got link error after done signal, no external signals sent"); } break; case OBEX_EV_PROGRESS: // report progress? sender->updateProgress( obj ); break; case OBEX_EV_STREAMEMPTY: // when streaming: add more sender->feedStream( obj ); break; default: qDebug("qobex_sender_callback:: did not recongnize event signal %d", event); break; }}QObexSender::QObexSender( QObject *parent, const char *name ) :QObexBase( parent, name ){ self = OBEX_Init( OBEX_TRANS_IRDA, qobex_sender_callback, 0 ); finished = FALSE; state = QObexSender::Init; OBEX_SetUserData( self, this );}QObexSender::~QObexSender(){}void QObexSender::beam( const QString& filename, const QString& mimetype ){ file_to_send = filename;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -