📄 qirserver.cpp
字号:
QObexServer::QObexServer( QObject *parent, const char *name ) :QObexBase( parent, name ){ state = Error; self = OBEX_Init( OBEX_TRANS_IRDA, qobex_server_callback, OBEX_FL_KEEPSERVER ); state = Init; OBEX_SetUserData( self, this ); // XXX To support OBEX other than IrDA, register those services here. // XXX (somehow) if(IrOBEX_ServerRegister(self, "OBEX") < 0) { qWarning( "could not register server" ); state = Error; } else { connectSocket(); } m_receiver = 0; m_receiving = FALSE; m_timer = 0;}QObexServer::~QObexServer(){ //cleanup}void QObexServer::doPending(){ //nothing, it's stateless}void QObexServer::spawnReceiver( obex_t *handle ){ ASSERT( handle == self ); // we emit this here, as doing in in QObexReceiver could cause race conditions #ifdef QTOPIA_DEBUG_OBEX qDebug("QObexServer::spawnReceiver()");#endif if( m_timer && m_timer->isActive() ) m_timer->stop(); // spawning a new receiver, don't timeout m_receiver = new QObexReceiver( handle, this ); connect( m_receiver, SIGNAL(fileComplete()), parent(), SIGNAL(fileComplete()) ); connect( m_receiver, SIGNAL(aboutToDelete()), this, SLOT(sessionEnded()) ); connect( m_receiver, SIGNAL(receiving(int,const QString&,const QString&)), parent(), SIGNAL(receiving(int,const QString&,const QString&)) ); connect( m_receiver, SIGNAL(progress(int)), parent(), SIGNAL(progressReceive(int)) ); /* don't enable unless you know what you're doing connect( m_receiver, SIGNAL(received(const QString&,const QString&)), parent(), SIGNAL(received(const QString&,const QString&)) ); */ connect( m_receiver, SIGNAL(receiving(bool)), this, SLOT(slotReceiving(bool)) ); slotReceiving( TRUE ); connect( parent(), SIGNAL(abortReceive()), m_receiver, SLOT(abort()) ); connect( m_receiver, SIGNAL(error()), parent(), SLOT(rError()) ); }void QObexServer::sessionEnded(){#ifdef QTOPIA_DEBUG_OBEX qDebug("Receive Session Ended");#endif if( m_receiver->linkErrFinish() ) { // session finished with a linkerr //work around for Siemens S45 //if another receive session is not started within 5 seconds, //assume there are no more files because there is no definite //way to tell if( !m_timer ) { m_timer = new QTimer( this ); connect( m_timer, SIGNAL(timeout()), this, SLOT(finishedReceive()) ); } m_timer->start( 3000 ); }}void QObexServer::finishedReceive(){#ifdef QTOPIA_DEBUG_OBEX qDebug("finishedReceive");#endif if( m_timer ) m_timer->stop(); m_receiving = FALSE; emit receiving( FALSE );}void QObexServer::slotReceiving( bool r ){#ifdef QTOPIA_DEBUG_OBEX qDebug("QObexServer::slotReceiving( %s )", r ?"TRUE" : "FALSE");#endif if( !r && m_receiving && m_receiver->linkErrFinish() ) {#ifdef QTOPIA_DEBUG_OBEX qDebug("LINK ERROR FINISH");#endif //finished a file successfully due to link error, may not be totally finished r = TRUE; } if( m_receiving != r ) { m_receiving = r; emit receiving( r ); }}static void qobex_server_callback(obex_t *handle, obex_object_t * object, int mode, int event, int obex_cmd, int obex_rsp){#ifdef QTOPIA_DEBUG_OBEX qDebug( "qobex_server_callback %p event %x cmd %x rsp %x", object, event, obex_cmd, obex_rsp );#else Q_UNUSED(object); Q_UNUSED(obex_cmd); Q_UNUSED(obex_rsp);#endif Q_UNUSED(mode); QObexServer* server = (QObexServer*)OBEX_GetUserData( handle ); switch (event) { case OBEX_EV_ACCEPTHINT: {#ifdef QTOPIA_DEBUG_OBEX qDebug( "#####------ OBEX_EV_ACCEPTHINT ------########" );#endif server->spawnReceiver( handle ); } break; default: qWarning( " Unexpected event in server" ); break; }}/* QObexReceiver functions*/QObexReceiver::QObexReceiver( obex_t *handle, QObject *parent, const char *name ) :QObexBase( parent, name ){ state = Error; reclen = 0; m_linkErrFinish = FALSE; state = Receiving; self = OBEX_ServerAccept( handle, qobex_receiver_callback, this ); connectSocket();}QObexReceiver::~QObexReceiver(){}static QString getString( const uchar* bs, int len ){ // qDebug( "getString" ); /* for ( int i = 0; i < len; i++ ) qDebug( "byte %2d : %02x %c", i, bs[i], bs[i] ); */ QString s; s.setUnicode( (const QChar*)bs, len/2-1 ); return s;}#define HDR_DESCRIPTION 0x05void QObexReceiver::getHeaders( obex_object_t *object ){ uchar hi; obex_headerdata_t hv; unsigned int hv_size; while(OBEX_ObjectGetNextHeader(self, object, &hi, &hv, &hv_size)) { switch ( hi ) { case OBEX_HDR_LENGTH:#ifdef QTOPIA_DEBUG_OBEX qDebug( "******** Got length %d", hv.bq4 );#endif reclen = hv.bq4; break; case OBEX_HDR_NAME: filename = getString(hv.bs, hv_size);#ifdef QTOPIA_DEBUG_OBEX qDebug( "******** Got name %s (%d)", getString(hv.bs, hv_size).latin1(), hv_size );#endif break; case HDR_DESCRIPTION:#ifdef QTOPIA_DEBUG_OBEX qDebug( "******** Got description %s (%d)", getString(hv.bs, hv_size).latin1(), hv_size );#endif break; case OBEX_HDR_TYPE: mimetype = QString::fromLatin1( (const char*)hv.bs, hv_size );#ifdef QTOPIA_DEBUG_OBEX qDebug( "******** Got type \"%s\"", mimetype.latin1() );#endif break; default:#ifdef QTOPIA_DEBUG_OBEX if ( hi < 0x40 ) //unicode header qDebug( "******** Got header 0x%x %s (%d)", hi, getString(hv.bs, hv_size).latin1(), hv_size ); else if ( (hi & 0xc0) == 0xc0 ) // quantity [eg. cf = PalmOS Creator ID] qDebug( "******** Got header 0x%x (%d)", hi, hv.bq4 ); else qDebug( "******** Got header 0x%x (size=%d)", hi, hv_size );#endif ; } }}void QObexReceiver::readData( obex_object_t *object ){ const uchar* buf; int len = OBEX_ObjectReadStream( self, object, &buf ); if ( filename.isEmpty() ) { getHeaders( object ); int slash = filename.find( '/', -1 ); if ( slash > 0 ) { filename = filename.mid( slash+1 ); } if ( mimetype.isNull() ) { QString ext = filename.mid( filename.findRev( '.', -1 )+1 ).lower(); if( ext == "vcs" ) { mimetype = "text/x-vCalendar"; } else if( ext == "vcf" ) { mimetype = "text/x-vCard"; } else { MimeType mt(filename); mimetype = mt.id(); } } if ( filename.isEmpty() ) filename = "unnamed"; // No tr for( int i = 0 ; i < (int)filename.length() ; ++i) if( filename[i] != '.' && (filename[i].isPunct() || filename[i].isSpace()) ) filename[i] = '_'; //ensure it's something valid#ifdef QTOPIA_DEBUG_OBEX qDebug("emit receiving( %d, %s, %s )", reclen, filename.latin1(), mimetype.latin1());#endif emit receiving( reclen, filename, mimetype ); filename = "/tmp/obex/in/" + filename; outfile.setName( filename ); if( !outfile.open( IO_WriteOnly ) ) qWarning("Unable to open file %s for IR receive", filename.latin1()); } if ( len > 0 ) { if( outfile.isOpen() ) // if unable to open outfile don't write to it outfile.writeBlock( (const char*)buf, len ); } else if ( len == 0 ) { outfile.close(); filename = QString::null; emit fileComplete(); } else { qWarning( "ERROR reading stream" ); emit error(); filename = QString::null; outfile.close(); } finished = ( len <= 0 );}void QIrServer::clean(){#ifdef QTOPIA_DEBUG_OBEX qDebug("QIrServer::clean");#endif //just blow it all away and recreate the dir system("rm -rf /tmp/obex/in/*"); mkdir( "/tmp/obex", 0755 ); mkdir( "/tmp/obex/in", 0755 );}void QObexReceiver::updateProgress( obex_object_t * /* obj */){ emit progress( outfile.size() );}static void qobex_receiver_callback(obex_t *handle, obex_object_t *object, int mode, int event, int obex_cmd, int obex_rsp ){#ifdef QTOPIA_DEBUG_OBEX qDebug( "qobex_receiver_callback %p event %x cmd %x rsp %x", object, event, obex_cmd, obex_rsp );#else Q_UNUSED(obex_rsp);#endif Q_UNUSED(mode); QObexReceiver* receiver = (QObexReceiver*)OBEX_GetUserData( handle ); switch (event) { case OBEX_EV_STREAMAVAIL:#ifdef QTOPIA_DEBUG_OBEX qDebug("OBEX_EV_STREAMAVAIL");#endif receiver->readData( object ); break; case OBEX_EV_PROGRESS:#ifdef QTOPIA_DEBUG_OBEX qDebug("OBEX_EV_PROGRESS");#endif receiver->updateProgress( object ); // report progress break; case OBEX_EV_REQ:#ifdef QTOPIA_DEBUG_OBEX qDebug("OBEX_EV_REQ");#endif /* An incoming request */ switch(obex_cmd) { case OBEX_CMD_CONNECT: case OBEX_CMD_DISCONNECT:#ifdef QTOPIA_DEBUG_OBEX qDebug("\tOBEX_CMD_CONNECT|OBEX_CMD_DISCONNECT");#endif /* Dont need to do anything here. Response is already set to success by OBEX_EV_REQHINT event */ break; case OBEX_CMD_PUT:#ifdef QTOPIA_DEBUG_OBEX qDebug("\tOBEX_CMD_PUT");#endif //We do it all in STREAMAVAIL //receiver->handlePut(object); break; } break; case OBEX_EV_ACCEPTHINT:#ifdef QTOPIA_DEBUG_OBEX qDebug("OBEX_EV_ACCEPTHINT");#endif //qFatal( " OBEX_EV_ACCEPTHINT in receiver" ); OBEX_ObjectSetRsp(object, OBEX_RSP_NOT_IMPLEMENTED, OBEX_RSP_NOT_IMPLEMENTED); break; case OBEX_EV_REQHINT:#ifdef QTOPIA_DEBUG_OBEX qDebug("OBEX_EV_REQHINT");#endif /* A new request is coming in */ switch(obex_cmd) { /* Accept some commands! */ case OBEX_CMD_PUT:#ifdef QTOPIA_DEBUG_OBJEX qDebug("\tOBEX_CMD_PUT");#endif OBEX_ObjectSetRsp(object, OBEX_RSP_CONTINUE, OBEX_RSP_SUCCESS); //turn on streaming... OBEX_ObjectReadStream(handle, object, NULL); break; case OBEX_CMD_CONNECT: case OBEX_CMD_DISCONNECT:#ifdef QTOPIA_DEBUG_OBJEX qDebug("\tOBEX_CMD_CONNECT|OBEX_CMD_DISCONNECT");#endif OBEX_ObjectSetRsp(object, OBEX_RSP_CONTINUE, OBEX_RSP_SUCCESS); break; default:#ifdef QTOPIA_DEBUG_OBJEX qDebug("OBEX_CMD_UNKNOWN");#endif /* Reject any other commands */ OBEX_ObjectSetRsp(object, OBEX_RSP_NOT_IMPLEMENTED, OBEX_RSP_NOT_IMPLEMENTED); break; } break; case OBEX_EV_REQDONE:#ifdef QTOPIA_DEBUG_OBEX qDebug("OBEX_EV_REQDONE");#endif if(obex_cmd == OBEX_CMD_DISCONNECT) { receiver->state = QObexReceiver::Finished; receiver->finished = TRUE; // Disconnect transport: OBEX_TransportDisconnect( handle ); } break; case OBEX_EV_LINKERR:#ifdef QTOPIA_DEBUG_OBEX qDebug("OBEX_EV_LINKERR");#endif if ( !receiver->reclen || receiver->reclen == (int)receiver->outfile.size() ) { // just treat is as finished. Some mobile phones behave this way. if( receiver->reclen ) { receiver->m_linkErrFinish = TRUE; } receiver->state = QObexReceiver::Finished; } else { receiver->state = QObexReceiver::Error; } receiver->finished = TRUE; // Disconnect transport: OBEX_TransportDisconnect( handle ); break; default: break; }}void QObexReceiver::doPending(){ if ( state == Finished || state == Error ) { if ( !aborted ) { deleteMeLater(); if ( state == Error ) { emit error(); } }#ifdef QTOPIA_DEBUG_OBEX qDebug("emitting receiving( FALSE ) from doPending");#endif emit receiving(FALSE); }}#include "qirserver.moc"QIrServer::QIrServer( QObject *parent, const char *name ) :QObject( parent, name ){ QObexServer* server = new QObexServer( this ); connect(server, SIGNAL(receiving(bool)), this, SLOT(receiving(bool)) ); bip = rip = FALSE; clean(); needClean = FALSE;}QIrServer::~QIrServer(){}void QIrServer::beam( const QString& filename, const QString& mimetype ){ if ( bip ) { qDebug("QIrServer not ready, beaming disallowed"); emit beamError(); return; }#ifdef QTOPIA_DEBUG_OBEX qDebug("beaming %s (type %s)", filename.data(), mimetype.latin1() );#endif bip = TRUE; QObexSender *sender = new QObexSender( this ); connect( this, SIGNAL(abortBeam()), sender, SLOT(abort()) ); connect( sender, SIGNAL(done()), this, SLOT(bDone()) ); connect( sender, SIGNAL(error()), this, SLOT(bError()) ); connect( sender, SIGNAL(statusMsg(const QString&)), this, SIGNAL(statusMsg(const QString&)) ); connect( sender, SIGNAL(progress(int)), this, SIGNAL( progressSend(int) ) ); sender->beam( filename, mimetype ); //fire-and forget, auto-cleanup}void QIrServer::receiving(bool b){ if ( rip != b ) { rip = b; if ( rip ) { emit receiveInit(); } else { emit receiveDone(); }#ifdef QTOPIA_DEBUG_OBEX qDebug("QIrServer::receiving(%s)", b ? "TRUE" : "FALSE");#endif if( b && needClean ) { clean(); needClean = FALSE; } if( !b ) // after change to not receiving, need to clean next time receiving needClean = TRUE; }}void QIrServer::rError(){ rip = FALSE; emit receiveError();}void QIrServer::bDone(){ bip = FALSE; emit beamDone();}void QIrServer::bError(){ bip = FALSE; emit beamError();}void QIrServer::cancelBeam(){ // internal signal emit abortBeam(); //external (this goes to qir) bError();}void QIrServer::cancelReceive(){ // internal signal emit abortReceive(); //external (this goes to qir) rError();}void QIrServer::setReceivingEnabled( bool ){ //XXX}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -