00001 #include <errno.h>
00002 #include <signal.h>
00003 #include <stdio.h>
00004 #include <stdlib.h>
00005 #include <unistd.h>
00006 #include <sys/socket.h>
00007 #include <sys/un.h>
00008
00009 #include <qcstring.h>
00010 #include <qtimer.h>
00011
00012 #include "ocopserver.h"
00013
00014 OCopServer::OCopServer()
00015 : QObject()
00016 {
00017 setName( "ocopserver");
00018
00019
00020
00021
00022 init();
00023 initSocket();
00024 }
00025 OCopServer::~OCopServer() {
00026
00027 close(m_serverfd );
00028 }
00029 void OCopServer::init() {
00030
00031
00032
00033
00034
00035 signal(SIGPIPE, SIG_IGN );
00036
00037
00038
00039
00040 m_server = 0l;
00041 m_serverError = 0l;
00042 }
00043
00048 void OCopServer::initSocket() {
00049
00050 QCString home( getenv("HOME") );
00051 QCString path( home + "/.opie.cop");
00052
00053 if ( ( m_serverfd = socket( PF_UNIX, SOCK_STREAM, 0 ) ) == -1 ) {
00054 qWarning("failed to create server socket");
00055
00056 QTimer::singleShot( 400, this, SLOT(initSocket() ) );
00057 return;
00058 }
00059 qWarning( "unlinking file %s", path.data() );
00060
00061
00062 unlink( path.data() );
00063
00064 struct sockaddr_un m_address;
00065 memset(&m_address, 0, sizeof(m_address ) );
00066 m_address.sun_family = AF_UNIX;
00067 strcpy(m_address.sun_path, path.data() );
00068 m_adrlaenge = sizeof(m_address.sun_family) + strlen(m_address.sun_path );
00069
00070
00071 if (bind(m_serverfd, (struct sockaddr*)&m_address, m_adrlaenge ) == -1 ) {
00072 qWarning("Server could not bind try again");
00073 close(m_serverfd);
00074 QTimer::singleShot(400, this, SLOT(initSocket() ) );
00075 return;
00076 }
00077
00078
00079
00080 if (listen(m_serverfd, 5) == -1 ) {
00081 qWarning("could not listen");
00082 close(m_serverfd );
00083 QTimer::singleShot(400, this, SLOT(initSocket() ) );
00084 return;
00085 }
00086
00087
00088
00089
00090
00091
00092
00093
00094 m_server = new QSocketNotifier(m_serverfd, QSocketNotifier::Read, this );
00095 connect( m_server, SIGNAL(activated(int) ),
00096 this, SLOT(newOnServer() ) );
00097
00098 m_serverError = new QSocketNotifier( m_serverfd, QSocketNotifier::Exception, this);
00099 connect(m_serverError, SIGNAL(activated(int) ),
00100 this, SLOT(errorOnServer() ) );
00101
00102 qWarning("done with registering");
00103 }
00112 void OCopServer::newOnServer() {
00113 int fd = accept();
00114 if ( fd < 0 )
00115 return;
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127 registerClient( fd );
00128 }
00129 int OCopServer::accept() {
00130
00131
00132
00133
00134 return ::accept( m_serverfd, (struct sockaddr*)&m_address, &m_adrlaenge );
00135 }
00136 void OCopServer::newOnClient( int fd ) {
00137 errno = 0;
00138 OCOPHead head;
00139 memset(&head, 0, sizeof(head) );
00140 int rea = ::read(fd, &head, sizeof(head) );
00141
00142
00143
00144
00145
00146
00147 if ( rea <= 0 ) {
00148 deregisterClient( fd );
00149 return;
00150 }
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166 if (head.magic == 47 ) {
00167
00168 QCString channel( head.chlen+1 );
00169 QCString func( head.funclen+1 );
00170 QByteArray data ( head.datalen+1 );
00171
00172
00173
00174
00175
00176 int s = read(fd, channel.data(), head.chlen );
00177 s = read(fd, func.data(), head.funclen );
00178 s = read(fd, data.data(), head.datalen );
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193 OCOPPacket packet( head.type, channel, func, data );
00194 dispatch( packet, fd );
00195
00196 }else{
00197
00198
00199 }
00200 }
00201 void OCopServer::registerClient( int fd ) {
00202 if (m_clients.contains(fd) )
00203 return;
00204
00205 QSocketNotifier* notify = new QSocketNotifier(fd, QSocketNotifier::Read, this );
00206 connect(notify, SIGNAL(activated(int) ),
00207 this, SLOT(newOnClient(int) ) );
00208 OCOPClient client;
00209 client.fd = fd;
00210 client.notify = notify;
00211 m_clients.insert( client.fd, client );
00212
00213 };
00214 void OCopServer::deregisterClient(int fd ) {
00215 QMap<int, OCOPClient>::Iterator it = m_clients.find( fd );
00216 if (it != m_clients.end() ) {
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226 QMap<QCString, QValueList<int> >::Iterator it2;
00227 repeatIt:
00228 for ( it2 = m_channels.begin(); it2 != m_channels.end(); ++it2 ) {
00229
00230
00231
00232
00233 if ( it2.data().contains( fd ) ) {
00234 qWarning("contains");
00235 QValueList<int> array = it2.data();
00236
00237
00238
00239
00240 if ( array.count() == 1 || array.count() == 0) {
00241
00242
00243 m_channels.remove( it2 );
00244
00245
00246
00247
00248
00249
00250
00251 goto repeatIt;
00252 }else{
00253
00254 QValueList<int>::Iterator it3 = array.find( fd );
00255 it3 = array.remove( it3 );
00256 QCString key = it2.key().copy();
00257 it2 = m_channels.replace( key, array );
00258 }
00259 }
00260 }
00261 OCOPClient client = it.data();
00262 delete client.notify;
00263 m_clients.remove(fd );
00264 close(fd );
00265 }
00266
00267 }
00272 void OCopServer::dispatch( const OCOPPacket& packet, int sourceFD ) {
00273
00274 switch( packet.type() ) {
00275 case OCOPPacket::Register:
00276 registerClient(sourceFD );
00277 break;
00278 case OCOPPacket::Unregister:
00279 deregisterClient(sourceFD );
00280 break;
00281 case OCOPPacket::Call:
00282 call( packet, sourceFD );
00283 break;
00284
00285 case OCOPPacket::Method:
00286 break;
00287
00288 case OCOPPacket::Reply:
00289 break;
00290 case OCOPPacket::RegisterChannel:
00291 addChannel( packet.channel() , sourceFD );
00292 break;
00293 case OCOPPacket::UnregisterChannel:
00294 delChannel( packet.channel(), sourceFD );
00295 break;
00296
00297 case OCOPPacket::Return:
00298 break;
00299
00300 case OCOPPacket::Signal:
00301 break;
00302 case OCOPPacket::IsRegistered:
00303
00304 isRegistered( packet.channel(), sourceFD );
00305 break;
00306 };
00307 }
00308 void OCopServer::errorOnServer() {
00309
00310
00311
00312
00313
00314 }
00315 QStringList OCopServer::channels() {
00316 QStringList list;
00317 {
00318 QMap<QCString, QValueList<int> >::Iterator it;
00319 for (it = m_channels.begin(); it != m_channels.end(); ++it ) {
00320 list << it.key();
00321 };
00322 }
00323 return list;
00324 }
00325 bool OCopServer::isChannelRegistered( const QCString& chan ) const{
00326 return m_channels.contains( chan );
00327 }
00328 void OCopServer::addChannel( const QCString& channel,
00329 int fd ) {
00330 QMap<QCString, QValueList<int> >::Iterator it;
00331 it = m_channels.find( channel );
00332 if ( it != m_channels.end() ) {
00333
00334 QValueList<int> list = it.data();
00335 list.append( fd );
00336 qWarning("Server:count is now in addChannel %d %s", list.count(), channel.data() );
00337 it = m_channels.replace( channel, list );
00338 }else {
00339 QValueList<int> ints;
00340 ints.append( fd );
00341 m_channels.insert( channel, ints );
00342 }
00343 };
00344 void OCopServer::delChannel( const QCString& channel,
00345 int fd ) {
00346
00347 if (!m_channels.contains( channel ) )
00348 return;
00349
00350 QMap<QCString, QValueList<int> >::Iterator it;
00351 it = m_channels.find( channel );
00352
00353 if ( it.data().contains(fd) ) {
00354 QValueList<int> ints = it.data();
00355 if ( ints.count() == 1 )
00356 m_channels.remove( channel );
00357 else{
00358 QValueList<int> ints = it.data();
00359 QValueList<int>::Iterator rem = ints.find( fd );
00360 rem = ints.remove( rem );
00361 QCString str = it.key().copy();
00362 m_channels.replace( str, ints );
00363 }
00364
00365 }
00366 }
00367 void OCopServer::isRegistered( const QCString& channel, int fd) {
00368
00369 OCOPHead head;
00370 QCString func(2);
00371
00372 memset(&head, 0, sizeof(head ) );
00373 head.magic = 47;
00374 head.type = OCOPPacket::IsRegistered;
00375 head.chlen = channel.size();
00376 head.funclen = func.size();
00377 head.datalen = 0;
00378
00379 if ( isChannelRegistered( channel ) ) {
00380
00381 func[0] = 1;
00382
00383 }else{
00384 func[0] = 0;
00385
00386 }
00387
00393 write(fd, &head, sizeof(head) );
00394 write(fd, channel.data(), channel.size() );
00395 write(fd, func.data(), func.size() );
00396 }
00397 QValueList<int> OCopServer::clients( const QCString& channel ) {
00398 return m_channels[channel];
00399 }
00400 void OCopServer::call( const OCOPPacket& p, int ) {
00401 QValueList<int> cli = clients( p.channel() );
00402 QValueList<int>::Iterator it;
00403
00404 OCOPHead head = p.head();
00405 for (it = cli.begin(); it != cli.end(); ++it ) {
00406
00407 write( (*it), &head, sizeof(head ) );
00408
00409 write( (*it), p.channel().data(), p.channel().size() );
00410 write( (*it), p.header().data(), p.header().size() );
00411 write( (*it), p.content().data(), p.content().size() );
00412 };
00413 }