Main Page | Class Hierarchy | Data Structures | File List | Data Fields | Globals

serversession.cpp

Go to the documentation of this file.
00001 /*
00002  * serversession.cpp,v 1.39 2003/11/25 19:29:56 mattid Exp
00003  *
00004  * COBAIN - Communications API for EPOC Environments
00005  * Copyright (C) 2002-2003 Matti Dahlbom, Matti Kokkola
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this library; if not, write to the Free Software
00019  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020  *
00021  * Contact: Matti Dahlbom <matti@777-team.org>
00022  *          Matti Kokkola <matti.kokkola@iki.fi>
00023  */
00024 
00025 #include "serversession.h"
00026 #include "concreteconnection.h"
00027 #include "Log.h"
00028 //#include "receivesession.h"
00029 
00030 CServerSession::CServerSession(RThread& aClient, 
00031                                CCobainServer* aServer) 
00032     : CSession(aClient),
00033       iServer(aServer)
00034 {
00035     Log::Print(_L("** created a session"));
00036 
00037     // clear connections table
00038     Mem::FillZ(iConnections, sizeof(iConnections));
00039 }
00040 
00041 CServerSession::~CServerSession()
00042 {
00043     // if this has already
00044 
00045     Log::Print(_L("** Session dying"));
00046 
00047     // kill bluetooth
00048     iBTCommunicator->StopListeningL();
00049     delete iBTCommunicator;
00050     iBTCommunicator = NULL;
00051 
00052     // close & deallocate all sockets in the socket table
00053     for( TInt i = 0; i < KMaxSocketCount; i++ ) {
00054         if( iConnections[i] != NULL ) {
00055             Log::Print(_L("~CServerSession: killing con %d"), i);
00056 
00057             iConnections[i]->Close(ETrue);
00058 
00059             delete iConnections[i];
00060             iConnections[i] = NULL;
00061         }
00062     }
00063 
00064     // inform server about our death
00065     iServer->DecrementSession();
00066 
00067     // deallocate existing peer list
00068     if( iPeerList != NULL ) {
00069         iPeerList->ResetAndDestroy();
00070         delete iPeerList;
00071         iPeerList = NULL;
00072     }
00073 }
00074 
00075 CServerSession* CServerSession::NewL(RThread& aClient, 
00076                                      CCobainServer* aServer) 
00077 {
00078     CServerSession *session = new (ELeave)CServerSession(aClient, aServer);
00079     CleanupStack::PushL(session);
00080     session->ConstructL();
00081     CleanupStack::Pop(); // session
00082 
00083     return session;
00084 }
00085 
00086 void CServerSession::ConstructL()
00087 {
00088     // increment client count
00089     iServer->IncrementSession();
00090 
00091     // create bluetooth communicator
00092     iBTCommunicator = CBTCommunicator::NewL(this);
00093 }
00094 
00095 CConcreteConnection* CServerSession::GetConnection(TInt id) 
00096 {
00097     if( (id < 0) || (id >= KMaxSocketCount) ) {
00098         User::Panic(KSessionPanic, KErrSessionBadSocketTableIndex);
00099     }
00100 
00101     CConcreteConnection *con = iConnections[id];
00102     if( con == NULL ) {
00103         User::Panic(KSessionPanic, KErrSessionConnectionNotFoundInGet);
00104     }
00105 
00106     return con;
00107 }
00108 
00109 // allocates room in connections table for the connection
00110 TInt CServerSession::AllocateConnection(CConcreteConnection *aConnection) 
00111 {
00112     TInt slot = -1;
00113 
00114     __ASSERT_ALWAYS(!aConnection->IsListening(), 
00115                     User::Panic(KSessionPanic, KErrSessionTryingToAllocListeningCon));
00116 
00117     for( TInt i = 0; i < KMaxSocketCount; i++ ) {
00118         if( iConnections[i] == NULL ) {
00119             slot = i;
00120             break;
00121         }
00122     }
00123 
00124     if( slot == -1 ) {
00125         // no room in table - panic!
00126         CCobainServer::PanicServer(CCobainServer::ESocketTableFull);
00127     }
00128 
00129     Log::Print(_L("AllocateConnection(): id: %d"), slot);
00130 
00131     iConnections[slot] = aConnection;
00132 
00133     return slot;
00134 }
00135 
00136 // removes the given connection from the connections table
00137 void CServerSession::DeallocateConnection(CConcreteConnection *aConnection)
00138 {
00139     __ASSERT_ALWAYS(!aConnection->IsListening(), 
00140                     User::Panic(KSessionPanic, KErrSessionTryingToDeallocListeningCon));
00141 
00142     Log::Print(_L("DeallocateConnection()"));
00143 
00144     for( TInt i = 0; i < KMaxSocketCount; i++ ) {
00145         if( aConnection == iConnections[i] ) {
00146             iConnections[i] = NULL;
00147             return;
00148         }
00149     }
00150 
00151     Log::Print(_L("DeallocateConnection() exiting.."));
00152 }
00153 
00154 // GetNumPeersL() has to be called first.
00155 // Int0 - ordinal (n) of the requested peer
00156 // Ptr1 - pointer to client-side buffer
00157 void CServerSession::GetPeer(const RMessage &aMessage)
00158 {
00159     TInt n = aMessage.Int0();
00160 
00161     Log::Print(_L("CServerSession::GetPeer(): n: %d"), n);
00162 
00163     if( (n < 0) || (n >= iPeerList->Count()) ) {
00164         // bad ordinal supplied
00165         aMessage.Complete(KErrArgument);
00166     }
00167 
00168     // write info about requested (n:th) peer
00169     TPeerData *data = (*iPeerList)[n];
00170     TPeerDataBuf buf = *data;
00171     aMessage.WriteL(aMessage.Ptr1(), buf);
00172 
00173     aMessage.Complete(KErrNone);
00174     return;
00175 }
00176 
00177 // Int0() - requested protocol
00178 // Ptr1() - buffer for number of peers (TInt)
00179 // Int2() - requested service identifyer (aServiceClassID for BT)
00180 void CServerSession::GetNumPeersL(const RMessage &aMessage)
00181 {
00182     // deallocate existing peer list
00183     if( iPeerList != NULL ) {
00184         iPeerList->ResetAndDestroy();
00185         delete iPeerList;
00186         iPeerList = NULL;
00187     }
00188 
00189     switch( aMessage.Int0() ) {
00190         case EBluetooth:
00191             // initiate device discovery. 
00192             // NOTE: the call will be completed by an active object
00193             iBTCommunicator->DiscoverPeersL(aMessage, 
00194                                             *this);
00195             break;
00196         default:
00197             PanicClient(aMessage, CCobainServer::EBadRequest);
00198             break;
00199     }
00200 }
00201 
00202 // Int0() - requested protocol
00203 // Ptr1() - pointer to clientside TPeerDataBuf
00204 // Ptr2() - pointer to clientside TPckgBuf<TInt> to store the id
00205 void CServerSession::ConnectL(const RMessage &aMessage)
00206 {
00207     TPeerDataBuf buf;
00208     TInt err = KErrNone;
00209 
00210     // copy peer data
00211     aMessage.ReadL(aMessage.Ptr1(), buf);
00212     TPeerData &data = buf();
00213 
00214     // connect to the peer
00215     RSocket *socket = NULL;
00216 
00217     switch ( aMessage.Int0() ) {
00218         case EBluetooth:
00219             TRAP(err, (socket = iBTCommunicator->ConnectL(&data)));
00220             break;
00221         default:
00222             PanicClient(aMessage, CCobainServer::EUnsupportedProtocol);
00223             break;
00224     }
00225 
00226     if( err != KErrNone ) {
00227         Log::Print(_L("ConnectL() error: %d"), err);
00228 
00229         // error connecting - complete call with error (negative value)
00230         aMessage.Complete(err);
00231         return;
00232     }
00233 
00234     // allocate new connection
00235     TInt slot = AllocateConnection(CConcreteConnection::NewL(socket, *this));
00236 
00237     // write the id 
00238     TPckgBuf<TInt> id_buf(slot);
00239     aMessage.WriteL(aMessage.Ptr2(), id_buf);
00240 
00241     aMessage.Complete(KErrNone);
00242 }
00243 
00244 // Int0() - socket id
00245 // Int1() - whether to close socket abruptively (ETrue = yes, EFalse = no)
00246 void CServerSession::CloseSocket(const RMessage &aMessage)
00247 {
00248     TInt n = aMessage.Int0();
00249 
00250     Log::Print(_L("CServerSession::CloseSocket() %d"), n);
00251 
00252     CConcreteConnection *con = GetConnection(n);
00253     DeallocateConnection(con);
00254 
00255     TBool immediately = (TBool)aMessage.Int1();
00256 
00257     Log::Print(_L("calling con->Close()"));
00258 
00259     con->Close(immediately);
00260     delete con;
00261 
00262     aMessage.Complete(KErrNone);
00263 
00264     Log::Print(_L("CloseSocket() exiting"));
00265 }
00266 
00267 // asynchronous call to retrieve the next incoming connection info.
00268 // calls asynchronous listen handler which will handle the completion of the 
00269 // message when a new connection is available
00270 void CServerSession::GetIncomingConnection(const RMessage& aMessage)
00271 {
00272     if( iListeningConnection == NULL ) {
00273         PanicClient(aMessage, CCobainServer::ENotListening);
00274     }
00275 
00276     // launches asynchronous listen handler and returns
00277     iListeningConnection->ListenL(aMessage);    
00278 }
00279 
00280 // this is a synchronous call to start listening to a given port
00281 //
00282 // Int0() - protocol
00283 // Int1() - port 
00284 // ##TODO## service name+desc
00285 void CServerSession::StartListen(const RMessage& aMessage)
00286 {
00287     if( iListeningConnection != NULL ) {
00288         PanicClient(aMessage, CCobainServer::EAlreadyListening);
00289     }
00290 
00291     TUint port = (TUint)aMessage.Int1();
00292 
00293     //##TODO## read these from client
00294     _LIT8(KServiceName, "servicename");
00295     _LIT8(KServiceDesc, "service desc");
00296 
00297     switch( aMessage.Int0() ) {
00298         case EBluetooth:
00299             iListeningConnection = iBTCommunicator->StartListeningL(port,
00300                                                                     -1,
00301                                                                     KServiceName,
00302                                                                     KServiceDesc);
00303             break;
00304         default:
00305             PanicClient(aMessage, CCobainServer::EUnsupportedProtocol);
00306             break;
00307     }
00308 
00309     // complete the message, allowing client call to return
00310     aMessage.Complete(KErrNone);
00311 }
00312 
00313 // Int0() - protocol
00314 void CServerSession::AbortListen(const RMessage& aMessage)
00315 {
00316     Log::Print(_L("AbortListen()"));
00317 
00318     switch( aMessage.Int0() ) {
00319         case EBluetooth:
00320             iBTCommunicator->StopListeningL();
00321             break;
00322         default:
00323             PanicClient(aMessage, CCobainServer::EUnsupportedProtocol);
00324             break;
00325     }
00326 
00327     iListeningConnection = NULL;
00328 
00329     aMessage.Complete(KErrNone);
00330 }
00331 
00332 // Int0() - socket ID
00333 // Ptr1() - buffer for received packet of size minimum KRecvBufSize
00334 void CServerSession::Receive(const RMessage& aMessage)
00335 {
00336     Log::Print(_L("CServerSession::Receive()"));
00337 
00338     TInt n = aMessage.Int0();
00339     CConcreteConnection *con = GetConnection(n);
00340     con->ReceiveL(aMessage);
00341 
00342     Log::Print(_L("CServerSession::Receive() returning"));
00343 }
00344 
00345 // Int0 - socket id
00346 void CServerSession::CancelReceive(const RMessage &aMessage) 
00347 {
00348     Log::Print(_L("CancelReceive()"));
00349 
00350     TInt id = aMessage.Int0();
00351     CConcreteConnection *con = GetConnection(id);
00352     con->CancelReceive();
00353     aMessage.Complete(KErrNone);
00354 }
00355 
00356 // Int0() - socket id
00357 // Int1() - data length
00358 // Ptr2() - send buffer
00359 void CServerSession::Send(const RMessage &aMessage)
00360 {
00361     TInt id = aMessage.Int0();
00362     TInt len = aMessage.Int1();
00363 
00364     Log::Print(_L("Send(): id: %d, len: %d"), id, len);
00365 
00366     // allocate buffer for the data. buffer will be released by CAsynchSend
00367     // after it has been sent
00368     HBufC8 *buf = HBufC8::NewL(len);
00369     CleanupStack::PushL(buf);
00370 
00371     // read data from client thread
00372     TPtr8 ptr = buf->Des();
00373     aMessage.ReadL(aMessage.Ptr2(), ptr);
00374 
00375     // get the connection matching the socket id
00376     CConcreteConnection *con = GetConnection(id);
00377 
00378     // send the data
00379     TRAPD(err, con->SendL(buf));
00380 
00381     CleanupStack::Pop(); // buf
00382 
00383     // allow client call to return
00384     //##TODO## handle error situations
00385     aMessage.Complete(err);
00386 }
00387 
00388 void CServerSession::ServiceL(const RMessage& aMessage)
00389 {
00390     TInt function = aMessage.Function();
00391 
00392 //    Log::Print(_L("ServiceL(): %d"), function);
00393 
00394     switch( function )
00395     {
00396         case CCobainServer::ESend:
00397             Send(aMessage);
00398             break;
00399         case CCobainServer::EConnect:
00400             ConnectL(aMessage);
00401             break;
00402         case CCobainServer::ECloseSocket:
00403             CloseSocket(aMessage);
00404             break;
00405         case CCobainServer::EGetNumPeers:
00406             GetNumPeersL(aMessage);
00407             break;
00408         case CCobainServer::EGetPeer:
00409             GetPeer(aMessage);
00410             break;
00411         case CCobainServer::EStartListen:
00412             StartListen(aMessage);
00413             break;
00414         case CCobainServer::EAbortListen:
00415             AbortListen(aMessage);
00416             break;
00417         case CCobainServer::EGetIncomingConnection:
00418             GetIncomingConnection(aMessage);
00419             break;
00420         case CCobainServer::EReceive:
00421             Receive(aMessage);
00422             break;
00423         case CCobainServer::ECancelReceive:
00424             CancelReceive(aMessage);
00425             break;
00426         default:
00427             PanicClient(aMessage, CCobainServer::EBadRequest);
00428             break;
00429     }
00430 
00431     //Log::Print(_L("ServiceL() returning"));
00432 }
00433 
00434 void CServerSession::PanicClient(const RMessage& aMessage, 
00435                                  CCobainServer::TServerPanic aPanic)
00436 {
00437     aMessage.Panic(KClientPanic, aPanic);
00438 }

Generated on Mon Dec 8 10:26:07 2003 for CobainAPIImplementation by doxygen 1.3.5