⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dbfunct.c

📁 是一个手机功能的模拟程序
💻 C
📖 第 1 页 / 共 5 页
字号:
 * is named "objxx", where xx is the hexidecimal representation
 * of 'object' in lower-case.
 *
 * Return a reference to the new object record.
 */
DB_ref addObject(INT8 object) {
   ObjectListPtr temp;

   temp = addObjectInternal(object);
   if (temp == NULL)
      return DB_null;
   else
      return temp->objectRef;
}



/*
 * Removes an object and its record from the database.
 */
void deleteObject(UINT8 object)
{
   BYTE key[] = "obj??";
   int  i;

   if (object == 0)
      return;

   /* Find object */
   for (i=0; ; i++) {
      if (i == objectListSize) 
         return;
      if (objectList[i].objectNbr == object) 
         break;
   }

   ByteToHex(object, key+3);
   db_deleteItem(DB_root, key);

   OSConnectorFree(objectList[i].channelList);
   objectListSize--;
}



/*
 * Search for an object not connected to a push, WTA, template or
 * content user agent. The number of first one found with at least 
 * one configured data channel is returned. If no matching object
 * is found, '*errorCode' is set to DB_err_objectNotFound, else
 * DB_err_success.
 */
UINT8 getFirstConfiguredObject(UINT8 *errorCode)
{
   int i;

   /* Find object */
   for (i=0; i < objectListSize; i++) {
      UINT8 obj = objectList[i].objectNbr;
      if (obj != ALL_USER_AGENT && obj != CONTENT_USER_AGENT &&
         obj != REPOSITORY_USER_AGENT && obj != PUSH_USER_AGENT)
         if (objectList[i].channelListSize >= 1) {
            *errorCode = DB_err_success;
            return obj;
         }
   }

   *errorCode = DB_err_objectNotFound;
   return 255;
}



/*
 * Add and update all fields needed in the record "objxx", where
 * xx is the hexidecimal representation of 'object'. If "objxx"
 * does not exist, it is created by addObjectInternal.
 *
 * A new record field "dchyy" is added to "objxx", containing an
 * empty set "hosts". yy is the hexidecimal representation of
 * 'channel'.
 *
 * "tmout" and "onln" fields are added to the channel record.
 * See capiclnt.c for more information.
 *
 * Return reference to the new channel record or to an old
 * channel record with the same name if it already exists.
 */
DB_ref addDataChannel(UINT8 object, UINT8 channel)
{
   BYTE           key[] = "dch??";
   ChannelListPtr channelList;
   DB_ref         refO, refC, refU;
   UINT8          error;
   UINT8          nbr;
   int            i;

   /* Find channel list for object */
   for (i=0; i < objectListSize; i++) {
      if (objectList[i].objectNbr == object) {
         channelList = objectList[i].channelList;
         break;
      }
   }
   if (i == objectListSize) {
      channelList = addObjectInternal(object)->channelList;
      if (channelList == NULL)
         return DB_null;
   } else
      if (objectList[i].channelListSize == DB_maxNbrOfDataChannels)
         return DB_null;

   refO = objectList[i].objectRef;

   ByteToHex(channel, key+3);
   refC = db_createRecord(refO, key, DB_rec, &error);
   if (error == DB_err_exists)
      return ((RecordPtr) db_findField(key))->ref;
   else if (error)
      return DB_null;
   refU = db_createRecord(refC, (BYTE*) "hosts", DB_set, &error);
   if (error) {
      db_deleteItem(refO, key);
      return DB_null;
   }

   if (objectList[i].defaultChannel == -1)
      objectList[i].defaultChannel = channel;

   nbr = objectList[i].channelListSize++;
   channelList[nbr].channelNbr = channel;
   channelList[nbr].channelRef = refC;
   channelList[nbr].hostPtr    = db_findRecord(refU);
   
   /* Fields added to the data channel */

   db_setInt(refC, (BYTE*) TIMEOUT, 60);            /* Request timeout */
   db_setInt(refC, (BYTE*) ONLINE , 0);             /* Online */
   db_setInt(refC, (BYTE*) ALLOW_WTLS_CLASS_1 , 1); /* Allow WTLS class 1 */
   db_setInt(refC, (BYTE*) MASTER_GW , 1);          /* Master Gateway */
   return refC;
}



/*
 * Removes a data channel.
 * Internal use ony!
 * The inparams are indexes into the object and channel arrays.
 * The indexes must not be out of bounds when calling.
 * The last data channel is moved to the chInd position, thereby
 * replacing the channel to be deleted. The channelListSize is
 * decremented.
 * If the default channel is deleted, then a 
 * call to getDataChannel that does not result
 * in a match will cause an error code to be returned.
 */
static void deleteDataChannelInternal(int objInd, int chInd)
{
   BYTE           key[] = "dch??";
   UINT8          channel;
   ChannelListPtr channelList;
   int            lastChannel;

   channelList = objectList[objInd].channelList;
   lastChannel = objectList[objInd].channelListSize - 1;  
   channel = channelList[chInd].channelNbr;

   channelList[chInd].channelNbr = channelList[lastChannel].channelNbr;
   channelList[chInd].channelRef = channelList[lastChannel].channelRef;
   channelList[chInd].hostPtr    = channelList[lastChannel].hostPtr;
   objectList[objInd].channelListSize--;

   if (objectList[objInd].defaultChannel == channel)
      objectList[objInd].defaultChannel = -1;

   ByteToHex(channel, key+3);
   db_deleteItem(objectList[objInd].objectRef, key);
}


/*
 * Removes a data channel, if found. If the default channel is
 * deleted, then a call to getDataChannel that does not result
 * in a match will cause an error code to be returned.
 */
void deleteDataChannel(UINT8 object, UINT8 channel)
{
   ChannelListPtr channelList;
   int            lastChannel;
   int            i, j;

   /* Find object */
   for (i=0; ; i++) {
      if (i == objectListSize) 
         return;
      if (objectList[i].objectNbr == object) 
         break;
   }

   channelList = objectList[i].channelList;
   lastChannel = objectList[i].channelListSize - 1;  
   for (j=lastChannel; ; j--) {
      if (j < 0)
         return;
      if (channelList[j].channelNbr == channel) {
         deleteDataChannelInternal(i, j);
         break;
      }
   }
}



/*
 * Searches through all host addresses connected to the channels
 * in an object. The channel number belonging to the best
 * matching host is returned. If there is no match, then if set,
 * the default channel number is returned, or else an error occurs. 
 *
 * getDataChannel assumes the URL to be well formatted, including
 * a scheme, host and optionally a path.
 *
 * The host address connected to a channel contains a host name
 * which may be followed by a path name.
 *
 * getDataChannel matches url:s with host addresses as sepcified
 * in the WAP End to End Security Specification (section 10.3.1). 
 *
 * During getDataChannel it is checked if channels for the specified
 * object have expired. If any expired channels are found the outparam
 * expired is set, otherwise it is false. The id of any expired channels
 * for the object is remembered in an internal set (list). These channel
 * id:s may be retrieved by calling getNextExpired. Note, the internal set
 * of expired channel id:s is reset for each call of getDataChannel.
 *
 * '*errorCode' signals the return status.
 */
UINT8 getDataChannel(UINT8 object, const BYTE* url,
                     BOOL* expired, UINT8 *errorCode)
{
   ChannelListPtr channelList;
   ElementPtr     element;
   BYTE*          host;
   BYTE*          path;
   int            i, j;
   UINT32         exp;
   UrlParts       urlParts;
   int            chListSize;
   int            currIndex;
   INT32          currPreLabels;
   UINT32         currPathLen;
   INT32          preLabels;
   UINT32         pathLen;

   if (expired) *expired = FALSE;
   expChNbrListSize = 0;
   nextExpChNbrListInd = 0;

   /* Find channel list for object */
   for (i=0; ; i++) {
      if (i == objectListSize) {
         *errorCode = DB_err_objectNotFound;
         return 255;
      }
      if (objectList[i].objectNbr == object) {
         channelList = objectList[i].channelList;
         break;
      }
   }
   
   
   /* remove expired data channels */
   j = 0;
   while (j < objectList[i].channelListSize) {
      exp = db_getInt(channelList[j].channelRef, (BYTE*) CHANNEL_EXPIRES,
                      FALSE, errorCode);
      if ((*errorCode == DB_err_success) && (exp > 0) &&
           (exp <= CLNTa_currentTime()))
      {
         if (expired && !*expired) *expired = TRUE;
         expChNbrList[expChNbrListSize] = channelList[j].channelNbr;
         expChNbrListSize++;
         deleteDataChannelInternal(i, j); /* channel j is replaced by last */
                                          /* and list size is decremented  */
      }
      else
         j++;
   }

   *errorCode = DB_err_success;         
   parseUrl((BYTE*) url, &urlParts);

   /* Search through all channels and match its host and path against */
   /* the url. Compare each match with previous best match stored in  */
   /* currIndex, currPreLabels and currPathLen. Compare matches       */
   /* according to WAP End to End Security specification              */
   currIndex = -1;
   currPreLabels = -1;
   currPathLen = 0;
   chListSize = objectList[i].channelListSize;
   for (j = 0; j < chListSize; j++) {

     /* Search through all elements in this channel */
      for (element = channelList[j].hostPtr->data.e;
           element != (ElementPtr) channelList[j].hostPtr;
           element = element->next)
      {
         host = element->data.s;
         for (path = host; (*path) && (*path != '/'); path++) ;

         if (!domainMatch(&urlParts, host, path, FALSE, TRUE, 1,
                          &preLabels))
            continue;

         /* Compare with previous best match. Minimize preLabels.        */
         /* If preLabels is smaller or equal, path has to be considered. */
         if ((currIndex >= 0) && (preLabels > currPreLabels))
            continue;
            
         if (!pathMatch(&urlParts, path, TRUE, &pathLen))
            continue;
         
         /* Change the current (best hit) if domain is more precise, */
         /* if preLabels is smaller. Otherwise if the domains are    */
         /* equally precise, change the current only if path is more */
         /* precise (maximize pathLen).                              */
         if ((currIndex < 0) ||
             (preLabels < currPreLabels) || (pathLen > currPathLen))
         {
            currIndex = j;
            currPreLabels = preLabels;
            currPathLen = pathLen;
         }

         /* Keep on searching for better hits in this channel even       */
         /* if currIndex was updated for the present j-value, since      */
         /* we otherwise would miss an even better hit in this channel.  */
         /* This could lead to reporting a channel (j-value) which does  */
         /* not contain the best hit.                                    */

      } /* end for loop over elements */
   } /* end for loop over channels */

   if (currIndex < 0) {                         /* Take default channel. */
      if (objectList[i].defaultChannel == -1) {
         *errorCode = DB_err_noDefaultChannel;
         return 255;
      }
      return (UINT8) objectList[i].defaultChannel;
   }

   return channelList[currIndex].channelNbr;
}



typedef union {
   ChannelListPtr channelStruct;
   ObjectListPtr  objectStruct;

} ObjectOrChannel;



/*
 * Return a pointer to the struct associated with 'channel'
 * if getChannel is TRUE, else return the struct associated
 * with 'object'.
 *
 * An object and a data channel are created if either is missing.
 */
static ObjectOrChannel getObjectOrChannel_add(UINT8 object, UINT8 channel, BOOL getChannel)
{
   ChannelListPtr  channelList;
   ObjectOrChannel u = {NULL};
   int             i, j;

   /* Find channel list for object */
   for (i=0; ; i++) {
      if (i == objectListSize)
         if (addDataChannel(object, channel) == DB_null) 
            return u;
         /* else caught by next if */ 
      if (objectList[i].objectNbr == object) {
         channelList = objectList[i].channelList;
         break;
      }
   }

   /* Find channel */
   for (j=0; ; j++) {
      if (j == objectList[i].channelListSize)
         if (addDataChannel(object, channel) == DB_null)
            return u;
         else
            break;
      if (channelList[j].channelNbr == channel)
         break;
   }

   if (getChannel)
      u.channelStruct = &channelList[j];
   else
      u.objectStruct  = &objectList[i];
   return u;
}



/*
 * Change the data channel to be used when no host matches when
 * calling getDataChannel.
 *
 * An object and a data channel are created if either is missing.
 */
void setDefaultDataChannel(UINT8 object, UINT8 channel)
{
   ObjectListPtr objectStruct;

   objectStruct = getObjectOrChannel_add(object, channel, FALSE).objectStruct;
   if (objectStruct != NULL)
      objectStruct->defaultChannel = channel;
}


/* getNextExpired
 *
 * getNextExpired iterates on the internal set of expired channels.
 * The internal set is reset when calling getDataChannel. getNextExpired
 * returns TRUE if outparam channelId is valid, i.e. containing the next
 * channel id in the iteration. getNextExpired returns FALSE when the
 * iteration ends and then the outparam channelId is not valid.
 * The channelId param must not be NULL.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -