📄 mnotify.c
字号:
/*
* Copyright (C) Obigo AB, 2002-2005.
* All rights reserved.
*
* This software is covered by the license agreement between
* the end user and Obigo AB, and may be
* used and copied only in accordance with the terms of the
* said agreement.
*
* Obigo AB assumes no responsibility or
* liability for any errors or inaccuracies in this software,
* or any consequential, incidental or indirect damage arising
* out of the use of the software.
*
*/
#include "cansilib.h"
#include "cmnconf.h"
#include "aapifile.h"
#include "cmntypes.h"
#include "aapicmn.h"
#include "fldrmgr.h"
#include "gmem.h"
#include "cutils.h"
#include "chartype.h"
#include "mmstypes.h"
#include "mmsconf.h"
#include "aapimms.h"
#include "msig.h"
#include "mtimer.h"
#include "mmem.h"
#include "mcpdu.h"
#include "mconfig.h"
#include "mutils.h"
#include "mfreemms.h"
#include "mmpdup.h"
#include "mfetch.h"
#include "mnotify.h"
#include "mreceive.h"
#include "mcnotif.h"
#include "mrptr.h"
#define NOTIF_TABLE_FILE_ID 0
#define MMS_NOTIFY_TIMEOUT 1200
#define MMS_NOTIFY_TIMEOUT_INIT 450
#define MMS_IMMEDIATE_RETRIEVAL_CHECKS_PER_ITERATION 1
typedef struct
{
UINT32 fileId;
MmsMsrNotifStorageType type;
UINT8 retries;
char *uri;
} MsrNotifTableData;
typedef struct
{
int count;
MsrNotifTableData notif[MMS_MAX_DUPLICATE_NOTIFICATION_CHECK];
} MsrNotifTable;
typedef enum
{
MSR_IDLE,
MSR_IMMEDIATELY_RETRIEVING
} MsrNotifyFsmState;
typedef struct
{
MsrNotifyFsmState state;
MsrNotifTable notifTable;
} MsrNotifyInstanceData;
static MsrNotifyInstanceData fsm;
static char *getTransactionId(unsigned char *pdu, UINT32 len);
static CMN_BOOL handleNotification( MmsMsrNotifStorageType storage, UINT32 fileId,
MmsTimeSec time, CMN_BOOL isSmsBearer, UINT32 len, unsigned char *pdu);
static void immediateRetrievalCheck(void);
static void immediateRetrievalFinished( MmsSigMsrReceiveParam *p);
static CMN_BOOL isImmediateRetrieval(const MmsNotification *mmsNotification);
static CMN_BOOL isInServerList( const char *server, const char *uri);
static CMN_BOOL moreAttempts( UINT32 fileId);
static void msrNotifyMain(MmsSignal *sig);
static void notifInit(void);
static CMN_BOOL notifIsEqual( const char *uri, const MmsNotification *notif);
static CMN_BOOL notifFileRead(UINT32 fileId, MmsTimeSec *time,
CMN_BOOL *isSmsBearer, UINT32 *len, unsigned char **pdu);
static UINT32 notifFileWrite(MmsTimeSec time, CMN_BOOL isSmsBearer,
unsigned char *pdu, UINT32 len);
static UINT32 notifTableDecodeData( const char *buf, UINT32 len);
static MmsMsrNotifStorageType notifTableEntryExists(const MmsNotification *notif);
static void notifTableFreeMemory(void);
static void notifTableInsert( MmsMsrNotifStorageType type, UINT32 fileId,
const char *uri);
static void notifTableRead(void);
static void notifTableRemove(int index);
static void notifTableSaveAll(void);
static void notifTableSaveAllNoCache(void);
static void sendNotifyRespInd( CMN_BOOL isSmsBearer, const char *trId,
MmsStatus mgsStatus, MmsClassIdentifier msgClass, MmsVersion version);
static MmsResult storeDelayedRetrieval( MmsMsrNotifStorageType storage, UINT32 fileId,
MmsTimeSec time, CMN_BOOL isSmsBearer, UINT32 len, unsigned char *pdu,
MmsVersion version, MmsNotificationReason reason, UINT32 seqId);
static CMN_BOOL transientError( MmsRetrieveStatus retrieveStatus);
static char *getTransactionId(unsigned char *pdu, UINT32 len)
{
MmsHeaderValue trId;
if (!mmsPduGet( pdu, len, X_MMS_TRANSACTION_ID, &trId) ||
trId.transactionId == NULL)
{
return NULL;
}
return trId.transactionId;
}
static void handleDeliveryReport(UINT32 len, unsigned char *pdu)
{
MmsDeliveryInd *mmsDelivery;
INT32 origMsgId;
mmsDelivery = (MmsDeliveryInd *)M_CALLOC(sizeof(MmsDeliveryInd));
parseDeliveryReport(pdu, len, mmsDelivery);
if ((origMsgId = mrpthGetMsgId(mmsDelivery->messageId)) == -1)
{
origMsgId = 0;
}
MMSa_deliveryReportReceived(mmsDelivery->messageId, mmsDelivery->to,
mmsDelivery->date, mmsDelivery->status, (MmsMsgId)origMsgId);
#ifndef MMS_RETAIN_ADAPTER_PARAMETERS
freeMmsAddress(mmsDelivery->to);
M_FREE(mmsDelivery->to);
M_FREE(mmsDelivery->messageId);
#endif
M_FREE(mmsDelivery);
}
static CMN_BOOL handleNotification( MmsMsrNotifStorageType storage, UINT32 fileId,
MmsTimeSec time, CMN_BOOL isSmsBearer, UINT32 len, unsigned char *pdu)
{
char *trId = NULL;
CMN_BOOL pduInUse = FALSE;
CMN_BOOL isStarted = FALSE;
MmsVersion version;
MmsNotification *mmsNotification;
MmsSigMsrReceiveParam *param;
MmsMsrNotifStorageType type;
MmsMessageClass mc;
mmsNotification = (MmsNotification *)M_CALLOC( sizeof(MmsNotification));
if (parseMmsNotification( pdu, len, mmsNotification, &version) != MMS_RESULT_OK)
{
if (storage == NOTIF_IMMEDIATE)
{
msrNotifyRemoveId( NOTIF_IMMEDIATE, fileId);
}
MMS_LOG_I(("%s(%d): Parse Notification failed!\n", __FILE__, __LINE__));
}
else if ( (trId = getTransactionId(pdu, len)) == NULL)
{
if (storage == NOTIF_IMMEDIATE)
{
msrNotifyRemoveId( NOTIF_IMMEDIATE, fileId);
}
MMS_LOG_I(("%s(%d): Missing X_MMS_TRANSACTION_ID\n", __FILE__, __LINE__));
}
else if ( storage == NOTIF_UNSTORED &&
(type = notifTableEntryExists(mmsNotification)) != NOTIF_UNSTORED)
{
if (type == NOTIF_IMMEDIATE)
{
MMS_LOG_I(("handleNotification: duplicate notification for %s.\n"
"\tStored for IMMEDIATE retrieval. This one is ignored.\n",
mmsNotification->contentLocation == NULL ? "NULL" :
mmsNotification->contentLocation));
}
else
{
MMS_LOG_I(("handleNotification: duplicate notification for %s.\n"
"\tDELAYED. Already stored. Send a new M-NotifyResp.ind.\n",
mmsNotification->contentLocation == NULL ? "NULL" :
mmsNotification->contentLocation));
mmsPduGetMessageClass( pdu, len, &mc);
sendNotifyRespInd( isSmsBearer, trId , MMS_STATUS_DEFERRED,
mc.classIdentifier, version);
}
}
else if (cfgGetInt(MMS_CFG_IMMEDIATE_RETRIEVAL) == FALSE)
{
(void)storeDelayedRetrieval( storage, fileId, time, isSmsBearer, len,
pdu, version, MMS_NOTIFICATION_REASON_NORMAL, 0);
}
else if (cfgGetInt(MMS_CFG_IMMEDIATE_RETRIEVAL) == TRUE &&
isImmediateRetrieval(mmsNotification))
{
if (cfgGetInt(MMS_CFG_MAX_DOWNLOAD_SIZE) > 0 &&
mmsNotification->length > cfgGetInt(MMS_CFG_MAX_DOWNLOAD_SIZE))
{
(void)storeDelayedRetrieval( storage, fileId, time, isSmsBearer, len,
pdu, version, MMS_NOTIFICATION_REASON_MAX_DOWNLOAD_SIZE_EXCEEDED, 0);
}
else
{
if (storage == NOTIF_UNSTORED)
{
fileId = notifFileWrite( time, isSmsBearer, pdu, len);
if (fileId != 0)
{
notifTableInsert( NOTIF_IMMEDIATE, fileId,
mmsNotification->contentLocation);
}
}
if (fsm.state == MSR_IMMEDIATELY_RETRIEVING)
{
isStarted = TRUE;
}
else if (fileId != 0)
{
param = M_CALLOC(sizeof(MmsSigMsrReceiveParam));
param->notifId = fileId;
param->category = MMS_FILE_CATEGORY_IMMEDIATE;
param->pdu = pdu;
param->len = len;
param->isSmsBearer = isSmsBearer;
param->time = time;
M_SIGNAL_SENDTO_IUP( M_FSM_MSR_RECEIVE, MMS_SIG_MSR_RECEIVE_IMMEDIATE,
MMS_SIG_MSR_IMMEDIATE_RETRIEVAL_FINISHED, M_FSM_MSR_NOTIFY,
param);
pduInUse = TRUE;
isStarted = TRUE;
fsm.state = MSR_IMMEDIATELY_RETRIEVING;
}
}
}
else if (cfgGetInt(MMS_CFG_TREAT_AS_DELAYED_RETRIEVAL))
{
(void)storeDelayedRetrieval( storage, fileId, time, isSmsBearer, len, pdu,
version, MMS_NOTIFICATION_REASON_CONDITION_NOT_FULFILLED, 0);
}
else
{
MMS_LOG_I(("handleNotification: Notification rejected!\n"));
sendNotifyRespInd( isSmsBearer, trId, MMS_STATUS_REJECTED,
mmsNotification->msgClass.classIdentifier, version);
}
freeMmsNotification(mmsNotification);
M_FREE(mmsNotification);
if ( !pduInUse )
{
M_FREE(pdu);
}
return isStarted;
}
static void handleReadReport(UINT32 len, unsigned char *pdu)
{
MmsReadOrigInd *mmsOrigInd = NULL;
INT32 origMsgId;
mmsOrigInd = parseReadReport(pdu, len);
if ((origMsgId = mrpthGetMsgId(mmsOrigInd->serverMessageId)) == -1)
{
origMsgId = 0;
}
MMSa_readReportIndication(mmsOrigInd, (MmsMsgId)origMsgId);
#ifndef MMS_RETAIN_ADAPTER_PARAMETERS
freeMmsReadOrigInd(mmsOrigInd);
#endif
}
static void immediateRetrievalCheck(void)
{
int nrOfFiles = 0;
int nrToCheck = 0;
MmsTimeSec time;
CMN_BOOL isSmsBearer;
CMN_BOOL isStarted = FALSE;
UINT32 len;
unsigned char *pdu;
UINT32 allFileIds[MMS_IMMEDIATE_RETRIEVAL_CHECKS_PER_ITERATION + 1];
if (fsm.state == MSR_IMMEDIATELY_RETRIEVING ||
cfgGetInt(MMS_CFG_IMMEDIATE_RETRIEVAL) == MMS_IMMEDIATE_RETRIEVAL_PAUSED)
{
return;
}
nrOfFiles = FILEa_getFileIds( MMS_FILE_CATEGORY_IMMEDIATE, NULL, 0);
if (nrOfFiles <= 1)
{
return;
}
nrToCheck = FILEa_getFileIds( MMS_FILE_CATEGORY_IMMEDIATE, allFileIds,
sizeof(allFileIds) / sizeof(UINT32));
if (nrToCheck > (int)(sizeof(allFileIds) / sizeof(UINT32)))
{
MMS_LOG_I(("%s(%d): FILEa_getFileIds return more than requested %d > %d\n",
__FILE__, __LINE__, nrToCheck,
(int)(sizeof(allFileIds) / sizeof(UINT32))));
MMSa_error(MMS_RESULT_ERROR);
return;
}
while ( --nrToCheck >= 0 && !isStarted )
{
if (allFileIds[nrToCheck] == NOTIF_TABLE_FILE_ID)
{
}
else if (notifFileRead( allFileIds[nrToCheck], &time, &isSmsBearer,
&len, &pdu))
{
isStarted = handleNotification( NOTIF_IMMEDIATE,
allFileIds[nrToCheck], time, isSmsBearer, len, pdu);
}
else
{
MMS_LOG_I(("%s(%d): Couldn't read stored notif\n", __FILE__, __LINE__));
FILEa_delete( MMS_FILE_CATEGORY_IMMEDIATE, allFileIds[nrToCheck]);
}
}
if ( !isStarted && nrOfFiles > nrToCheck )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -