sdkcreationmw/sdkruntimes/wsock/src/wsock.cpp
changeset 0 b26acd06ea60
child 1 ac50fd48361b
equal deleted inserted replaced
-1:000000000000 0:b26acd06ea60
       
     1 /*
       
     2 * Copyright (c) 2004-2007 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #define TRACE_PREFIX "WSOCK: "
       
    20 #include "wsock.h"
       
    21 #include <utf.h>
       
    22 #include <etelpckt.h>
       
    23 #include <ApEngineConsts.h>
       
    24 #include <CNetworkControllerBase.h>
       
    25 #include "WinsockAgentFactory.h"
       
    26 #include "WinsockProtocolFamily.h"
       
    27 #include "WinsockInterfaceFactory.h"
       
    28 #include "WinsockUtils.h"
       
    29 
       
    30 _LIT(KProxyTableName,"Proxies");
       
    31 static const TInt KDefaultProxyPort = 8080;
       
    32 
       
    33 enum TProxyUpdateFlags
       
    34 {
       
    35     TProxyUpdateUseProxy                = 0x00000001,
       
    36     TProxyUpdateServerName              = 0x00000002,
       
    37     TProxyUpdateProtocol                = 0x00000004,
       
    38     TProxyUpdatePort                    = 0x00000008,
       
    39     TProxyUpdateName                    = 0x00000010
       
    40 };
       
    41 
       
    42 enum TBearerUpdateFlags
       
    43 {
       
    44     TBearerUpdateAgent                  = 0x00000001,
       
    45     TBearerUpdateSocketActivityTimeout  = 0x00000002,
       
    46     TBearerUpdateSessionClosedTimeout   = 0x00000004,
       
    47     TBearerUpdateSocketClosedTimeout    = 0x00000008
       
    48 };
       
    49 
       
    50 enum TServiceUpdateFlags
       
    51 {
       
    52     TServiceUpdateNetworks              = 0x00000001,
       
    53     TServiceUpdateAuthPrompt            = 0x00000002,
       
    54     TServiceUpdateAPN                   = 0x00000004,
       
    55     TServiceUpdateAPType                = 0x00000008
       
    56 };
       
    57 
       
    58 enum TIAPUpdateFlags
       
    59 {
       
    60     TIAPUpdateService                   = 0x00000001,
       
    61     TIAPUpdateServiceType               = 0x00000002,
       
    62     TIAPUpdateBearer                    = 0x00000004,
       
    63     TIAPUpdateBearerType                = 0x00000008,
       
    64     TIAPUpdateNetwork                   = 0x00000010
       
    65 };
       
    66 
       
    67 enum TWapIpBearerUpdateFlags
       
    68 {
       
    69     TWapIpBearerUpdateIAP               = 0x00000001,
       
    70     TWapIpBearerUpdateWspOption         = 0x00000002,
       
    71     TWapIpBearerUpdateProxyPort         = 0x00000004,
       
    72     TWapIpBearerUpdateSecurity          = 0x00000008,
       
    73     TWapIpBearerUpdateGatewayAddress    = 0x00000010,
       
    74     TWapIpBearerUpdateProxyLoginName    = 0x00000020,
       
    75     TWapIpBearerUpdateProxyLoginPass    = 0x00000040
       
    76 };
       
    77 
       
    78 #ifdef _REALLY_DEBUG
       
    79 extern "C" int __stdcall IsDebuggerPresent(void);
       
    80 void WsockAssert(const TText* s, const TText* file, TInt line)
       
    81 {
       
    82     TRACE1("Assertion failed: %s",s);
       
    83     TRACE1("File: %s",file);
       
    84     TRACE1("Line: %d",line);
       
    85 
       
    86     #ifdef WSOCK_ASSERT_BREAKPOINT
       
    87     if (IsDebuggerPresent())
       
    88     {
       
    89         __BREAKPOINT();
       
    90     }
       
    91     #endif
       
    92 }
       
    93 TInt WsockAssertSuccess(TInt err, const TText* s, const TText* file, TInt line)
       
    94 {
       
    95     if (err != KErrNone)
       
    96     {
       
    97         TRACE1("Unexpected error: %d",err);
       
    98         TRACE1("Expression: %s",s);
       
    99         TRACE1("File: %s",file);
       
   100         TRACE1("Line: %d",line);
       
   101 
       
   102         #ifdef WSOCK_ASSERT_BREAKPOINT
       
   103         if (IsDebuggerPresent())
       
   104         {
       
   105             __BREAKPOINT();
       
   106         }
       
   107         #endif
       
   108     }
       
   109     return err;
       
   110 }
       
   111 void WsockLeave(TInt err, const TText* s, const TText* file, TInt line)
       
   112 {
       
   113     TRACE2("Leaving with error %d (%s)",err,s);
       
   114     TRACE1("File: %s",file);
       
   115     TRACE1("Line: %d",line);
       
   116 
       
   117     #ifdef WSOCK_ASSERT_BREAKPOINT
       
   118     if (IsDebuggerPresent())
       
   119     {
       
   120         __BREAKPOINT();
       
   121     }
       
   122     #endif
       
   123     User::Leave(err);
       
   124 }
       
   125 void WsockLeaveIfError(TInt err, const TText* s, const TText* file, TInt line)
       
   126 {
       
   127     if (err != KErrNone)
       
   128     {
       
   129         TRACE1("Unexpected error: %d",err);
       
   130         TRACE1("Expression: %s",s);
       
   131         TRACE1("File: %s",file);
       
   132         TRACE1("Line: %d",line);
       
   133 
       
   134         #ifdef WSOCK_ASSERT_BREAKPOINT
       
   135         if (IsDebuggerPresent())
       
   136         {
       
   137             __BREAKPOINT();
       
   138         }
       
   139         #endif
       
   140         User::Leave(err);
       
   141     }
       
   142 }
       
   143 #endif // _REALLY_DEBUG
       
   144 
       
   145 // WSOCK lock
       
   146 class WsockLock
       
   147 {
       
   148 private:
       
   149     TBool iLocked;
       
   150     RMutex iMutex;
       
   151 public:
       
   152     WsockLock() : iLocked(EFalse) {}
       
   153     ~WsockLock() {
       
   154         ASSERT(!iLocked);
       
   155         if (iLocked) Unlock();
       
   156     }
       
   157 
       
   158     // Locks the mutex, returning KErrNone on success
       
   159     TInt Lock()
       
   160     {
       
   161         _LIT(KMutexName, "WsockLock");
       
   162         ASSERT(!iLocked);
       
   163         TInt err = iMutex.CreateGlobal(KMutexName, EOwnerThread);
       
   164         while (err == KErrAlreadyExists) {
       
   165             err = iMutex.OpenGlobal(KMutexName, EOwnerThread);
       
   166             if (err == KErrNone) {
       
   167                 TRACE("opened existing CommDb mutex");
       
   168             } else {
       
   169                 TRACE("couldn't either create or open CommDb mutex, retry");
       
   170                 err = iMutex.CreateGlobal(KMutexName, EOwnerThread);
       
   171             }
       
   172         }
       
   173         ASSERT_SUCCESS(err);
       
   174         if (err == KErrNone) {
       
   175             iMutex.Wait();
       
   176             iLocked = ETrue;
       
   177         }
       
   178         return err;
       
   179     }
       
   180 
       
   181     // Locks the mutex, leaves on failure
       
   182     void LockL()
       
   183     {
       
   184         LEAVE_IF_ERROR(Lock());
       
   185     }
       
   186 
       
   187     // Locks the mutex, leaves on failure, sets up cleanup callback
       
   188     void LockLC()
       
   189     {
       
   190         LEAVE_IF_ERROR(Lock());
       
   191         CleanupStack::PushL(TCleanupItem(UnlockOnLeave,this));
       
   192     }
       
   193 
       
   194     // Releases the mutex
       
   195     void Unlock()
       
   196     {
       
   197         ASSERT(iLocked);
       
   198         if (iLocked) {
       
   199             iLocked = EFalse;
       
   200             iMutex.Signal();
       
   201             iMutex.Close();
       
   202         }
       
   203     }
       
   204 
       
   205     // Cleanup callback. Unlocks WsockLock
       
   206     static void UnlockOnLeave(TAny* aPtr)
       
   207     {
       
   208         WsockLock* lock = (WsockLock*)aPtr;
       
   209         lock->Unlock();
       
   210     }
       
   211 };
       
   212 
       
   213 // Cleanup callback. Rolls back the transaction
       
   214 static void WsockRollbackOnLeave(TAny* aDb)
       
   215 {
       
   216     CCommsDatabase* db = (CCommsDatabase*)aDb;
       
   217     db->RollbackTransaction();
       
   218 }
       
   219 
       
   220 // Begins CommDb transaction
       
   221 static void WsockBeginCommDbTransactionLC(CCommsDatabase* aDb)
       
   222 {
       
   223     TInt err = aDb->BeginTransaction();
       
   224     TInt retriesLeft = KRetryCount;
       
   225     while ((err == KErrLocked || err == KErrAccessDenied) && --retriesLeft)
       
   226     {
       
   227         User::After(KRetryWait);
       
   228         err = aDb->BeginTransaction();
       
   229     }
       
   230     LEAVE_IF_ERROR(err); // Leaves if error
       
   231     CleanupStack::PushL(TCleanupItem(WsockRollbackOnLeave,aDb));
       
   232 }
       
   233 
       
   234 // Checks proxy settings in CommDb. Returns ETrue if transaction needs
       
   235 // to be commited. If aProxyHost is NULL, does not check the proxy values,
       
   236 // only makes sure that there is on and only one proxy record in CommDb.
       
   237 // If we allow more than one record, Symbian HTTP framework gets confused
       
   238 // what to use and more often than not uses the wrong one. Particularly,
       
   239 // it appears to prefer proxy records associated with OutgoingGPRS service,
       
   240 // ignoring LANService.
       
   241 static TBool WsockCheckProxyL(CCommsDatabase* aDb,
       
   242                               TUint32 aServiceId,
       
   243                               TBool aUseProxy,
       
   244                               const TDesC* aProxyHost,
       
   245                               TUint aProxyPort)
       
   246 {
       
   247     _LIT(KProxyProtocol,"http");
       
   248     _LIT(KProxyName, "Winsock Proxy Settings");
       
   249     const TDesC& TableName = KProxyTableName();
       
   250     const TDesC& ServiceType = KWinsockServiceType();
       
   251     TRACE1("examining %S table...",&TableName);
       
   252     CCommsDbTableView* view = aDb->OpenTableLC(TableName);
       
   253 
       
   254     // Column names
       
   255     TPtrC IdColumn(COMMDB_ID);
       
   256     TPtrC NameColumn(COMMDB_NAME);
       
   257     TPtrC ISPColumn(PROXY_ISP);
       
   258     TPtrC UseProxyColumn(PROXY_USE_PROXY_SERVER);
       
   259     TPtrC ServiceTypeColumn(PROXY_SERVICE_TYPE);
       
   260     TPtrC ServerNameColumn(PROXY_SERVER_NAME);
       
   261     TPtrC ProtocolColumn(PROXY_PROTOCOL_NAME);
       
   262     TPtrC ProxyPortColumn(PROXY_PORT_NUMBER);
       
   263 
       
   264     // Delete everything except our record
       
   265     TInt err;
       
   266     TUint32 id = 0;
       
   267     TBool recordFound = EFalse;
       
   268     TBool databaseUpdated  = EFalse;
       
   269     if (view->GotoFirstRecord() == KErrNone)
       
   270     {
       
   271         TUint32 number = 0;
       
   272         TBuf<KCommsDbSvrMaxFieldLength> text;
       
   273         do
       
   274         {
       
   275             // This one must exist
       
   276             TRAP(err, view->ReadUintL(IdColumn, id));
       
   277             if (err == KErrNone)
       
   278             {
       
   279                 // We detect our record based on the values of "ISP"
       
   280                 // and "ProxyServiceType" columns
       
   281                 number = 0;
       
   282                 TRAP(err, view->ReadUintL(ISPColumn,number));
       
   283                 TRAP(err, view->ReadTextL(ServiceTypeColumn,text));
       
   284                 TRACE4("  %S #%d -> %d,%S",&TableName,id,number,&text);
       
   285                 if (err == KErrNone &&
       
   286                     text == ServiceType &&
       
   287                     number == aServiceId &&
       
   288                     !recordFound)
       
   289                 {
       
   290                     TUint updateFlags = 0;
       
   291                     if (aProxyHost)
       
   292                     {
       
   293                         TBool useProxy = EFalse;
       
   294                         TRAP(err, view->ReadBoolL(UseProxyColumn,useProxy));
       
   295                         if (err != KErrNone || useProxy != aUseProxy)
       
   296                         {
       
   297                             updateFlags |= TProxyUpdateUseProxy;
       
   298                         }
       
   299 
       
   300                         HBufC* val = NULL;
       
   301                         TRAP(err, val = view->ReadLongTextLC(ServerNameColumn);
       
   302                         CleanupStack::Pop(val));
       
   303                         if (err != KErrNone || *val != *aProxyHost)
       
   304                         {
       
   305                             updateFlags |= TProxyUpdateServerName;
       
   306                         }
       
   307                         delete val;
       
   308 
       
   309                         TRAP(err, view->ReadUintL(ProxyPortColumn,number));
       
   310                         if (err != KErrNone || number != aProxyPort)
       
   311                         {
       
   312                             updateFlags |= TProxyUpdatePort;
       
   313                         }
       
   314                     }
       
   315 
       
   316                     TRAP(err, view->ReadTextL(NameColumn,text));
       
   317                     if (err != KErrNone || text != KProxyName())
       
   318                     {
       
   319                         updateFlags |= TProxyUpdateName;
       
   320                     }
       
   321 
       
   322                     TRAP(err, view->ReadTextL(ProtocolColumn,text));
       
   323                     if (err != KErrNone || text != KProxyProtocol())
       
   324                     {
       
   325                         updateFlags |= TProxyUpdateProtocol;
       
   326                     }
       
   327 
       
   328                     if (updateFlags)
       
   329                     {
       
   330                         TRACE3("updating %S #%d (flags: %08X)",&TableName,id,updateFlags);
       
   331                         LEAVE_IF_ERROR(view->UpdateRecord());
       
   332 
       
   333                         if (updateFlags & TProxyUpdateUseProxy)
       
   334                         {
       
   335                             TRAP(err,view->WriteBoolL(UseProxyColumn,aUseProxy));
       
   336                             ASSERT_SUCCESS(err);
       
   337                         }
       
   338                         if (updateFlags & TProxyUpdateServerName)
       
   339                         {
       
   340                             TRAP(err,view->WriteLongTextL(ServerNameColumn,*aProxyHost));
       
   341                             ASSERT_SUCCESS(err);
       
   342                         }
       
   343                         if (updateFlags & TProxyUpdateName)
       
   344                         {
       
   345                             TRAP(err,view->WriteTextL(NameColumn,KProxyName()));
       
   346                             ASSERT_SUCCESS(err);
       
   347                         }
       
   348                         if (updateFlags & TProxyUpdateProtocol)
       
   349                         {
       
   350                             TRAP(err,view->WriteTextL(ProtocolColumn,KProxyProtocol()));
       
   351                             ASSERT_SUCCESS(err);
       
   352                         }
       
   353                         if (updateFlags & TProxyUpdatePort)
       
   354                         {
       
   355                             TRAP(err,view->WriteUintL(ProxyPortColumn,aProxyPort));
       
   356                             ASSERT_SUCCESS(err);
       
   357                         }
       
   358 
       
   359                         LEAVE_IF_ERROR(view->PutRecordChanges());
       
   360                         databaseUpdated = ETrue;
       
   361                     }
       
   362 
       
   363                     recordFound = ETrue;
       
   364                     continue;
       
   365                 }
       
   366             }
       
   367             TRACE4("  deleting proxy record: %S #%d -> %d,%S",&TableName,id,number,&text);
       
   368             VERIFY_SUCCESS(view->DeleteRecord());
       
   369             databaseUpdated = ETrue;
       
   370         }
       
   371         while (view->GotoNextRecord() == KErrNone);
       
   372     }
       
   373 
       
   374     // Create a new entry if it doesn't exist
       
   375     if (!recordFound)
       
   376     {
       
   377         LEAVE_IF_ERROR(view->InsertRecord(id));
       
   378 
       
   379         const TDesC& host = aProxyHost ? (*aProxyHost) : KNullDesC();
       
   380         TRACE2("created %S #%d",&TableName,id);
       
   381         TRAP(err,view->WriteUintL(ISPColumn,aServiceId));
       
   382         ASSERT_SUCCESS(err);
       
   383         TRAP(err,view->WriteTextL(ServiceTypeColumn,ServiceType));
       
   384         ASSERT_SUCCESS(err);
       
   385         TRAP(err,view->WriteBoolL(UseProxyColumn, aUseProxy));
       
   386         ASSERT_SUCCESS(err);
       
   387         TRAP(err,view->WriteTextL(NameColumn, KProxyName));
       
   388         ASSERT_SUCCESS(err);
       
   389         TRAP(err,view->WriteTextL(ProtocolColumn, KProxyProtocol));
       
   390         ASSERT_SUCCESS(err);
       
   391         TRAP(err,view->WriteUintL(ProxyPortColumn, aProxyPort));
       
   392         ASSERT_SUCCESS(err);
       
   393         TRAP(err,view->WriteLongTextL(ServerNameColumn, host));
       
   394         ASSERT_SUCCESS(err);
       
   395         LEAVE_IF_ERROR(view->PutRecordChanges());
       
   396         databaseUpdated = ETrue;
       
   397     }
       
   398 
       
   399     CleanupStack::PopAndDestroy(view);
       
   400     return databaseUpdated;
       
   401 }
       
   402 
       
   403 // Shortcut for making sure that there's no garbage in the proxy settings table
       
   404 static TBool WsockCheckProxyL(CCommsDatabase* aDb, TUint32 aServiceId)
       
   405 {
       
   406     return WsockCheckProxyL(aDb, aServiceId, EFalse, NULL, KDefaultProxyPort);
       
   407 }
       
   408 
       
   409 // Makes sure our IAP is in the Network table
       
   410 static TBool WsockCheckNetworkL(CCommsDatabase* aDb, TUint32& aNetworkId)
       
   411 {
       
   412     _LIT(KNetworkTable,"Network");
       
   413     const TDesC& TableName = KNetworkTable();
       
   414     TRACE1("examining %S table...",&TableName);
       
   415     CCommsDbTableView* view = aDb->OpenTableLC(TableName);
       
   416 
       
   417     // Column names
       
   418     TPtrC IdColumn(COMMDB_ID);
       
   419     TPtrC NameColumn(COMMDB_NAME);
       
   420 
       
   421     // Walk the table
       
   422     TInt err;
       
   423     TUint32 id = 0;
       
   424     TBool found = EFalse;
       
   425     TBool needCommit = EFalse;
       
   426     if (view->GotoFirstRecord() == KErrNone)
       
   427     {
       
   428         TBuf<KCommsDbSvrMaxFieldLength> text;
       
   429         do
       
   430         {
       
   431             // This one must exist
       
   432             TRAPD(err, view->ReadUintL(IdColumn, id));
       
   433             if (err == KErrNone)
       
   434             {
       
   435                 TRAP(err, view->ReadTextL(NameColumn,text));
       
   436                 TRACE3("  %S #%d -> %S",&TableName,id,&text);
       
   437                 if (err == KErrNone && text == KWinsockAPName)
       
   438                 {
       
   439                     if (!found)
       
   440                     {
       
   441                         found = ETrue;
       
   442                     }
       
   443                     else
       
   444                     {
       
   445                         TRACE1("  deleting record #%d",id);
       
   446                         LEAVE_IF_ERROR(view->DeleteRecord());
       
   447                         needCommit = ETrue;
       
   448                     }
       
   449                 }
       
   450             }
       
   451         }
       
   452         while (view->GotoNextRecord() == KErrNone);
       
   453     }
       
   454 
       
   455     // Create a new entry if it doesn't exist
       
   456     if (!found)
       
   457     {
       
   458         LEAVE_IF_ERROR(view->InsertRecord(id));
       
   459         TRACE2("created %S #%d",&TableName,id);
       
   460         TRAP(err,view->WriteTextL(NameColumn, KWinsockAPName));
       
   461         ASSERT_SUCCESS(err);
       
   462         LEAVE_IF_ERROR(view->PutRecordChanges());
       
   463         needCommit = ETrue;
       
   464     }
       
   465 
       
   466     aNetworkId = id;
       
   467     CleanupStack::PopAndDestroy(view);
       
   468     return needCommit;
       
   469 }
       
   470 
       
   471 // Finds our records in CommDb, creating one if necessary. Returns ETrue
       
   472 // if transaction needs to be commited.
       
   473 static TBool WsockCheckBearerTypeL(CCommsDatabase* aDb, TUint32& aBearerId)
       
   474 {
       
   475     const TDesC& TableName = KWinsockBearerType();
       
   476     TRACE1("examining %S table...",&TableName);
       
   477     CCommsDbTableView* view = aDb->OpenTableLC(TableName);
       
   478 
       
   479     TBuf<KCommsDbSvrMaxFieldLength> agent;
       
   480     agent.Copy(KWinsockAgent);
       
   481     agent.Append(_L(".agt"));
       
   482 
       
   483     // Column names
       
   484     TPtrC IdColumn(COMMDB_ID);
       
   485     TPtrC NameColumn(COMMDB_NAME);
       
   486     TPtrC IfNameColumn(IF_NAME);
       
   487     TPtrC AgentColumn(AGENT_NAME);
       
   488     TPtrC SocketActivityTimeoutColumn(LAST_SOCKET_ACTIVITY_TIMEOUT);
       
   489     TPtrC SessionClosedTimeoutColumn(LAST_SESSION_CLOSED_TIMEOUT);
       
   490     TPtrC SocketClosedTimeoutColumn(LAST_SOCKET_CLOSED_TIMEOUT);
       
   491 
       
   492     // Walk the table
       
   493     TInt err;
       
   494     TBool needCommit = EFalse;
       
   495     if (view->GotoFirstRecord() == KErrNone)
       
   496     {
       
   497         TUint32 number = 0;
       
   498         TBuf<KCommsDbSvrMaxFieldLength> text;
       
   499         do
       
   500         {
       
   501             // This one must exist
       
   502             TUint32 id = 0;
       
   503             TRAPD(err, view->ReadUintL(IdColumn, id));
       
   504             if (err == KErrNone)
       
   505             {
       
   506                 // We detect our record based on the value of the "IfName"
       
   507                 // column, it must point to our interface.
       
   508                 TRAP(err, view->ReadTextL(IfNameColumn,text));
       
   509                 TRACE3("  %S #%d -> %S",&TableName,id,&text);
       
   510                 if (err == KErrNone && text == KWinsockInterface)
       
   511                 {
       
   512                     aBearerId = id;
       
   513                     TUint updateFlags = 0;
       
   514                     TRAP(err, view->ReadTextL(AgentColumn,text));
       
   515                     if (err != KErrNone || text != agent)
       
   516                     {
       
   517                        updateFlags |= TBearerUpdateAgent;
       
   518                     }
       
   519                     TRAP(err, view->ReadUintL(SocketActivityTimeoutColumn,number));
       
   520                     if (err != KErrNone || number != KWinsockSocketActivityTimeout)
       
   521                     {
       
   522                        updateFlags |= TBearerUpdateSocketActivityTimeout;
       
   523                     }
       
   524                     TRAP(err, view->ReadUintL(SessionClosedTimeoutColumn,number));
       
   525                     if (err != KErrNone || number != KWinsockSessionClosedTimeout)
       
   526                     {
       
   527                        updateFlags |= TBearerUpdateSessionClosedTimeout;
       
   528                     }
       
   529                     TRAP(err, view->ReadUintL(SocketClosedTimeoutColumn,number));
       
   530                     if (err != KErrNone || number != KWinsockSocketClosedTimeout)
       
   531                     {
       
   532                        updateFlags |= TBearerUpdateSocketClosedTimeout;
       
   533                     }
       
   534 
       
   535                     if (updateFlags)
       
   536                     {
       
   537                         needCommit = ETrue;
       
   538                         TRACE3("updating %S #%d (flags: %08X)",&TableName,id,updateFlags);
       
   539                         LEAVE_IF_ERROR(view->UpdateRecord());
       
   540 
       
   541                         if (updateFlags & TBearerUpdateAgent)
       
   542                         {
       
   543                             TRAP(err,view->WriteTextL(AgentColumn,agent));
       
   544                             ASSERT_SUCCESS(err);
       
   545                         }
       
   546                         if (updateFlags & TBearerUpdateSocketActivityTimeout)
       
   547                         {
       
   548                             TRAP(err,view->WriteUintL(SocketActivityTimeoutColumn,
       
   549                                 KWinsockSocketActivityTimeout));
       
   550                             ASSERT_SUCCESS(err);
       
   551                         }
       
   552                         if (updateFlags & TBearerUpdateSessionClosedTimeout)
       
   553                         {
       
   554                             TRAP(err,view->WriteUintL(SessionClosedTimeoutColumn,
       
   555                                 KWinsockSessionClosedTimeout));
       
   556                             ASSERT_SUCCESS(err);
       
   557                         }
       
   558                         if (updateFlags & TBearerUpdateSocketClosedTimeout)
       
   559                         {
       
   560                             TRAP(err,view->WriteUintL(SocketClosedTimeoutColumn,
       
   561                                 KWinsockSocketClosedTimeout));
       
   562                             ASSERT_SUCCESS(err);
       
   563                         }
       
   564 
       
   565                         LEAVE_IF_ERROR(view->PutRecordChanges());
       
   566                     }
       
   567 
       
   568                     // Done
       
   569                     CleanupStack::PopAndDestroy(view);
       
   570                     return needCommit;
       
   571                 }
       
   572             }
       
   573         }
       
   574         while (view->GotoNextRecord() == KErrNone);
       
   575     }
       
   576 
       
   577     // Create a new entry
       
   578     LEAVE_IF_ERROR(view->InsertRecord(aBearerId));
       
   579 
       
   580     TRACE2("created %S #%d",&TableName,aBearerId);
       
   581     TRAP(err,view->WriteTextL(NameColumn,KWinsockBearerName));
       
   582     ASSERT_SUCCESS(err);
       
   583     TRAP(err,view->WriteTextL(IfNameColumn,KWinsockInterface));
       
   584     ASSERT_SUCCESS(err);
       
   585     TRAP(err,view->WriteTextL(AgentColumn,agent));
       
   586     ASSERT_SUCCESS(err);
       
   587     TRAP(err,view->WriteUintL(SocketActivityTimeoutColumn, KWinsockSocketClosedTimeout));
       
   588     ASSERT_SUCCESS(err);
       
   589     TRAP(err,view->WriteUintL(SessionClosedTimeoutColumn, KWinsockSessionClosedTimeout));
       
   590     ASSERT_SUCCESS(err);
       
   591     TRAP(err,view->WriteUintL(SocketClosedTimeoutColumn, KWinsockSocketClosedTimeout));
       
   592     ASSERT_SUCCESS(err);
       
   593 
       
   594     // These must be present in the LANBearer table, otherwise
       
   595     // PutRecordChanges fails because these fields are mandatory
       
   596     _LIT(something,"foo");
       
   597     TRAP(err,view->WriteTextL(TPtrC(LAN_BEARER_LDD_NAME),something));
       
   598     TRAP(err,view->WriteTextL(TPtrC(LAN_BEARER_PDD_NAME),something));
       
   599 
       
   600     LEAVE_IF_ERROR(view->PutRecordChanges());
       
   601     CleanupStack::PopAndDestroy(view);
       
   602     return ETrue;
       
   603 }
       
   604 
       
   605 // Finds our records in CommDb, creating one if necessary. Returns ETrue
       
   606 // if transaction needs to be commited.
       
   607 static TBool WsockCheckServiceTypeL(CCommsDatabase* aDb, TUint32& aServiceId)
       
   608 {
       
   609     const TDesC& TableName = KWinsockServiceType();
       
   610     TRACE1("examining %S table...",&TableName);
       
   611     CCommsDbTableView* view = aDb->OpenTableLC(TableName);
       
   612 
       
   613     // We will need the list of networks and the agent ame
       
   614     TBuf<KCommsDbSvrMaxFieldLength> networks;
       
   615     CWinsockProtocolFamily::ProtocolNames(networks);
       
   616 
       
   617     // Column names
       
   618     TPtrC IdColumn(COMMDB_ID);
       
   619     TPtrC NameColumn(COMMDB_NAME);
       
   620     TPtrC APNColumn(GPRS_APN);
       
   621     TPtrC APTypeColumn(GPRS_AP_TYPE);
       
   622     TPtrC NetworksColumn(SERVICE_IF_NETWORKS);
       
   623     TPtrC AuthPromptColumn(ISP_IF_PROMPT_FOR_AUTH);
       
   624 
       
   625     // Walk the table
       
   626     TInt err;
       
   627     if (view->GotoFirstRecord() == KErrNone)
       
   628     {
       
   629         TBuf<KCommsDbSvrMaxFieldLength> text;
       
   630         do
       
   631         {
       
   632             // This one must exist
       
   633             TUint32 id = 0;
       
   634             TRAPD(err, view->ReadUintL(IdColumn, id));
       
   635             if (err == KErrNone)
       
   636             {
       
   637                 TRAP(err, view->ReadTextL(NameColumn,text));
       
   638                 TRACE3("  %S #%d -> %S",&TableName,id,&text);
       
   639                 if (err == KErrNone && text == KWinsockServiceName)
       
   640                 {
       
   641                     // This is our record. Make sure it looks right.
       
   642                     aServiceId = id;
       
   643                     TBool authPrompt = EFalse;
       
   644                     TInt updateFlags = 0;
       
   645                     TRAP(err, view->ReadTextL(NetworksColumn,text));
       
   646                     if (err != KErrNone || text != networks)
       
   647                     {
       
   648                         updateFlags |= TServiceUpdateNetworks;
       
   649                     }
       
   650                     // The following one is not present in the LANService
       
   651                     // table. Ignore it if it's not there.
       
   652                     TRAP(err, view->ReadBoolL(AuthPromptColumn,authPrompt));
       
   653                     if (err == KErrNone && authPrompt)
       
   654                     {
       
   655                         updateFlags |= TServiceUpdateAuthPrompt;
       
   656                     }
       
   657 
       
   658                     // The above statement also applies to APN column
       
   659                     TBuf<KCommsDbSvrMaxFieldLength> text;
       
   660                     TRAP(err, view->ReadTextL(APNColumn,text));
       
   661                     if (err == KErrNone && text != KWinsockAPName)
       
   662                     {
       
   663                         updateFlags |= TServiceUpdateAPN;
       
   664                     }
       
   665 
       
   666 #ifndef WSOCK_LAN_SERVICE
       
   667                     // This one is important. If this number isn't set, our
       
   668                     // access point almost (!) never shows up in the list of
       
   669                     // access points, at least if we use "OutgoingGPRS"
       
   670                     // service type (hence the #ifdef).
       
   671                     TUint32 n = 0;
       
   672                     TRAP(err, view->ReadUintL(APTypeColumn, n));
       
   673                     if (err != KErrNone || n != KWinsockAPType)
       
   674                     {
       
   675                         updateFlags |= TServiceUpdateAPType;
       
   676                     }
       
   677 #endif // !WSOCK_LAN_SERVICE
       
   678 
       
   679                     TBool update = (updateFlags != 0);
       
   680                     if (update)
       
   681                     {
       
   682                         TRACE3("updating %S #%d (flags: %08X)",&TableName,id,updateFlags);
       
   683                         LEAVE_IF_ERROR(view->UpdateRecord());
       
   684 
       
   685                         if (updateFlags & TServiceUpdateNetworks)
       
   686                         {
       
   687                             TRAP(err,view->WriteTextL(NetworksColumn,networks));
       
   688                             ASSERT_SUCCESS(err);
       
   689                         }
       
   690                         if (updateFlags & TServiceUpdateAuthPrompt)
       
   691                         {
       
   692                             TRAP(err,view->WriteBoolL(AuthPromptColumn,EFalse));
       
   693                             ASSERT_SUCCESS(err);
       
   694                         }
       
   695                         if (updateFlags & TServiceUpdateAPN)
       
   696                         {
       
   697                             TRAP(err,view->WriteTextL(APNColumn,KWinsockAPName));
       
   698                             ASSERT_SUCCESS(err);
       
   699                         }
       
   700                         if (updateFlags & TServiceUpdateAPType)
       
   701                         {
       
   702                             TRAP(err,view->WriteUintL(APTypeColumn,KWinsockAPType));
       
   703                             ASSERT_SUCCESS(err);
       
   704                         }
       
   705 
       
   706                         LEAVE_IF_ERROR(view->PutRecordChanges());
       
   707                     }
       
   708 
       
   709                     // Done
       
   710                     CleanupStack::PopAndDestroy(view);
       
   711                     return update;
       
   712                 }
       
   713             }
       
   714         }
       
   715         while (view->GotoNextRecord() == KErrNone);
       
   716 
       
   717         TRACE1("  did not find %S",&KWinsockServiceName);
       
   718     }
       
   719 
       
   720     // Create a new entry
       
   721     LEAVE_IF_ERROR(view->InsertRecord(aServiceId));
       
   722 
       
   723     TRACE2("created %S #%d",&TableName,aServiceId);
       
   724     TRAP(err,view->WriteTextL(NameColumn,KWinsockServiceName));
       
   725     ASSERT_SUCCESS(err);
       
   726     TRAP(err,view->WriteTextL(NetworksColumn,networks));
       
   727     ASSERT_SUCCESS(err);
       
   728 
       
   729     // Ignore the errors below - LANService table does not have these entries.
       
   730     // Only OutgoingGPRS does. But we try anyway, in case if Symbian unifies
       
   731     // the formats of the service tables in CommDb.
       
   732     TRAP(err,view->WriteBoolL(AuthPromptColumn,EFalse));
       
   733     TRAP(err,view->WriteTextL(APNColumn,KWinsockAPName));
       
   734     TRAP(err,view->WriteUintL(APTypeColumn,KWinsockAPType));
       
   735     TRAP(err,view->WriteUintL(TPtrC(GPRS_PDP_TYPE),KWinsockPdpType));
       
   736 
       
   737     // We don't use these fields, but they are mandatory.
       
   738     TRAP(err,view->WriteBoolL(TPtrC(SERVICE_IP_ADDR_FROM_SERVER),EFalse));
       
   739     ASSERT_SUCCESS(err);
       
   740     TRAP(err,view->WriteBoolL(TPtrC(SERVICE_IP_DNS_ADDR_FROM_SERVER),EFalse));
       
   741     ASSERT_SUCCESS(err);
       
   742 
       
   743     LEAVE_IF_ERROR(view->PutRecordChanges());
       
   744     CleanupStack::PopAndDestroy(view);
       
   745     return ETrue;
       
   746 }
       
   747 
       
   748 // Finds our record in WAPAccessPoint table, creating one if necessary.
       
   749 // Returns ETrue if transaction needs to be commited.
       
   750 static TBool WsockCheckWapAccessPointL(CCommsDatabase* aDb, TUint32& aWapApId)
       
   751 {
       
   752     TPtrC TableName(WAP_ACCESS_POINT);
       
   753     TRACE1("examining %S table...",&TableName);
       
   754     CCommsDbTableView* view = aDb->OpenTableLC(TableName);
       
   755 
       
   756     // Column names
       
   757     TPtrC IdColumn(COMMDB_ID);
       
   758     TPtrC NameColumn(COMMDB_NAME);
       
   759     TPtrC CurrentBearerColumn(WAP_CURRENT_BEARER);
       
   760 
       
   761     // Walk the table
       
   762     TInt err;
       
   763     TUint32 id = 0;
       
   764     TBool found = EFalse;
       
   765     TBool commit = EFalse;
       
   766     if (view->GotoFirstRecord() == KErrNone)
       
   767     {
       
   768         TBuf<KCommsDbSvrMaxFieldLength> text;
       
   769         do
       
   770         {
       
   771             // This one must exist
       
   772             TRAPD(err, view->ReadUintL(IdColumn, id));
       
   773             if (err == KErrNone)
       
   774             {
       
   775                 TRAP(err, view->ReadTextL(NameColumn,text));
       
   776                 TRACE3("  %S #%d -> %S",&TableName,id,&text);
       
   777                 if (err == KErrNone && text == KWinsockAPName)
       
   778                 {
       
   779                     if (!found)
       
   780                     {
       
   781                         aWapApId = id;
       
   782                         found = ETrue;
       
   783                         TRAP(err, view->ReadTextL(CurrentBearerColumn,text));
       
   784                         if (err != KErrNone || text != KWinsockWapBearer)
       
   785                         {
       
   786                             TRACE1("  updating \"%S\"",&CurrentBearerColumn);
       
   787                             LEAVE_IF_ERROR(view->UpdateRecord());
       
   788                             TRAP(err,view->WriteTextL(CurrentBearerColumn,
       
   789                                                       KWinsockWapBearer));
       
   790                             ASSERT_SUCCESS(err);
       
   791                             LEAVE_IF_ERROR(view->PutRecordChanges());
       
   792                             commit = ETrue;
       
   793                         }
       
   794                     }
       
   795                     else
       
   796                     {
       
   797                         TRACE1("  deleting record #%d",id);
       
   798                         LEAVE_IF_ERROR(view->DeleteRecord());
       
   799                         commit = ETrue;
       
   800                     }
       
   801                 }
       
   802             }
       
   803         }
       
   804         while (view->GotoNextRecord() == KErrNone);
       
   805     }
       
   806 
       
   807     // Create a new entry if it doesn't exist
       
   808     if (!found)
       
   809     {
       
   810         LEAVE_IF_ERROR(view->InsertRecord(id));
       
   811         TRACE2("created %S #%d",&TableName,id);
       
   812         TRAP(err,view->WriteTextL(NameColumn, KWinsockAPName));
       
   813         ASSERT_SUCCESS(err);
       
   814         TRAP(err,view->WriteTextL(CurrentBearerColumn, KWinsockWapBearer));
       
   815         ASSERT_SUCCESS(err);
       
   816         LEAVE_IF_ERROR(view->PutRecordChanges());
       
   817         aWapApId = id;
       
   818         commit = ETrue;
       
   819     }
       
   820 
       
   821     CleanupStack::PopAndDestroy(view);
       
   822     return commit;
       
   823 }
       
   824 
       
   825 // Finds our records in WAPIPBearer table, creating one if necessary.
       
   826 // Returns ETrue if transaction needs to be commited.
       
   827 static TBool WsockCheckWapIpBearerL(CCommsDatabase* aDb,
       
   828                                     TUint32 aWapApId,
       
   829                                     TUint32 aIapId)
       
   830 {
       
   831     const TDesC& TableName = KWinsockWapBearer();
       
   832     TRACE1("examining %S table...",&TableName);
       
   833     CCommsDbTableView* view = aDb->OpenTableLC(TableName);
       
   834 
       
   835     // Column names
       
   836     TPtrC IdColumn(COMMDB_ID);
       
   837     TPtrC NameColumn(COMMDB_NAME);
       
   838     TPtrC AccessPointIdColumn(WAP_ACCESS_POINT_ID);
       
   839     TPtrC IAPColumn(WAP_IAP);
       
   840     TPtrC ProxyPortColumn(WAP_PROXY_PORT);
       
   841     TPtrC WspOptionColumn(WAP_WSP_OPTION);
       
   842     TPtrC SecurityColumn(WAP_SECURITY);
       
   843     TPtrC GatewayAddressColumn(WAP_GATEWAY_ADDRESS);
       
   844     TPtrC ProxyLoginNameColumn(WAP_PROXY_LOGIN_NAME);
       
   845     TPtrC ProxyLoginPassColumn(WAP_PROXY_LOGIN_PASS);
       
   846 
       
   847     // Walk the table
       
   848     TInt err;
       
   849     TUint32 id = 0;
       
   850     if (view->GotoFirstRecord() == KErrNone)
       
   851     {
       
   852         do
       
   853         {
       
   854             // This one must exist
       
   855             TRAPD(err, view->ReadUintL(IdColumn, id));
       
   856             if (err == KErrNone)
       
   857             {
       
   858                 // We detect our record based on WAP access point id
       
   859                 TUint32 wap = 0;
       
   860                 TRAPD(err, view->ReadUintL(AccessPointIdColumn, wap));
       
   861                 TRACE3("  %S #%d -> %d", &TableName, id, wap);
       
   862                 if (err == KErrNone && wap == aWapApId)
       
   863                 {
       
   864                     TUint32 n = 0;
       
   865                     TBool b = EFalse;
       
   866                     TUint updateFlags = 0;
       
   867                     TBuf<KCommsDbSvrMaxFieldLength> text;
       
   868                     TBool commit = EFalse;
       
   869 
       
   870                     TRAPD(err, view->ReadUintL(IAPColumn, n));
       
   871                     if (err != KErrNone || n != aIapId)
       
   872                     {
       
   873                         updateFlags |= TWapIpBearerUpdateIAP;
       
   874                     }
       
   875                     TRAP(err, view->ReadUintL(WspOptionColumn, n));
       
   876                     if (err != KErrNone)
       
   877                     {
       
   878                         updateFlags |= TWapIpBearerUpdateWspOption;
       
   879                     }
       
   880                     TRAP(err, view->ReadUintL(ProxyPortColumn, n));
       
   881                     if (err != KErrNone)
       
   882                     {
       
   883                         updateFlags |= TWapIpBearerUpdateProxyPort;
       
   884                     }
       
   885                     TRAP(err, view->ReadBoolL(SecurityColumn, b));
       
   886                     if (err != KErrNone)
       
   887                     {
       
   888                         updateFlags |= TWapIpBearerUpdateSecurity;
       
   889                     }
       
   890                     TRAP(err, view->ReadTextL(GatewayAddressColumn,text));
       
   891                     if (err != KErrNone || text != KWinsockGatewayAddress)
       
   892                     {
       
   893                         updateFlags |= TWapIpBearerUpdateGatewayAddress;
       
   894                     }
       
   895                     TRAP(err, view->ReadTextL(ProxyLoginNameColumn,text));
       
   896                     if (err != KErrNone)
       
   897                     {
       
   898                         updateFlags |= TWapIpBearerUpdateProxyLoginName;
       
   899                     }
       
   900                     TRAP(err, view->ReadTextL(ProxyLoginPassColumn,text));
       
   901                     if (err != KErrNone)
       
   902                     {
       
   903                         updateFlags |= TWapIpBearerUpdateProxyLoginPass;
       
   904                     }
       
   905 
       
   906                     TBool update = (updateFlags != 0);
       
   907                     if (updateFlags)
       
   908                     {
       
   909                         // Update the existing table
       
   910                         TRACE3("updating %S #%d (flags: %08X)",&TableName,id,updateFlags);
       
   911                         LEAVE_IF_ERROR(view->UpdateRecord());
       
   912                         if (updateFlags & TWapIpBearerUpdateIAP)
       
   913                         {
       
   914                             TRACE1("  updating \"%S\"",&IAPColumn);
       
   915                             TRAP(err,view->WriteUintL(IAPColumn, aIapId));
       
   916                             ASSERT_SUCCESS(err);
       
   917                         }
       
   918                         if (updateFlags & TWapIpBearerUpdateWspOption)
       
   919                         {
       
   920                             TRACE1("  updating \"%S\"",&WspOptionColumn);
       
   921                             TRAP(err,view->WriteUintL(WspOptionColumn,0));
       
   922                             ASSERT_SUCCESS(err);
       
   923                         }
       
   924                         if (updateFlags & TWapIpBearerUpdateProxyPort)
       
   925                         {
       
   926                             TRACE1("  updating \"%S\"",&ProxyPortColumn);
       
   927                             TRAP(err,view->WriteUintL(ProxyPortColumn,0));
       
   928                             ASSERT_SUCCESS(err);
       
   929                         }
       
   930                         if (updateFlags & TWapIpBearerUpdateSecurity)
       
   931                         {
       
   932                             TRACE1("  updating \"%S\"",&SecurityColumn);
       
   933                             TRAP(err,view->WriteBoolL(SecurityColumn,EFalse));
       
   934                             ASSERT_SUCCESS(err);
       
   935                         }
       
   936                         if (updateFlags & TWapIpBearerUpdateGatewayAddress)
       
   937                         {
       
   938                             TRACE1("  updating \"%S\"",&GatewayAddressColumn);
       
   939                             TRAP(err,view->WriteTextL(GatewayAddressColumn,
       
   940                                                       KWinsockGatewayAddress));
       
   941                             ASSERT_SUCCESS(err);
       
   942                         }
       
   943                         if (updateFlags & TWapIpBearerUpdateProxyLoginName)
       
   944                         {
       
   945                             TRACE1("  updating \"%S\"",&ProxyLoginNameColumn);
       
   946                             TRAP(err,view->WriteTextL(ProxyLoginNameColumn,
       
   947                                                       KNullDesC));
       
   948                             ASSERT_SUCCESS(err);
       
   949                         }
       
   950                         if (updateFlags & TWapIpBearerUpdateProxyLoginPass)
       
   951                         {
       
   952                             TRACE1("  updating \"%S\"",&ProxyLoginPassColumn);
       
   953                             TRAP(err,view->WriteTextL(ProxyLoginPassColumn,
       
   954                                                       KNullDesC));
       
   955                             ASSERT_SUCCESS(err);
       
   956                         }
       
   957                         LEAVE_IF_ERROR(view->PutRecordChanges());
       
   958                         commit = ETrue;
       
   959                     }
       
   960 
       
   961                     // Done
       
   962                     CleanupStack::PopAndDestroy(view);
       
   963                     return commit;
       
   964                 }
       
   965             }
       
   966         }
       
   967         while (view->GotoNextRecord() == KErrNone);
       
   968     }
       
   969 
       
   970     // Create a new entry
       
   971     LEAVE_IF_ERROR(view->InsertRecord(id));
       
   972 
       
   973     TRACE2("created %S #%d",&TableName,id);
       
   974     TRAP(err,view->WriteTextL(NameColumn,KWinsockBearerName));
       
   975     ASSERT_SUCCESS(err);
       
   976     TRAP(err,view->WriteUintL(AccessPointIdColumn, aWapApId));
       
   977     ASSERT_SUCCESS(err);
       
   978     TRAP(err,view->WriteUintL(IAPColumn, aIapId));
       
   979     ASSERT_SUCCESS(err);
       
   980     TRAP(err,view->WriteUintL(ProxyPortColumn, 0));
       
   981     ASSERT_SUCCESS(err);
       
   982     TRAP(err,view->WriteUintL(WspOptionColumn, 0));
       
   983     ASSERT_SUCCESS(err);
       
   984     TRAP(err,view->WriteBoolL(SecurityColumn, EFalse));
       
   985     ASSERT_SUCCESS(err);
       
   986     TRAP(err,view->WriteTextL(GatewayAddressColumn,KWinsockGatewayAddress));
       
   987     ASSERT_SUCCESS(err);
       
   988     TRAP(err,view->WriteTextL(ProxyLoginNameColumn,KNullDesC));
       
   989     ASSERT_SUCCESS(err);
       
   990     TRAP(err,view->WriteTextL(ProxyLoginPassColumn,KNullDesC));
       
   991     ASSERT_SUCCESS(err);
       
   992 
       
   993     LEAVE_IF_ERROR(view->PutRecordChanges());
       
   994     CleanupStack::PopAndDestroy(view);
       
   995     return ETrue;
       
   996 }
       
   997 
       
   998 static TBool WsockCheckConnPreferencesL(CCommsDatabase* aDb, TUint32 aIapId)
       
   999 {
       
  1000     TRACE("examining Connection Preferences...");
       
  1001     CCommsDbConnectionPrefTableView *view = aDb->OpenConnectionPrefTableLC();
       
  1002 
       
  1003     CCommsDbConnectionPrefTableView::TCommDbIapConnectionPref myPrefs;
       
  1004     myPrefs.iBearer.iIapId      = aIapId;
       
  1005     myPrefs.iDirection          = ECommDbConnectionDirectionOutgoing;
       
  1006     myPrefs.iDialogPref         = ECommDbDialogPrefPrompt;
       
  1007     myPrefs.iRanking            = 1;
       
  1008     myPrefs.iBearer.iBearerSet  = KCommDbBearerCSD
       
  1009                                 | KCommDbBearerWcdma
       
  1010                                 | KCommDbBearerLAN
       
  1011                                 | KCommDbBearerVirtual;
       
  1012     // Walk the table
       
  1013     TInt err;
       
  1014     if (view->GotoFirstRecord() == KErrNone)
       
  1015     {
       
  1016         do
       
  1017         {
       
  1018             CCommsDbConnectionPrefTableView::TCommDbIapConnectionPref prefs;
       
  1019             TRAP(err, view->ReadConnectionPreferenceL(prefs));
       
  1020             if (err == KErrNone)
       
  1021             {
       
  1022                 // check, whether this is our record
       
  1023                 if (prefs.iBearer.iIapId == myPrefs.iBearer.iIapId)
       
  1024                 {
       
  1025                     TBool update = EFalse;
       
  1026 
       
  1027                     // This is our record. Make sure it looks right.
       
  1028                     if (prefs.iDialogPref != myPrefs.iDialogPref)
       
  1029                     {
       
  1030                         TRACE("updating DialogPref");
       
  1031                         view->UpdateDialogPrefL(myPrefs.iDialogPref);
       
  1032                         update = ETrue;
       
  1033                     }
       
  1034                     if (prefs.iRanking != myPrefs.iRanking)
       
  1035                     {
       
  1036                         TRACE("updating Ranking");
       
  1037                         view->ChangeConnectionPreferenceRankL(myPrefs.iRanking);
       
  1038                         update = ETrue;
       
  1039                     }
       
  1040                     if (prefs.iBearer.iBearerSet != myPrefs.iBearer.iBearerSet)
       
  1041                     {
       
  1042                         TRACE("updating Bearer");
       
  1043                         view->UpdateBearerL(myPrefs.iBearer);
       
  1044                         update = ETrue;
       
  1045                     }
       
  1046                     CleanupStack::PopAndDestroy(view);
       
  1047                     return update;
       
  1048                 }
       
  1049             }
       
  1050         }
       
  1051         while (view->GotoNextRecord() == KErrNone);
       
  1052     }
       
  1053 
       
  1054     // Create a new entry
       
  1055     view->InsertConnectionPreferenceL(myPrefs);
       
  1056     TRACE("created connection preferences");
       
  1057     CleanupStack::PopAndDestroy(view);
       
  1058     return ETrue;
       
  1059 }
       
  1060 
       
  1061 // Finds our records in CommDb, creating one if necessary.
       
  1062 void WsockCheckCommDbL(TUint32& aIapId,
       
  1063                        TUint32& aNetworkId,
       
  1064                        TUint32& aServiceId,
       
  1065                        TUint32& aBearerId)
       
  1066 {
       
  1067     TRACE("checking CommDb");
       
  1068     CCommsDatabase* db = CCommsDatabase::NewL();
       
  1069     CleanupStack::PushL(db);
       
  1070     WsockBeginCommDbTransactionLC(db);
       
  1071     TBool commit = EFalse;
       
  1072     TUint32 number = 0;
       
  1073     TInt err;
       
  1074 
       
  1075     // This must be 2
       
  1076     TPtrC ConnectionAttempts(CONNECTION_ATTEMPTS);
       
  1077     TRAP(err, db->GetGlobalSettingL(ConnectionAttempts, number));
       
  1078     if (err != KErrNone || number < 2)
       
  1079     {
       
  1080         TRACE1("Resetting ConnectionAttempts (%d) to 2",number);
       
  1081         TRAP(err, db->SetGlobalSettingL(ConnectionAttempts, 2));
       
  1082         ASSERT_SUCCESS(err);
       
  1083         commit = ETrue;
       
  1084     }
       
  1085 
       
  1086     // Not sure if we need this check...
       
  1087     _LIT(KTsy, "PHONETSY");
       
  1088     TFileName tsy;
       
  1089     TPtrC BearerAvailabilityCheckTsy(BEARER_AVAILABILITY_CHECK_TSY);
       
  1090     TRAP(err, db->GetGlobalSettingL(BearerAvailabilityCheckTsy, tsy));
       
  1091     if (err != KErrNone || tsy.CompareF(KTsy))
       
  1092     {
       
  1093         TRACE1("Updating BearerAvailabilityCheckTSY (%S)",&tsy);
       
  1094         TRAP(err, db->SetGlobalSettingL(BearerAvailabilityCheckTsy, KTsy));
       
  1095         ASSERT_SUCCESS(err);
       
  1096         commit = ETrue;
       
  1097     }
       
  1098 
       
  1099     // Check a few other things
       
  1100     if (WsockCheckServiceTypeL(db, aServiceId)) commit = ETrue;
       
  1101     if (WsockCheckBearerTypeL(db, aBearerId)) commit = ETrue;
       
  1102     if (WsockCheckNetworkL(db, aNetworkId)) commit = ETrue;
       
  1103 
       
  1104     // Initialize descriptors
       
  1105     TPtrC TableName(IAP);
       
  1106     TPtrC IdColumn(COMMDB_ID);
       
  1107     TPtrC NameColumn(COMMDB_NAME);
       
  1108     TPtrC IAPNetworkColumn(IAP_NETWORK);
       
  1109     TPtrC IAPServiceColumn(IAP_SERVICE);
       
  1110     TPtrC IAPServiceTypeColumn(IAP_SERVICE_TYPE);
       
  1111     TPtrC IAPBearerColumn(IAP_BEARER);
       
  1112     TPtrC IAPBearerTypeColumn(IAP_BEARER_TYPE);
       
  1113 
       
  1114     // Open the IAP table
       
  1115     CCommsDbTableView* view = db->OpenTableLC(TableName);
       
  1116 
       
  1117     // Find our access point
       
  1118     TRACE("examining APs...");
       
  1119     if (view->GotoFirstRecord() == KErrNone)
       
  1120     {
       
  1121         TBuf<KCommsDbSvrMaxFieldLength> text;
       
  1122         do
       
  1123         {
       
  1124             // This one must exist
       
  1125             TUint32 id = 0;
       
  1126             TRAP(err, view->ReadUintL(IdColumn, id));
       
  1127             if (err == KErrNone)
       
  1128             {
       
  1129                 TRAP(err, view->ReadTextL(NameColumn,text));
       
  1130                 TRACE3("  %S #%d -> %S",&TableName,id,&text);
       
  1131                 if (err == KErrNone && text == KWinsockAPName)
       
  1132                 {
       
  1133                     aIapId = id;
       
  1134                     TUint updateFlags = 0;
       
  1135                     TRAP(err, view->ReadUintL(IAPServiceColumn,number));
       
  1136                     if (err != KErrNone || number != aServiceId)
       
  1137                     {
       
  1138                        updateFlags |= TIAPUpdateService;
       
  1139                     }
       
  1140                     TRAP(err, view->ReadTextL(IAPServiceTypeColumn,text));
       
  1141                     if (err == KErrNone && text != KWinsockServiceType)
       
  1142                     {
       
  1143                         updateFlags |= TIAPUpdateServiceType;
       
  1144                     }
       
  1145                     TRAP(err, view->ReadUintL(IAPBearerColumn,number));
       
  1146                     if (err != KErrNone || number != aBearerId)
       
  1147                     {
       
  1148                        updateFlags |= TIAPUpdateBearer;
       
  1149                     }
       
  1150                     TRAP(err, view->ReadTextL(IAPBearerTypeColumn,text));
       
  1151                     if (err == KErrNone && text != KWinsockBearerType)
       
  1152                     {
       
  1153                         updateFlags |= TIAPUpdateBearerType;
       
  1154                     }
       
  1155                     TRAP(err, view->ReadUintL(IAPNetworkColumn,number));
       
  1156                     if (err != KErrNone || number != aNetworkId)
       
  1157                     {
       
  1158                        updateFlags |= TIAPUpdateNetwork;
       
  1159                     }
       
  1160 
       
  1161                     if (updateFlags)
       
  1162                     {
       
  1163                         // Update the existing table
       
  1164                         TRACE2("updating AP \"%S\" (flags: %08X)",&KWinsockAPName(), updateFlags);
       
  1165                         LEAVE_IF_ERROR(view->UpdateRecord());
       
  1166 
       
  1167                         if (updateFlags & TIAPUpdateService)
       
  1168                         {
       
  1169                             TRACE2("  updating \"%S\": %u",&IAPServiceColumn, aServiceId);
       
  1170                             TRAP(err,view->WriteUintL(IAPServiceColumn,aServiceId));
       
  1171                             ASSERT_SUCCESS(err);
       
  1172                         }
       
  1173                         if (updateFlags & TIAPUpdateServiceType)
       
  1174                         {
       
  1175                             TRACE2("  updating \"%S\": %S",&IAPServiceTypeColumn, &KWinsockServiceType);
       
  1176                             TRAP(err,view->WriteTextL(IAPServiceTypeColumn,KWinsockServiceType));
       
  1177                             ASSERT_SUCCESS(err);
       
  1178                         }
       
  1179                         if (updateFlags & TIAPUpdateBearer)
       
  1180                         {
       
  1181                             TRACE2("  updating \"%S\": %u",&IAPServiceTypeColumn, aBearerId);
       
  1182                             TRAP(err,view->WriteUintL(IAPBearerColumn,aBearerId));
       
  1183                             ASSERT_SUCCESS(err);
       
  1184                         }
       
  1185                         if (updateFlags & TIAPUpdateBearerType)
       
  1186                         {
       
  1187                             TRACE2("  updating \"%S\": %S",&IAPBearerTypeColumn, &KWinsockBearerType);
       
  1188                             TRAP(err,view->WriteTextL(IAPBearerTypeColumn,KWinsockBearerType));
       
  1189                             ASSERT_SUCCESS(err);
       
  1190                         }
       
  1191                         if (updateFlags & TIAPUpdateNetwork)
       
  1192                         {
       
  1193                             TRACE2("  updating \"%S\": %u",&IAPNetworkColumn, aNetworkId);
       
  1194                             TRAP(err,view->WriteUintL(IAPNetworkColumn,aNetworkId));
       
  1195                             ASSERT_SUCCESS(err);
       
  1196                         }
       
  1197 
       
  1198                         LEAVE_IF_ERROR(view->PutRecordChanges());
       
  1199                         commit = ETrue;
       
  1200                     }
       
  1201 
       
  1202                     TUint32 wap = 0;
       
  1203                     if (WsockCheckWapAccessPointL(db,wap)) commit = ETrue;
       
  1204                     if (WsockCheckWapIpBearerL(db,wap,aIapId)) commit = ETrue;
       
  1205                     if (WsockCheckConnPreferencesL(db, aIapId)) commit = ETrue;
       
  1206                     if (commit)
       
  1207                     {
       
  1208                         TRACE("commit CommDb transaction");
       
  1209                         LEAVE_IF_ERROR(db->CommitTransaction());
       
  1210                     }
       
  1211 
       
  1212                     // Done
       
  1213                     CleanupStack::PopAndDestroy(view);
       
  1214                     CleanupStack::Pop(); // WsockRollbackOnLeave
       
  1215                     CleanupStack::PopAndDestroy(db);
       
  1216 
       
  1217                     TRACE4("selected AP=%d, network=%d, service=%d, bearer=%d",
       
  1218                         aIapId,aNetworkId,aServiceId,aBearerId);
       
  1219                     return;
       
  1220                 }
       
  1221             }
       
  1222         }
       
  1223         while (view->GotoNextRecord() == KErrNone);
       
  1224     }
       
  1225 
       
  1226     // Find any valid location id
       
  1227     TUint32 locationId = 1;
       
  1228     CCommsDbTableView* locationView = db->OpenTableLC(TPtrC(LOCATION));
       
  1229     if (locationView->GotoFirstRecord() == KErrNone)
       
  1230     {
       
  1231         TRAPD(err, locationView->ReadUintL(IdColumn, locationId));
       
  1232     }
       
  1233     CleanupStack::PopAndDestroy(locationView);
       
  1234 
       
  1235     // Create new IAP entry
       
  1236     err = view->InsertRecord(aIapId);
       
  1237     ASSERT_SUCCESS(err);
       
  1238 
       
  1239     TRACE1("created AP #%d",aIapId);
       
  1240     TRAP(err,view->WriteTextL(NameColumn,KWinsockAPName));
       
  1241     ASSERT_SUCCESS(err);
       
  1242     TRAP(err,view->WriteUintL(IAPServiceColumn,aServiceId));
       
  1243     ASSERT_SUCCESS(err);
       
  1244     TRAP(err,view->WriteTextL(IAPServiceTypeColumn,KWinsockServiceType));
       
  1245     ASSERT_SUCCESS(err);
       
  1246     TRAP(err,view->WriteUintL(IAPBearerColumn,aBearerId));
       
  1247     ASSERT_SUCCESS(err);
       
  1248     TRAP(err,view->WriteTextL(IAPBearerTypeColumn,KWinsockBearerType));
       
  1249     ASSERT_SUCCESS(err);
       
  1250     TRAP(err,view->WriteUintL(IAPNetworkColumn,aNetworkId));
       
  1251     ASSERT_SUCCESS(err);
       
  1252 
       
  1253     // These must be present in the LANBearer table, otherwise
       
  1254     // PutRecordChanges fails because these fields are mandatory
       
  1255     _LIT(something,"foo");
       
  1256     TRAP(err,view->WriteUintL(TPtrC(IAP_NETWORK_WEIGHTING),0));
       
  1257     ASSERT_SUCCESS(err);
       
  1258     TRAP(err,view->WriteUintL(TPtrC(IAP_LOCATION),locationId));
       
  1259     ASSERT_SUCCESS(err);
       
  1260 
       
  1261     LEAVE_IF_ERROR(view->PutRecordChanges());
       
  1262     CleanupStack::PopAndDestroy(view);
       
  1263     CleanupStack::Pop(); // WsockRollbackOnLeave
       
  1264 
       
  1265     TUint32 wap = 0;
       
  1266     WsockCheckWapAccessPointL(db, wap);
       
  1267     WsockCheckWapIpBearerL(db, wap, aIapId);
       
  1268     WsockCheckConnPreferencesL(db, aIapId);
       
  1269 
       
  1270     TRACE("commit CommDb transaction");
       
  1271     LEAVE_IF_ERROR(db->CommitTransaction());
       
  1272     CleanupStack::PopAndDestroy(db);
       
  1273     TRACE4("selected AP=%d, network=%d, service=%d, bearer=%d",
       
  1274         aIapId,aNetworkId,aServiceId,aBearerId);
       
  1275 }
       
  1276 
       
  1277 // Creating necessary entries in CommDB if necessary.
       
  1278 static TInt WsockCheckCommDb()
       
  1279 {
       
  1280     TUint32 apId, apNetwork, apService, apBearer;
       
  1281 
       
  1282     // Make sure Winsock is initialized
       
  1283     static TBool initWinsock = ETrue;
       
  1284     if (initWinsock) {
       
  1285         WSADATA wsaData;
       
  1286         TRACE("initializing Winsock");
       
  1287         WSAStartup(MAKEWORD(1,1),&wsaData);
       
  1288         initWinsock = EFalse;
       
  1289     }
       
  1290 
       
  1291     WsockLock lock;
       
  1292     lock.Lock();
       
  1293     TRAPD(err, WsockCheckCommDbL(apId, apNetwork, apService, apBearer));
       
  1294     lock.Unlock();
       
  1295 
       
  1296     if (err == KErrNone)
       
  1297     {
       
  1298         TRACE("CommDB check successful");
       
  1299     }
       
  1300     else
       
  1301     {
       
  1302         TRACE1("CommDB check failed, err %d",err);
       
  1303     }
       
  1304     return err;
       
  1305 }
       
  1306 
       
  1307 // Deletes Wsock access points
       
  1308 static TBool WsockDeleteApsL(CCommsDatabase* aDb)
       
  1309 {
       
  1310     TBool needCommit = EFalse;
       
  1311 
       
  1312     // Initialize descriptors
       
  1313     TPtrC TableName(IAP);
       
  1314     TPtrC IdColumn(COMMDB_ID);
       
  1315     TPtrC NameColumn(COMMDB_NAME);
       
  1316 
       
  1317     // Open the IAP table
       
  1318     CCommsDbTableView* view = aDb->OpenTableLC(TableName);
       
  1319 
       
  1320     // Find our access points
       
  1321     TRACE("looking for APs to delete...");
       
  1322     if (view->GotoFirstRecord() == KErrNone)
       
  1323     {
       
  1324         TUint32 number = 0;
       
  1325         TBuf<KCommsDbSvrMaxFieldLength> text;
       
  1326         do
       
  1327         {
       
  1328             // This one must exist
       
  1329             TUint32 id = 0;
       
  1330             TRAPD(err, view->ReadUintL(IdColumn, id));
       
  1331             if (err == KErrNone)
       
  1332             {
       
  1333                 TRAP(err, view->ReadTextL(NameColumn,text));
       
  1334                 TRACE3("  %S #%d -> %S",&TableName,id,&text);
       
  1335                 if (err == KErrNone && text == KWinsockAPName)
       
  1336                 {
       
  1337                     TRACE1("deleting AP #%d",id);
       
  1338                     LEAVE_IF_ERROR(view->DeleteRecord());
       
  1339                     needCommit = ETrue;
       
  1340                 }
       
  1341             }
       
  1342         }
       
  1343         while (view->GotoNextRecord() == KErrNone);
       
  1344     }
       
  1345 
       
  1346     CleanupStack::PopAndDestroy(view);
       
  1347     return needCommit;
       
  1348 }
       
  1349 
       
  1350 // Configures wsock settings, leaves on failure
       
  1351 static void WsockSetConfigL(TBool aUseWsock, TBool aUseProxy,
       
  1352                             const TDesC* aHost, TUint aPort)
       
  1353 {
       
  1354     // Synchronize access to the database
       
  1355     WsockLock lock;
       
  1356     lock.LockLC();
       
  1357 
       
  1358     // Figure out the service id - we will need it
       
  1359     CCommsDatabase* db = CCommsDatabase::NewL();
       
  1360     CleanupStack::PushL(db);
       
  1361     WsockBeginCommDbTransactionLC(db);
       
  1362     TUint32 serviceId;
       
  1363     TBool commit = WsockCheckServiceTypeL(db, serviceId);
       
  1364 
       
  1365     // Now that we know the service id, we can update the proxy settings
       
  1366     if (WsockCheckProxyL(db,serviceId,aUseProxy,aHost,aPort)) commit = ETrue;
       
  1367     if (!aUseWsock && WsockDeleteApsL(db)) commit = ETrue;
       
  1368     if (commit)
       
  1369     {
       
  1370         TRACE("commit CommDb transaction");
       
  1371         LEAVE_IF_ERROR(db->CommitTransaction());
       
  1372     }
       
  1373     CleanupStack::Pop(); // WsockRollbackOnLeave
       
  1374     CleanupStack::PopAndDestroy(db);
       
  1375 
       
  1376     if (aUseWsock)
       
  1377     {
       
  1378         // Final touch
       
  1379         TUint32 apId, networkId, bearerId;
       
  1380         TRAPD(err, WsockCheckCommDbL(apId, networkId, serviceId, bearerId));
       
  1381     }
       
  1382 
       
  1383     CleanupStack::PopAndDestroy(); // WsockLock::UnlockOnLeave
       
  1384 }
       
  1385 
       
  1386 // Reads Wsock settings, leaves on failure
       
  1387 static void WsockQueryConfigL(TBool& aUseProxy, HBufC*& aHost, TUint& aPort)
       
  1388 {
       
  1389     // Default values
       
  1390     aUseProxy = EFalse;
       
  1391     aHost = NULL;
       
  1392     aPort = KDefaultProxyPort;
       
  1393 
       
  1394     // Synchronize access to the database
       
  1395     WsockLock lock;
       
  1396     lock.LockLC();
       
  1397 
       
  1398     // Figure out the service id - we will need it
       
  1399     CCommsDatabase* db = CCommsDatabase::NewL();
       
  1400     CleanupStack::PushL(db);
       
  1401     WsockBeginCommDbTransactionLC(db);
       
  1402     TUint32 serviceId;
       
  1403     TBool commit = EFalse;
       
  1404     if (WsockCheckServiceTypeL(db, serviceId)) commit = ETrue;
       
  1405     if (WsockCheckProxyL(db, serviceId)) commit = ETrue;
       
  1406 
       
  1407     // At this point there should be only one record in the proxy table
       
  1408     const TDesC& TableName = KProxyTableName();
       
  1409     const TDesC& ServiceType = KWinsockServiceType();
       
  1410     CCommsDbTableView* view = db->OpenTableLC(TableName);
       
  1411 
       
  1412     // Column names
       
  1413     TPtrC UseProxyColumn(PROXY_USE_PROXY_SERVER);
       
  1414     TPtrC ProxyPortColumn(PROXY_PORT_NUMBER);
       
  1415     TPtrC ServerNameColumn(PROXY_SERVER_NAME);
       
  1416 
       
  1417     // Walk the table and deleted everything except our settings
       
  1418     TInt status = KErrNotFound;
       
  1419     if (view->GotoFirstRecord() == KErrNone)
       
  1420     {
       
  1421         status = KErrNone;
       
  1422         TUint32 number = KDefaultProxyPort;
       
  1423         view->ReadBoolL(UseProxyColumn,aUseProxy);
       
  1424         view->ReadUintL(ProxyPortColumn, number);
       
  1425         aPort = number;
       
  1426         aHost = view->ReadLongTextLC(ServerNameColumn);
       
  1427         CleanupStack::Pop(aHost);
       
  1428     }
       
  1429 
       
  1430     if (commit)
       
  1431     {
       
  1432         TRACE("commit CommDb transaction");
       
  1433         LEAVE_IF_ERROR(db->CommitTransaction());
       
  1434     }
       
  1435 
       
  1436     CleanupStack::PopAndDestroy(view);
       
  1437     CleanupStack::Pop();            // WsockRollbackOnLeave
       
  1438     CleanupStack::PopAndDestroy(db);
       
  1439     CleanupStack::PopAndDestroy();  // WsockLock::UnlockOnLeave
       
  1440 
       
  1441     LEAVE_IF_ERROR(status);
       
  1442 }
       
  1443 
       
  1444 // Entry point #1
       
  1445 extern "C"EXPORT_C CProtocolFamilyBase * WsockCreateProtocolFamily()
       
  1446 {
       
  1447     TRACE("WsockCreateProtocolFamily");
       
  1448     VERIFY_SUCCESS(WsockCheckCommDb());
       
  1449     return new CWinsockProtocolFamily(KAfInet);
       
  1450 }
       
  1451 
       
  1452 // Entry point #2
       
  1453 extern "C" EXPORT_C CNifAgentFactory* WsockCreateAgentFactory()
       
  1454 {
       
  1455     TRACE("WsockCreateAgentFactory");
       
  1456     return new CWinsockAgentFactory;
       
  1457 }
       
  1458 
       
  1459 // Entry point #3
       
  1460 extern "C" EXPORT_C CNifIfFactory* WsockCreateInterfaceFactory()
       
  1461 {
       
  1462     TRACE("WsockCreateInterfaceFactory");
       
  1463     return new CWinsockInterfaceFactory;
       
  1464 }
       
  1465 
       
  1466 // Entry point #4
       
  1467 extern "C" EXPORT_C TInt WsockQueryConfiguration(TBool& aUseProxy,
       
  1468                                                  HBufC*& aProxyHost,
       
  1469                                                  TUint& aProxyPort)
       
  1470 {
       
  1471     TRACE("WsockQueryProxy");
       
  1472     TRAPD(err,WsockQueryConfigL(aUseProxy,aProxyHost,aProxyPort));
       
  1473     if (err == KErrNone)
       
  1474     {
       
  1475         TRACE3("WsockQueryConfig: %d,%S:%d",aUseProxy,aProxyHost,aProxyPort);
       
  1476     }
       
  1477     else
       
  1478     {
       
  1479         TRACE1("configuration query failed, err %d",err);
       
  1480     }
       
  1481     return err;
       
  1482 }
       
  1483 
       
  1484 // Entry point #5
       
  1485 extern "C" EXPORT_C TInt WsockSetConfiguration(TBool aUseWsock,
       
  1486                                                TBool aUseProxy,
       
  1487                                                const TDesC* aProxyHost,
       
  1488                                                TUint aProxyPort)
       
  1489 {
       
  1490     TRACE4("WsockSetConfig(%d,%d,%S:%d)",aUseWsock,aUseProxy,
       
  1491         aProxyHost,aProxyPort);
       
  1492     TRAPD(err,WsockSetConfigL(aUseWsock, aUseProxy, aProxyHost, aProxyPort));
       
  1493     if (err == KErrNone)
       
  1494     {
       
  1495         TRACE("configuration updated ok");
       
  1496     }
       
  1497     else
       
  1498     {
       
  1499         TRACE1("configuration update failed, err %d",err);
       
  1500     }
       
  1501     return err;
       
  1502 }
       
  1503 
       
  1504 // Entry point #6
       
  1505 extern "C"EXPORT_C CProtocolFamilyBase * WsockCreateProtocolFamily6()
       
  1506 {
       
  1507     TRACE("WsockCreateProtocolFamily6");
       
  1508     VERIFY_SUCCESS(WsockCheckCommDb());
       
  1509     return new CWinsockProtocolFamily(KAfInet6);
       
  1510 }
       
  1511 
       
  1512 #ifndef EKA2
       
  1513 // Required function
       
  1514 GLDEF_C TInt E32Dll(TDllReason /*aReason*/)
       
  1515 {
       
  1516     return(KErrNone);
       
  1517 }
       
  1518 #endif // !EKA2
       
  1519 
       
  1520 /**
       
  1521  * Local Variables:
       
  1522  * c-basic-offset: 4
       
  1523  * indent-tabs-mode: nil
       
  1524  * End:
       
  1525  */