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.43 2004/01/10 14:27:11 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 "bt_sock.h"
00029 //#include "receivesession.h"
00030 
00031 CServerSession::CServerSession(RThread& aClient, 
00032                                CCobainServer* aServer) 
00033     : CSession(aClient),
00034       iServer(aServer)
00035 {
00036     Log::Print(_L("** created a session"));
00037 
00038     // clear connections table
00039     Mem::FillZ(iConnections, sizeof(iConnections));
00040 }
00041 
00042 CServerSession::~CServerSession()
00043 {
00044     // if this has already
00045 
00046     Log::Print(_L("** Session dying"));
00047 
00048     // kill bluetooth
00049     iBTCommunicator->StopListeningL();
00050     delete iBTCommunicator;
00051     iBTCommunicator = NULL;
00052 
00053     // close & deallocate all sockets in the socket table
00054     for( TInt i = 0; i < KMaxSocketCount; i++ ) {
00055         if( iConnections[i] != NULL ) {
00056             Log::Print(_L("~CServerSession: killing con %d"), i);
00057 
00058             iConnections[i]->Close(ETrue);
00059 
00060             delete iConnections[i];
00061             iConnections[i] = NULL;
00062         }
00063     }
00064 
00065     // inform server about our death
00066     iServer->DecrementSession();
00067 
00068     // deallocate existing peer list
00069     if( iPeerList != NULL ) {
00070         iPeerList->ResetAndDestroy();
00071         delete iPeerList;
00072         iPeerList = NULL;
00073     }
00074 }
00075 
00076 CServerSession* CServerSession::NewL(RThread& aClient, 
00077                                      CCobainServer* aServer) 
00078 {
00079     CServerSession *session = new (ELeave)CServerSession(aClient, aServer);
00080     CleanupStack::PushL(session);
00081     session->ConstructL();
00082     CleanupStack::Pop(); // session
00083 
00084     return session;
00085 }
00086 
00087 void CServerSession::ConstructL()
00088 {
00089     // increment client count
00090     iServer->IncrementSession();
00091 
00092     // create bluetooth communicator
00093     iBTCommunicator = CBTCommunicator::NewL(this);
00094 }
00095 
00096 CConcreteConnection* CServerSession::GetConnection(TInt id) 
00097 {
00098     if( (id < 0) || (id >= KMaxSocketCount) ) {
00099         User::Panic(KSessionPanic, KErrSessionBadSocketTableIndex);
00100     }
00101 
00102     CConcreteConnection *con = iConnections[id];
00103     if( con == NULL ) {
00104         User::Panic(KSessionPanic, KErrSessionConnectionNotFoundInGet);
00105     }
00106 
00107     return con;
00108 }
00109 
00110 // allocates room in connections table for the connection
00111 TInt CServerSession::AllocateConnection(CConcreteConnection *aConnection) 
00112 {
00113     TInt slot = -1;
00114 
00115     __ASSERT_ALWAYS(!aConnection->IsListening(), 
00116                     User::Panic(KSessionPanic, KErrSessionTryingToAllocListeningCon));
00117 
00118     for( TInt i = 0; i < KMaxSocketCount; i++ ) {
00119         if( iConnections[i] == NULL ) {
00120             slot = i;
00121             break;
00122         }
00123     }
00124 
00125     if( slot == -1 ) {
00126         // no room in table - panic!
00127         CCobainServer::PanicServer(CCobainServer::ESocketTableFull);
00128     }
00129 
00130     Log::Print(_L("AllocateConnection(): id: %d"), slot);
00131 
00132     iConnections[slot] = aConnection;
00133 
00134     return slot;
00135 }
00136 
00137 // removes the given connection from the connections table
00138 void CServerSession::DeallocateConnection(CConcreteConnection *aConnection)
00139 {
00140     __ASSERT_ALWAYS(!aConnection->IsListening(), 
00141                     User::Panic(KSessionPanic, KErrSessionTryingToDeallocListeningCon));
00142 
00143     Log::Print(_L("DeallocateConnection()"));
00144 
00145     for( TInt i = 0; i < KMaxSocketCount; i++ ) {
00146         if( aConnection == iConnections[i] ) {
00147             iConnections[i] = NULL;
00148             return;
00149         }
00150     }
00151 
00152     Log::Print(_L("DeallocateConnection() exiting.."));
00153 }
00154 
00155 void CServerSession::SetPeerList(TPeerDataList *aPeerList)
00156 {
00157     // if a peer list exists, it must be deleted first
00158     delete iPeerList;
00159     iPeerList = aPeerList;
00160 }
00161 
00162 // GetNumPeersL() has to be called first.
00163 // Int0 - ordinal (n) of the requested peer
00164 // Ptr1 - pointer to client-side buffer
00165 void CServerSession::GetPeer(const RMessage &aMessage)
00166 {
00167     TInt n = aMessage.Int0();
00168 
00169     Log::Print(_L("CServerSession::GetPeer(): n: %d"), n);
00170 
00171     if( (n < 0) || (n >= iPeerList->Count()) ) {
00172         // bad ordinal supplied
00173         aMessage.Complete(KErrArgument);
00174     }
00175 
00176     // write info about requested (n:th) peer
00177     TPeerData *data = (*iPeerList)[n];
00178     TPeerDataBuf buf = *data;
00179     aMessage.WriteL(aMessage.Ptr1(), buf);
00180 
00181     aMessage.Complete(KErrNone);
00182     return;
00183 }
00184 
00185 // Int0() - requested protocol
00186 // Ptr1() - buffer for number of peers (TInt)
00187 // Int2() - requested service identifyer (aServiceClassID for BT)
00188 void CServerSession::GetNumPeersL(const RMessage &aMessage)
00189 {
00190     // deallocate existing peer list
00191     if( iPeerList != NULL ) {
00192         iPeerList->ResetAndDestroy();
00193         delete iPeerList;
00194         iPeerList = NULL;
00195     }
00196 
00197     switch( aMessage.Int0() ) {
00198         case EBluetooth:
00199             // initiate device discovery. 
00200             // NOTE: the call will be completed by an active object
00201             iBTCommunicator->DiscoverPeersL(aMessage, 
00202                                             *this);
00203             break;
00204         default:
00205             PanicClient(aMessage, CCobainServer::EBadRequest);
00206             break;
00207     }
00208 }
00209 
00210 // Int0() - requested protocol (i.e. bearer)
00211 // Ptr1() - pointer to clientside TPeerDataBuf
00212 // Ptr2() - pointer to clientside TPckgBuf<TInt> to store the id
00213 // ##TODO## Add parameter for requtested transfer protocol (i.e.
00214 // nanoTCP, nanoUDP etc)
00215 void CServerSession::ConnectL(const RMessage &aMessage)
00216 {
00217     TPeerDataBuf buf;
00218     TInt err = KErrNone;
00219 
00220     // copy peer data
00221     aMessage.ReadL(aMessage.Ptr1(), buf);
00222     TPeerData &data = buf();
00223 
00224     // connect to the peer
00225     RSocket *socket = NULL;
00226     TInt mtu = 0;
00227 
00228     switch ( aMessage.Int0() ) {
00229         case EBluetooth:
00230             TRAP(err, (socket = iBTCommunicator->ConnectL(&data)));
00231             mtu = CBTCommunicator::ResolveMTU(*socket);
00232             break;
00233 
00234         default:
00235             PanicClient(aMessage, CCobainServer::EUnsupportedProtocol);
00236             break;
00237     }
00238 
00239     if( err != KErrNone ) {
00240         Log::Print(_L("ConnectL() error: %d"), err);
00241 
00242         // error connecting - complete call with error (negative value)
00243         aMessage.Complete(err);
00244         return;
00245     }
00246 
00247     // allocate new connection
00248     TInt slot = AllocateConnection(CConcreteConnection::NewL(socket, *this, mtu));
00249 
00250     // write the id 
00251     TPckgBuf<TInt> id_buf(slot);
00252     aMessage.WriteL(aMessage.Ptr2(), id_buf);
00253 
00254     aMessage.Complete(KErrNone);
00255 
00256     Log::Print(_L("CServerSession::ConnectL() returning.."));
00257 }
00258 
00259 // Int0() - socket id
00260 // Int1() - whether to close socket abruptively (ETrue = yes, EFalse = no)
00261 void CServerSession::CloseSocket(const RMessage &aMessage)
00262 {
00263     TInt n = aMessage.Int0();
00264 
00265     Log::Print(_L("CServerSession::CloseSocket() %d"), n);
00266 
00267     CConcreteConnection *con = GetConnection(n);
00268     DeallocateConnection(con);
00269 
00270     TBool immediately = (TBool)aMessage.Int1();
00271 
00272     Log::Print(_L("calling con->Close()"));
00273 
00274     con->Close(immediately);
00275     delete con;
00276 
00277     aMessage.Complete(KErrNone);
00278 
00279     Log::Print(_L("CloseSocket() exiting"));
00280 }
00281 
00282 // asynchronous call to retrieve the next incoming connection info.
00283 // calls asynchronous listen handler which will handle the completion of the 
00284 // message when a new connection is available
00285 void CServerSession::GetIncomingConnection(const RMessage& aMessage)
00286 {
00287     if( iListeningConnection == NULL ) {
00288         PanicClient(aMessage, CCobainServer::ENotListening);
00289     }
00290 
00291     // launches asynchronous listen handler and returns
00292     iListeningConnection->ListenL(aMessage);    
00293 }
00294 
00295 // this is a synchronous call to start listening to a given port
00296 //
00297 // Int0() - protocol
00298 // Int1() - port 
00299 // Int2() - protocol specific extra info
00300 void CServerSession::StartListen(const RMessage& aMessage)
00301 {
00302     if( iListeningConnection != NULL ) {
00303         PanicClient(aMessage, CCobainServer::EAlreadyListening);
00304     }
00305 
00306     TUint port = (TUint)aMessage.Int1();
00307     TUint list_sock_type = (TUint)aMessage.Int2();
00308 
00309     //##TODO## read these from client
00310     _LIT8(KServiceName, "Cobain");
00311     _LIT8(KServiceDesc, "CobainServiceDesc");
00312 
00313     switch( aMessage.Int0() ) {
00314         case EBluetooth:
00315             iListeningConnection = iBTCommunicator->StartListeningL(port,
00316                                                                     -1,
00317                                                                     KServiceName,
00318                                                                     KServiceDesc,
00319                                                                     list_sock_type);
00320             break;
00321         default:
00322             PanicClient(aMessage, CCobainServer::EUnsupportedProtocol);
00323             break;
00324     }
00325 
00326     // complete the message, allowing client call to return
00327     aMessage.Complete(KErrNone);
00328 }
00329 
00330 // Int0() - protocol
00331 void CServerSession::AbortListen(const RMessage& aMessage)
00332 {
00333     Log::Print(_L("AbortListen()"));
00334 
00335     switch( aMessage.Int0() ) {
00336         case EBluetooth:
00337             iBTCommunicator->StopListeningL();
00338             break;
00339         default:
00340             PanicClient(aMessage, CCobainServer::EUnsupportedProtocol);
00341             break;
00342     }
00343 
00344     iListeningConnection = NULL;
00345 
00346     aMessage.Complete(KErrNone);
00347 }
00348 
00349 // Int0() - socket ID
00350 // Ptr1() - buffer for received packet of size minimum KRecvBufSize
00351 void CServerSession::Receive(const RMessage& aMessage)
00352 {
00353     Log::Print(_L("CServerSession::Receive()"));
00354 
00355     TInt n = aMessage.Int0();
00356     CConcreteConnection *con = GetConnection(n);
00357     con->ReceiveL(aMessage);
00358 
00359     Log::Print(_L("CServerSession::Receive() returning"));
00360 }
00361 
00362 // Int0 - socket id
00363 void CServerSession::CancelReceive(const RMessage &aMessage) 
00364 {
00365     Log::Print(_L("CancelReceive()"));
00366 
00367     TInt id = aMessage.Int0();
00368     CConcreteConnection *con = GetConnection(id);
00369     con->CancelReceive();
00370     aMessage.Complete(KErrNone);
00371 }
00372 
00373 // Int0() - socket id
00374 // Int1() - data length
00375 // Ptr2() - send buffer
00376 void CServerSession::Send(const RMessage &aMessage)
00377 {
00378     TInt id = aMessage.Int0();
00379     TInt len = aMessage.Int1();
00380 
00381     Log::Print(_L("Send(): id: %d, len: %d"), id, len);
00382 
00383     // allocate buffer for the data. buffer will be released by CAsynchSend
00384     // after it has been sent
00385     HBufC8 *buf = HBufC8::NewL(len);
00386     CleanupStack::PushL(buf);
00387 
00388     // read data from client thread
00389     TPtr8 ptr = buf->Des();
00390     aMessage.ReadL(aMessage.Ptr2(), ptr);
00391 
00392     // get the connection matching the socket id
00393     CConcreteConnection *con = GetConnection(id);
00394 
00395     // send the data
00396     TRAPD(err, con->SendL(buf));
00397 
00398     CleanupStack::Pop(); // buf
00399 
00400     // allow client call to return
00401     //##TODO## handle error situations
00402     aMessage.Complete(err);
00403 }
00404 
00405 void CServerSession::ServiceL(const RMessage& aMessage)
00406 {
00407     TInt function = aMessage.Function();
00408 
00409 //    Log::Print(_L("ServiceL(): %d"), function);
00410 
00411     switch( function )
00412     {
00413         case CCobainServer::ESend:
00414             Send(aMessage);
00415             break;
00416         case CCobainServer::EConnect:
00417             ConnectL(aMessage);
00418             break;
00419         case CCobainServer::ECloseSocket:
00420             CloseSocket(aMessage);
00421             break;
00422         case CCobainServer::EGetNumPeers:
00423             GetNumPeersL(aMessage);
00424             break;
00425         case CCobainServer::EGetPeer:
00426             GetPeer(aMessage);
00427             break;
00428         case CCobainServer::EStartListen:
00429             StartListen(aMessage);
00430             break;
00431         case CCobainServer::EAbortListen:
00432             AbortListen(aMessage);
00433             break;
00434         case CCobainServer::EGetIncomingConnection:
00435             GetIncomingConnection(aMessage);
00436             break;
00437         case CCobainServer::EReceive:
00438             Receive(aMessage);
00439             break;
00440         case CCobainServer::ECancelReceive:
00441             CancelReceive(aMessage);
00442             break;
00443         default:
00444             PanicClient(aMessage, CCobainServer::EBadRequest);
00445             break;
00446     }
00447 
00448     //Log::Print(_L("ServiceL() returning"));
00449 }
00450 
00451 void CServerSession::PanicClient(const RMessage& aMessage, 
00452                                  CCobainServer::TServerPanic aPanic)
00453 {
00454     aMessage.Panic(KClientPanic, aPanic);
00455 }

Generated on Tue Jan 13 15:47:07 2004 for CobainAPIImplementation by doxygen 1.3.5