examples/DataComms/Rconnection/rconnection.cpp

00001 // Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
00002 // All rights reserved.
00003 // This component and the accompanying materials are made available
00004 // under the terms of "Eclipse Public License v1.0"
00005 // which accompanies this distribution, and is available
00006 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
00007 //
00008 // Initial Contributors:
00009 // Nokia Corporation - initial contribution.
00010 //
00011 // Contributors:
00012 //
00013 // Description:
00014 //
00015 
00016 
00017 
00018 #include "rconnection.h"
00019 
00020 _LIT(KContinueNote,"Press any key to continue\n");
00021 _LIT(KOpenErr,"Open() unsuccessful\n");
00022 _LIT(KStartErr,"RConnection::Start() unsuccessful\n");
00023 _LIT(KInterfaceUp,"Connection has started and interface is up\n");
00024 _LIT(KInterfaceDown,"Connection has closed and interface is down\n");
00025 _LIT(KConnectionUpNote,"Connection is up....\n");
00026 _LIT(KConnectionStartNote,"Start() was called on the connection\n");
00027 _LIT(KConnectionClosingNote,"The connection is about to be closed\n");
00028 _LIT(KWaitNote,"Waiting for the connection to close.....\n");
00029 _LIT(KUpLinkData,"Data volume on uplink=%d bytes\n");
00030 _LIT(KDownLinkData,"Data volume on downlink=%d bytes\n");
00031 _LIT(KDataTransferNote,"Calling DataSendAndReceive()\n");
00032 _LIT(KSocketErrNote,"Socket preparation failed\n");
00033 _LIT(KSocketSetNote,"Socket successfully established\n");
00034 
00035 _LIT(KRow1,"**********************************************************\n");
00036 _LIT(KRow2,"    Section Demonstrating  :                  \n");
00037 _LIT(KRow3,"**********************************************************\n");
00038 _LIT(KTab,"\t");
00039 _LIT(KNewLine,"\n");
00040 
00041 #define KEchoPort 0xAB                  //Port value for client socket.
00042 #define KMaxBufferLength 2048   //Maximum length of buffer used to send and receive data.
00043 #define KDelay 1000000                  //Time interval in microseconds to wait before carrying out the next task.
00044 
00048 CRConnection::CRConnection(CConsoleBase* aConsole)
00049         :iConsole(aConsole)     
00050         {
00051         //Set the destination address and port.
00052         //Before running the example user should start an Echo server 
00053         //and then specify the respective IP Address and port of the echo server 
00054         //for iDestAddr.
00055         //Until the Echo Server is established send and receive functionality won't work properly. 
00056         
00057         
00058         _LIT(KDestAddr,"127.0.0.1");  
00059         const TInt KSockPort= 7;
00060         
00061         iDestAddr.Input(KDestAddr);
00062         iDestAddr.SetPort(KSockPort);
00063           
00064         StartESOCK();
00065         }
00066 
00067 
00071 CRConnection::~CRConnection()
00072         {
00073         //Closing the monitor and socket server session.
00074         iMonitor.Close();
00075         iSocketServ.Close();
00076         }
00077 
00083 void CRConnection::StartESOCK() 
00084         {
00085         
00086         //Connects to the socket server.
00087         TInt err=iSocketServ.Connect();
00088         if(err!=KErrNone)
00089                 {
00090                 _LIT(KConnectErr,"Connect failed\n");
00091                 User::Panic(KConnectErr,err);           
00092                 }       
00093         
00094         //Opens the monitor to receive notification when another connection
00095         //that uses the same socket server goes up or down. 
00096         err=iMonitor.Open(iSocketServ);
00097         if(err!=KErrNone)
00098                 {
00099                 iConsole->Printf(KOpenErr);
00100                 return; 
00101                 }       
00102         }
00103                 
00111 TInt CRConnection::ConnectWithoutDbOverrideL()
00112         {
00113         // Opens an RConnection and associates it with the same socket server session as iMonitor.
00114         // To use an RConnection instance first it needs to be opened on an existing socket server session 
00115         // and then Start() must be called to associate it with an underlying interface.
00116         TInt err=iConnection.Open(iSocketServ); 
00117         if(err!=KErrNone)
00118                 {
00119                 iConsole->Printf(KOpenErr);
00120                 return err;     
00121                 }
00122         
00123         //Starts the connection using default CommDb settings.
00124         err=iConnection.Start();
00125         if(err!=KErrNone)
00126                 {
00127                 iConsole->Printf(KStartErr);
00128                 return err;     
00129                 }
00130         else
00131                 {
00132                 iConsole->Printf(KConnectionStartNote); 
00133                 return err;
00134                 }                               
00135         }
00136         
00140 TInt CRConnection::ConnectWithDbOverrideL()
00141         {
00142         // To use an RConnection instance first it needs to be opened on an existing socket server session 
00143         // and then Start() must be called to associate it with an underlying interface.
00144         TInt err=iConnection.Open(iSocketServ); 
00145         if(err!=KErrNone)
00146                 {
00147                 iConsole->Printf(KOpenErr);
00148                 return err;
00149                 }
00150         
00151         // Overrides some Commdb connection preferences.
00152         const TInt KIapId=9;
00153         TCommDbConnPref prefs;
00154         prefs.SetDialogPreference(ECommDbDialogPrefDoNotPrompt);
00155         prefs.SetIapId(KIapId);    //The commdb is set for Ethernet with Daemon Static IP. 
00156                                                                         
00157         //Starts an outgoing connection.
00158         err=iConnection.Start(prefs);
00159         
00160         if(err==KErrNone)
00161                 {
00162                 iConsole->Printf(KConnectionStartNote); 
00163                 return err;
00164                 }
00165         else
00166                 {
00167                 iConsole->Printf(KStartErr);
00168                 return err;     
00169                 }               
00170         }
00176 void CRConnection::GetProgressNotification()
00177         {
00178         TRequestStatus status;
00179         TNifProgressBuf buffer; //filled with progress/error information on completion 
00180         while((TUint)(buffer().iStage)!=KConnectionUp) 
00181                 {
00182                 iConnection.ProgressNotification(buffer,status);
00183                 User::WaitForRequest(status);
00184                 if(status==KErrNone&&(buffer().iError)==KErrNone)
00185                         {
00186                         DisplayProgressinfo(buffer());
00187                         }
00188                 User::After(KDelay);
00189                 }
00190         iConsole->Printf(KConnectionUpNote); //Link layer is now open.  
00191                 
00192                         
00193         }
00194         
00199 void CRConnection::DisplayProgressinfo(const TNifProgress& aProgress)
00200         {
00201         switch(aProgress.iStage)
00202                 {
00203                 case KStartingSelection:
00204                         {
00205                         _LIT(KStartSelectionNote,"Starting Selection...........\n");
00206                         iConsole->Printf(KStartSelectionNote);
00207                         break;  
00208                         }
00209                                         
00210                 case KFinishedSelection:
00211                         {
00212                         _LIT(KFinishedSelectionNote,"Finished Selection...........\n");
00213                         iConsole->Printf(KFinishedSelectionNote);
00214                         break;  
00215                         }
00216                                         
00217                 case KConnectionOpen:
00218                         {
00219                         _LIT(KWlanAgtConnected,"Wlan agent connected....\n");
00220                         iConsole->Printf(KWlanAgtConnected);
00221                         break;  
00222                         }
00223                                                 
00224                 //Generic progress notifications from the configuration daemon.                         
00225                 case KConfigDaemonLoading:
00226                         {
00227                         _LIT(KConfigDaemonLoadingNote,"Daemon loading....\n");
00228                         iConsole->Printf(KConfigDaemonLoadingNote);
00229                         break;  
00230                         }
00231                                         
00232                 case KConfigDaemonLoaded:
00233                         {
00234                         _LIT(KConfigDaemonLoadedNote,"Daemon loaded....\n");
00235                         iConsole->Printf(KConfigDaemonLoadedNote);
00236                         break;  
00237                         }
00238                                                 
00239                 case KConfigDaemonStartingRegistration:
00240                         {
00241                         _LIT(KConfigDaemonStartingRegistrationNote,"Daemon starting registration....\n");
00242                         iConsole->Printf(KConfigDaemonStartingRegistrationNote);
00243                         break;  
00244                         }
00245                                                 
00246                 case KConfigDaemonFinishedRegistration:
00247                         {
00248                         _LIT(KConfigDaemonFinishedRegistrationNote,"Daemon registration finished....\n");
00249                         iConsole->Printf(KConfigDaemonFinishedRegistrationNote);
00250                         break;  
00251                         }       
00252         
00253                 default:
00254                         break;                  
00255                 }
00256         }
00257 
00263 TInt CRConnection::PrepareSocket()
00264         {
00265         TInt err = iSocket.Open(iSocketServ, KAfInet, KSockDatagram, KProtocolInetUdp, iConnection);
00266         if (err != KErrNone)
00267                 {
00268                 return err;     
00269                 }
00270                 
00271         //Sets a socket option. These options affect operations such as the routing of packets, 
00272         //out-of-band data transfer, and so on. Here the option level "KSolInetIp" is set for an IP socket,
00273         //and the option being set is "KSoReuseAddr". This means the socket is allowed to be bound to a local
00274         //address that is already in use.
00275         //The third parameter i.e 1 states that the option is enabled.A value of 0 means disabled.
00276         
00277         err = iSocket.SetOpt(KSoReuseAddr, KSolInetIp, 1); 
00278         if (err != KErrNone)
00279                 {
00280                 return err;     
00281                 }
00282         
00283         //Sets a local port for the socket.
00284         err = iSocket.SetLocalPort(KEchoPort); 
00285         if (err != KErrNone)
00286                 {
00287                 return err;     
00288                 }
00289         return err;             
00290         }
00296 TInt CRConnection::SendUdpData(TUint aPayloadSize)
00297         {
00298         
00299         TBuf8<KMaxBufferLength> buffer;
00300         // construct an ICMP packet to send on the socket.
00301         buffer.SetMax();
00302         buffer.FillZ();
00303         buffer[0] = (TUint8) 0x08; // ICMP type = 8.
00304         buffer[1] = (TUint8) 0x00; // ICMP code = 0.
00305         buffer[2] = (TUint8) 0xF7; // ICMP checksum high byte.
00306         buffer[3] = (TUint8) 0xFF; // ICMP checksum low byte.
00307         
00308         // NB the rest of the buffer is zero
00309         // hence the checksum (0xFFFF - 0x800) since 0x8
00310         // is the only non-zero element of the buffer
00311 
00312         // set the length of the data to be sent to that specified (payload size!).
00313         buffer.SetLength(aPayloadSize);
00314 
00315         TRequestStatus status;
00316 
00317         // send the data out over the socket.
00318         iSocket.SendTo(buffer, iDestAddr, 0, status);
00319         User::WaitForRequest(status);
00320 
00321         return status.Int();
00322         }
00323 
00329 TInt CRConnection::RecvUdpData(TUint aPayloadSize)
00330         {
00331         
00332         TInt timeoutInSecs = 30;
00333         RTimer timer;
00334         
00335         /* 
00336         Creates a timer so that we can handle error situation arising due to lost udp packet
00337         and dont completely rely on being errored by esock alone. This code waits for 30sec for
00338         udp data packet to arrive from the server. If the data is not available within this
00339         time the socket waiting for data is closed and the error value of KErrTimedOut is 
00340         returned. 
00341         */
00342         TInt ret;
00343         if ((ret = timer.CreateLocal()) != KErrNone)
00344                 {
00345                 timer.Close(); // closing the timer.
00346                 return ret;
00347                 }
00348         TRequestStatus timerStatus;
00349         timer.After(timerStatus, timeoutInSecs * 1000000); //setting timer.
00350         
00351         TBuf8<KMaxBufferLength> buffer;
00352         buffer.Zero();
00353         buffer.SetLength(aPayloadSize);
00354 
00355         TRequestStatus status;
00356         iSocket.RecvFrom(buffer, iDestAddr, 0, status); //waiting on data from the server.
00357         User::WaitForRequest(status, timerStatus);
00358 
00359         // Timer expired, and if no data is received cancel the receive operation.
00360         if(timerStatus != KRequestPending)
00361                 {
00362                 iSocket.CancelAll();
00363                 User::WaitForRequest(status);
00364                 timer.Close();
00365                 return KErrTimedOut;
00366                 }
00367         // otherwise cancel the timer.
00368         timer.Cancel();
00369         User::WaitForRequest(timerStatus);
00370         timer.Close();
00371 
00372         //when data is successfully received, check against the previously sent buffer data,
00373         //to see what is received is what was sent.
00374         if (status != KErrNone)
00375                 return status.Int();
00376         else
00377                 {   
00378                 if(buffer[0] == 0x08)
00379                         {
00380                         if(buffer[1] == 0x00)
00381                                 {
00382                                 if(buffer[2] == 0xF7)
00383                                         {
00384                                         if(buffer[3] == 0xFF)
00385                                                 {
00386                                                 ;       
00387                                                 }
00388                                         else 
00389                                                 {
00390                                                 _LIT(KFourthDataSet,"Fourth set of data not received\n");
00391                                                 iConsole->Printf(KFourthDataSet);
00392                                                 }               
00393                                         }
00394                                 else
00395                                         {
00396                                         _LIT(KThirdDataSet,"Third set of data not received\n");
00397                                         iConsole->Printf(KThirdDataSet);        
00398                                         }       
00399 
00400                                 }
00401                         else
00402                                 {
00403                                 _LIT(KSecondDataSet,"Second set of data not received\n");
00404                                 iConsole->Printf(KSecondDataSet);       
00405                                 }
00406                         }
00407                 else
00408                         {
00409                         _LIT(KFirstDataSet,"First set of data not received\n");
00410                         iConsole->Printf(KFirstDataSet);        
00411                         }       
00412                         
00413                 }
00414         return KErrNone;
00415         }
00416 
00420 void CRConnection::DataSendAndReceive(TUint aPayloadSize)
00421         {
00422         //Sends UDP Data.
00423         TInt err = SendUdpData(aPayloadSize);
00424         if (err != KErrNone)
00425                 {
00426                 _LIT(KDataSentErrNote,"DataSend Failed\n");
00427                 iConsole->Printf(KDataSentErrNote);
00428                 return ;        
00429                 }
00430         else
00431                 {
00432                 _LIT(KDataSentNote,"DataSend Successful\n");
00433                 iConsole->Printf(KDataSentNote);        
00434                 }
00435 
00436         //Receives UDP Data.
00437         err = RecvUdpData(aPayloadSize);
00438         if(err!=KErrNone)
00439                 {
00440                 _LIT(KDataReceiveErrNote,"DataReceive Failed\n");
00441                 iConsole->Printf(KDataReceiveErrNote);
00442                 return ;        
00443                 }
00444         else
00445                 {
00446                 _LIT(KDataReceiveNote,"DataReceive Successful\n");
00447                 iConsole->Printf(KDataReceiveNote);
00448                 }       
00449                 
00450         }
00451 
00455 void CRConnection::DataTransferredRequest()
00456         {
00457         TPckg<TUint> uplinkVolumeDes(0); //holds the amount of data received.
00458         TPckg<TUint> downlinkVolumeDes(0); //holds the amount of data transmitted.
00459         
00460         TRequestStatus datastatus;
00461 
00462         iConnection.DataTransferredRequest(uplinkVolumeDes, downlinkVolumeDes, datastatus);
00463         User::WaitForRequest(datastatus);
00464         
00465         if(datastatus==KErrNone)
00466                 {
00467                 iConsole->Printf(KUpLinkData,uplinkVolumeDes());
00468                 iConsole->Printf(KDownLinkData,downlinkVolumeDes());    
00469                 }
00470                         
00471         }
00476 void CRConnection::DataTransferNotificationRequest()
00477         {
00478         const TUint KHundredBytes = 100; //The threshold value for notification.
00479         const TUint KThousandBytes = 1000; //The total amount of data to send/receive.
00480         TPckg< TUint > uplinkPkg(0); //Holds the amount of data sent.
00481         TPckg< TUint > downlinkPkg(0);//Holds the amount of data received.
00482         TRequestStatus dataSentStatus,dataReceivedStatus;
00483         
00484         //Registers for data sent notification. The process gets notified when 100 bytes of data are sent. 
00485         iConnection.DataSentNotificationRequest(KHundredBytes, uplinkPkg, dataSentStatus );
00486         
00487         //Registers for data received notification. The process gets notified when 100 bytes of data are received.
00488         iConnection.DataReceivedNotificationRequest(KHundredBytes, downlinkPkg, dataReceivedStatus );
00489         iConsole->Printf(KDataTransferNote);
00490         
00491         //Sends and receives 1000 bytes of data.
00492         DataSendAndReceive(KThousandBytes);
00493                 
00494         /*
00495         Gets the total data sent/received = datavolume+UdpPacketOverhead
00496         here datavolume=1000 bytes,thus total data send/receive > 1000 as 
00497         some overhead gets added on top of the actual datavolume.
00498         */
00499         
00500         User::WaitForRequest(dataSentStatus);
00501         User::WaitForRequest(dataReceivedStatus);
00502         if ((dataSentStatus.Int())== KErrNone)
00503                 {
00504                 _LIT(KSentSuccessNote,"DataSentNotificationRequest is successful and\n ");      
00505                 iConsole->Printf(KSentSuccessNote);
00506                 }
00507         else
00508                 {
00509                 _LIT(KSentFailureNote,"DataSentNotificationRequest has failed and \n");
00510                 iConsole->Printf(KSentFailureNote);
00511                 }
00512         iConsole->Printf(KUpLinkData,uplinkPkg());
00513                                         
00514         if (dataReceivedStatus.Int()==KErrNone)
00515                 {
00516                 _LIT(KReceivedSuccessNote,"DataReceivedNotificationRequest is successful and \n");      
00517                 iConsole->Printf(KReceivedSuccessNote);
00518                 }
00519         else 
00520                 {
00521                 _LIT(KReceivedFailureNote,"DataReceivedNotificationRequest has failed and \n");
00522                 iConsole->Printf(KReceivedFailureNote);
00523                 }               
00524         iConsole->Printf(KDownLinkData,downlinkPkg());  
00525 
00526         }
00527         
00528 void CRConnection::DisplaySectionToDemo(const TDesC& aText)
00529         {
00530         TBuf<120> newtext;
00531         newtext.Append(KTab);
00532         newtext.Append(aText);
00533         newtext.Append(KTab);
00534         newtext.Append(KNewLine);
00535         iConsole->Printf(KRow1);
00536         iConsole->Printf(KRow2);
00537         iConsole->Printf(newtext);
00538         iConsole->Printf(KRow3);
00539         iConsole->Printf(KNewLine);
00540         }
00541 
00552 void CRConnection::DemoApiWithoutDbOverrideL()
00553         {
00554         _LIT(KDemoApiWithoutDbOverride,"RConnection API without CommDb override\n");
00555         iConsole->ClearScreen();
00556         DisplaySectionToDemo(KDemoApiWithoutDbOverride);
00557         
00558         TRequestStatus status;
00559         TInterfaceNotificationBuf info;
00560         //Makes a request for notification when the interface goes up i.e. the connection starts.
00561         iMonitor.AllInterfaceNotification(info,status);
00562                 
00563         //Makes an explicit connection without CommDb override. 
00564         TInt err=ConnectWithoutDbOverrideL();
00565         if(err!=KErrNone)
00566                 return;
00567         
00568         //Waits on TRequestStatus until the interface is up.
00569         User::WaitForRequest(status);
00570         if(info().iState==EInterfaceUp)
00571                 {
00572                 iConsole->Printf(KInterfaceUp); 
00573                 }                               
00574         
00575         //Gets and prints progress notification for the connection.
00576         GetProgressNotification();
00577         User::After(KDelay);  // waits for a while and then proceeds. This helps to get a sequential flow.
00578         
00579         err=PrepareSocket(); // Once the socket is ready for data transfer, send and receive operations can be carried out.
00580         if(err!=KErrNone)
00581                 {
00582                 iConsole->Printf(KSocketErrNote);
00583                 return; 
00584                 }
00585         else
00586                 {
00587                 iConsole->Printf(KSocketSetNote);       
00588                 }       
00589         
00590         iConsole->Printf(KDataTransferNote);
00591         
00592         const TUint KPayLoadSize=512;
00593         //Sends and receives data through the socket.
00594         DataSendAndReceive(KPayLoadSize);
00595         
00596         DataTransferredRequest();// Gets and prints the amount of data that has been transferred.
00597                 
00598         User::After(KDelay);//Wait for a while, before proceeding.      
00599 
00600         //Makes a request for notification when the interface goes down i.e. the connection closes.
00601         iMonitor.AllInterfaceNotification(info,status); 
00602                 
00603         // All the operations related to the socket and connection are done, so close both.
00604         iSocket.Close();
00605         iConsole->Printf(KConnectionClosingNote);
00606         iConnection.Close();
00607         iConsole->Printf(KWaitNote); 
00608         
00609         //Waits for the 'interface down' notification
00610         User::WaitForRequest(status);
00611         if(info().iState==EInterfaceDown)
00612                 {
00613                 iConsole->Printf(KInterfaceDown);       
00614                 }
00615                 
00616         iConsole->Printf(KContinueNote);
00617         iConsole->Getch();
00618 
00619         }
00620         
00631 void CRConnection::DemoApiWithDbOverrideL()
00632         {
00633         
00634         _LIT(KDemoApiWithDbOverride,"RConnection API with CommDb override\n");
00635         iConsole->ClearScreen();
00636         DisplaySectionToDemo(KDemoApiWithDbOverride);
00637                 
00638         TRequestStatus status;
00639         TInterfaceNotificationBuf info;
00640         
00641         // Requests notification when the connection is established.
00642         // Notification request is issued before calling Start().
00643         iMonitor.AllInterfaceNotification(info,status);
00644         
00645         //Start an explicit connection with CommDb override. 
00646         TInt err=ConnectWithDbOverrideL();
00647         if(err!=KErrNone)
00648                 return;
00649         
00650         //Waits on TRequestStatus until the interface is up.
00651         User::WaitForRequest(status);
00652         if(info().iState==EInterfaceUp)
00653                 {
00654                 iConsole->Printf(KInterfaceUp); 
00655                 }       
00656 
00657         //Gets and prints progress notification for the connection.
00658         GetProgressNotification();
00659         
00660         //Waits for a while before next operation.
00661         User::After(KDelay);
00662         
00663         err=PrepareSocket(); //Once the socket is ready for data transfer, send and receive operations can be carried out.
00664         if(err!=KErrNone)
00665                 {
00666                 iConsole->Printf(KSocketErrNote);
00667                 return; 
00668                 }
00669         else    
00670                 {
00671                 iConsole->Printf(KSocketSetNote);       
00672                 }
00673         //Sends and receives data and requests notification when a threshold amount of data is transferred.
00674         DataTransferNotificationRequest(); 
00675         User::After(KDelay);
00676 
00677         //Makes a request for notification when the interface goes down i.e. the connection closes.
00678         iMonitor.AllInterfaceNotification(info,status);
00679                 
00680         //Closes socket 
00681         iSocket.Close();
00682         iConsole->Printf(KConnectionClosingNote);
00683                 
00684         //Closes the connection.
00685         iConnection.Close();
00686         iConsole->Printf(KWaitNote); 
00687         
00688         //Waits on the TRequestStatus until the interface is down 
00689         User::WaitForRequest(status);
00690         if(info().iState==EInterfaceDown)
00691                 {
00692                 iConsole->Printf(KInterfaceDown);       
00693                 }       
00694         
00695         iConsole->Printf(KContinueNote);
00696         iConsole->Getch();
00697         
00698         }
00699 
00709 void CRConnection::AttachToExistingInterfaceL()
00710         {
00711         
00712         _LIT(KAttachToConnection,"Attaching to a connection\n");
00713         iConsole->ClearScreen();
00714         DisplaySectionToDemo(KAttachToConnection);
00715         
00716         // Attaching to a connection is done as follows:
00717         // 1)first open a connection interface.
00718         // 2)on this connection interface, obtain the no. of active connections and their connection info.
00719         // 3)a second connection is opened.
00720         // 4)this 2nd connection is attached to the existing active connection interface.
00721          
00722         RConnection conn;
00723         
00724         //Opens the first RConnection.
00725         TInt err = conn.Open(iSocketServ);
00726         if(err==KErrNone)
00727                 {
00728                 CleanupClosePushL(conn);        
00729                 }
00730         else
00731                 {
00732                 iConsole->Printf(KOpenErr);
00733                 return; 
00734                 }       
00735         
00736         //Opens the 2nd connection. 
00737         err =  iConnection.Open(iSocketServ);
00738         if(err!=KErrNone)
00739                 {
00740                 iConsole->Printf(KOpenErr);
00741                 return; 
00742                 }       
00743         
00744         //Starts the 1st connection.
00745         err=conn.Start();
00746         if(err!=KErrNone)
00747                 {
00748                 iConsole->Printf(KStartErr);
00749                 return; 
00750                 }
00751         
00752         // Enumerates the total number of connections on the 1st connection interface.
00753         // This call returns a count of 1.      
00754         TUint connectionCount;
00755         err = conn.EnumerateConnections(connectionCount);
00756         if((err != KErrNone) || (connectionCount < 1))
00757                 {
00758                 return;
00759                 }
00760         
00761         
00762         // Gets connection info for the 1st connection (conn) which will be used by the 
00763         // 2nd connection to attach to. 
00764         TConnectionInfoBuf connectionInfo;
00765         err = conn.GetConnectionInfo(connectionCount, connectionInfo); // gets connection info about the indexed connection
00766                                                                                                                                    // (the 1st connection).
00767         if(err != KErrNone)
00768                 {
00769                 return;
00770                 }
00771 
00772         // Attaches iConnection to the existing underlying interface.
00773         // The connection is used for normal data transfer.
00774         // Both connections are now actively associated with an interface.
00775         err = iConnection.Attach(connectionInfo,RConnection::EAttachTypeNormal);
00776         if(err==KErrNone)
00777                 {
00778                 _LIT(KAttachNote,"Attached to interface\n");    
00779                 iConsole->Printf(KAttachNote);                  
00780                 }
00781         else
00782                 return; 
00783         
00784         // Gets progress info and prints it to the console. 
00785     TNifProgress progress;
00786     err = iConnection.Progress(progress);
00787     if(err==KErrNone&&progress.iError==KErrNone)
00788             {
00789             if((TUint)(progress.iStage)==KConnectionUp)
00790                 iConsole->Printf(KConnectionUpNote);    
00791             }
00792         
00793         User::After(KDelay);  //waits for a while before proceeding.
00794         
00795         iConsole->Printf(KConnectionClosingNote);
00796                 
00797         //closes both connections.
00798         iConnection.Close();
00799         CleanupStack::PopAndDestroy(&conn); //conn.
00800         
00801         _LIT(KConnectionClosedNote,"Connection Closed\n");
00802         iConsole->Printf(KConnectionClosedNote);
00803         
00804         }
00805 

Generated by  doxygen 1.6.2