📄 dbfunct.c
字号:
* 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 + -