• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* ------------------------------------------------------------------
2  * Copyright (C) 1998-2009 PacketVideo
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13  * express or implied.
14  * See the License for the specific language governing permissions
15  * and limitations under the License.
16  * -------------------------------------------------------------------
17  */
18 #include "pvmf_protocol_engine_node.h"
19 #include "pvmf_protocol_engine_command_format_ids.h"
20 #include "pvmf_protocolengine_node_tunables.h"
21 #include "pvlogger.h"
22 #include "oscl_utf8conv.h"
23 
24 
25 /**
26 //////////////////////////////////////////////////
27 // Node Constructor & Destructor
28 //////////////////////////////////////////////////
29 */
30 
PVMFProtocolEngineNode(int32 aPriority)31 PVMFProtocolEngineNode::PVMFProtocolEngineNode(int32 aPriority) :
32         OsclTimerObject(aPriority, "PVMFProtocolEngineNode"),
33         iStatusCode(0),
34         iProcessingState(ProcessingState_Idle),
35         iInterfacingObjectContainer(NULL),
36         iProtocol(NULL),
37         iProtocolContainer(NULL),
38         iProtocolContainerFactory(NULL),
39         iNodeOutput(NULL),
40         iCurrEventHandler(NULL),
41         iCfgFileContainer(NULL),
42         iDownloadSource(NULL),
43         iDownloadControl(NULL),
44         iDownloadProgess(NULL),
45         iSDPInfo(NULL),
46         iUserAgentField(NULL),
47         iEventReport(NULL),
48         iPortConfigFSInfoAlloc(NULL),
49         iPortConfigMemPool(PVHTTPDOWNLOADOUTPUT_CONTENTDATA_POOLNUM, OSCL_REFCOUNTER_MEMFRAG_DEFAULT_SIZE),
50         iNodeTimer(NULL),
51         iPortInForData(NULL),
52         iPortInForLogging(NULL),
53         iPortOut(NULL),
54         iCurrentCmdId(0),
55         iCmdRespPort(NULL),
56         iLogger(NULL),
57         iDataPathLogger(NULL),
58         iClockLogger(NULL),
59         iExtensionRefCount(0),
60         iCurrentDataStreamCmdId(0)
61 {
62     int32 err = 0;
63     OSCL_TRY(err,
64              //Create the input command queue.  Use a reserve to avoid lots of
65              //dynamic memory allocation.
66              iInputCommands.Construct(PVMF_PROTOCOLENGINE_NODE_COMMAND_ID_START, PVMF_PROTOCOLENGINE_NODE_COMMAND_VECTOR_RESERVE);
67 
68              //Create the "current command" queue.  It will only contain one
69              //command at a time, so use a reserve of 1.
70              iCurrentCommand.Construct(0, 1);
71 
72              //Create the port vector.
73              iPortVector.Construct(PVMF_PROTOCOLENGINE_NODE_PORT_VECTOR_RESERVE);
74 
75              //Set the node capability data.
76              //This node can support an unlimited number of ports.
77              iCapability.iCanSupportMultipleInputPorts = false;
78              iCapability.iCanSupportMultipleOutputPorts = false;
79              iCapability.iHasMaxNumberOfPorts = false;
80              iCapability.iMaxNumberOfPorts = 0;//no maximum
81              iCapability.iInputFormatCapability.push_back(PVMF_MIME_INET_TCP);
82 
83              // create the internal data queue
84              iDataInQueue.reserve(PVPROTOCOLENGINE_RESERVED_NUMBER_OF_FRAMES);
85              iInternalEventQueue.reserve(PVPROTOCOLENGINE_RESERVED_NUMBER_OF_FRAMES);
86             );
87 
88     if (err)
89     {
90         //if a leave happened, cleanup and re-throw the error
91         iInputCommands.clear();
92         iCurrentCommand.clear();
93         iPortVector.clear();
94         iCapability.iInputFormatCapability.clear();
95         iCapability.iOutputFormatCapability.clear();
96         iDataInQueue.clear();
97         iInternalEventQueue.clear();
98         OSCL_CLEANUP_BASE_CLASS(PVMFNodeInterface);
99         OSCL_CLEANUP_BASE_CLASS(OsclTimerObject);
100         OSCL_LEAVE(err);
101     }
102 
103     for (uint32 i = 0; i < EVENT_HANDLER_TOTAL; i++) iEventHandlers[i] = NULL;
104 }
105 
~PVMFProtocolEngineNode()106 PVMFProtocolEngineNode::~PVMFProtocolEngineNode()
107 {
108     //thread logoff
109     if (IsAdded()) RemoveFromScheduler();
110 
111 
112     //Cleanup commands
113     //The command queues are self-deleting, but we want to
114     //notify the observer of unprocessed commands.
115     while (!iCurrentCommand.empty())
116     {
117         CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFFailure);
118     }
119 
120     while (!iInputCommands.empty())
121     {
122         CommandComplete(iInputCommands, iInputCommands.front(), PVMFFailure);
123     }
124 
125     Clear(true);
126 }
127 
128 /**
129 //////////////////////////////////////////////////
130 // Public Node API implementation
131 //////////////////////////////////////////////////
132 */
133 
134 
ThreadLogon()135 PVMFStatus PVMFProtocolEngineNode::ThreadLogon()
136 {
137     LOGINFO((0, "PVMFProtocolEngineNode::ThreadLogon()"));
138     switch (iInterfaceState)
139     {
140         case EPVMFNodeCreated:
141             if (!IsAdded()) AddToScheduler();
142             iLogger = PVLogger::GetLoggerObject("PVMFProtocolEngineNode");
143             iDataPathLogger = PVLogger::GetLoggerObject(NODEDATAPATHLOGGER_TAG);
144             iClockLogger = PVLogger::GetLoggerObject("clock");
145             SetState(EPVMFNodeIdle);
146             return PVMFSuccess;
147 
148         default:
149             return PVMFErrInvalidState;
150     }
151 }
152 
153 
ThreadLogoff()154 PVMFStatus PVMFProtocolEngineNode::ThreadLogoff()
155 {
156     LOGINFO((0, "PVMFProtocolEngineNode::ThreadLogoff()"));
157     switch (iInterfaceState)
158     {
159         case EPVMFNodeIdle:
160             if (IsAdded()) RemoveFromScheduler();
161 
162             iLogger = NULL;
163             iDataPathLogger = NULL;
164             iClockLogger = NULL;
165             SetState(EPVMFNodeCreated);
166             return PVMFSuccess;
167 
168         default:
169             return PVMFErrInvalidState;
170     }
171 }
172 
173 
GetCapability(PVMFNodeCapability & aNodeCapability)174 PVMFStatus PVMFProtocolEngineNode::GetCapability(PVMFNodeCapability& aNodeCapability)
175 {
176     OSCL_UNUSED_ARG(aNodeCapability);
177     LOGINFO((0, "PVMFProtocolEngineNode::GetCapability()"));
178     //aNodeCapability=iCapability;
179     return PVMFSuccess;
180 }
181 
182 
GetPorts(const PVMFPortFilter * aFilter)183 PVMFPortIter* PVMFProtocolEngineNode::GetPorts(const PVMFPortFilter* aFilter)
184 {
185     LOGINFO((0, "PVMFProtocolEngineNode::GetPorts()"));
186     OSCL_UNUSED_ARG(aFilter);//port filter is not implemented.
187     iPortVector.Reset();
188     return &iPortVector;
189 }
190 
191 
QueryUUID(PVMFSessionId s,const PvmfMimeString & aMimeType,Oscl_Vector<PVUuid,PVMFProtocolEngineNodeAllocator> & aUuids,bool aExactUuidsOnly,const OsclAny * aContext)192 PVMFCommandId PVMFProtocolEngineNode::QueryUUID(PVMFSessionId s, const PvmfMimeString& aMimeType,
193         Oscl_Vector<PVUuid, PVMFProtocolEngineNodeAllocator>& aUuids,
194         bool aExactUuidsOnly, const OsclAny* aContext)
195 {
196     LOGINFO((0, "PVMFProtocolEngineNode::QueryUUID()"));
197     PVMFProtocolEngineNodeCommand cmd;
198     cmd.PVMFProtocolEngineNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_QUERYUUID, aMimeType, aUuids, aExactUuidsOnly, aContext);
199     return QueueCommandL(cmd);
200 }
201 
202 
QueryInterface(PVMFSessionId s,const PVUuid & aUuid,PVInterface * & aInterfacePtr,const OsclAny * aContext)203 PVMFCommandId PVMFProtocolEngineNode::QueryInterface(PVMFSessionId s, const PVUuid& aUuid, PVInterface*& aInterfacePtr, const OsclAny* aContext)
204 {
205     LOGINFO((0, "PVMFProtocolEngineNode::QueryInterface()"));
206     PVMFProtocolEngineNodeCommand cmd;
207     cmd.PVMFProtocolEngineNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_QUERYINTERFACE, aUuid, aInterfacePtr, aContext);
208     return QueueCommandL(cmd);
209 }
210 
211 
RequestPort(PVMFSessionId s,int32 aPortTag,const PvmfMimeString * aPortConfig,const OsclAny * aContext)212 PVMFCommandId PVMFProtocolEngineNode::RequestPort(PVMFSessionId s, int32 aPortTag, const PvmfMimeString* aPortConfig, const OsclAny* aContext)
213 {
214     OSCL_UNUSED_ARG(aPortConfig);
215     LOGINFO((0, "PVMFProtocolEngineNode::RequestPort()"));
216     PVMFProtocolEngineNodeCommand cmd;
217     cmd.PVMFProtocolEngineNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_REQUESTPORT, aPortTag, aContext);
218     return QueueCommandL(cmd);
219 }
220 
221 
ReleasePort(PVMFSessionId s,PVMFPortInterface & aPort,const OsclAny * aContext)222 PVMFCommandId PVMFProtocolEngineNode::ReleasePort(PVMFSessionId s, PVMFPortInterface& aPort, const OsclAny* aContext)
223 {
224     LOGINFO((0, "PVMFProtocolEngineNode::ReleasePort()"));
225     PVMFProtocolEngineNodeCommand cmd;
226     cmd.PVMFProtocolEngineNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_RELEASEPORT, aPort, aContext);
227     return QueueCommandL(cmd);
228 }
229 
230 
Init(PVMFSessionId s,const OsclAny * aContext)231 PVMFCommandId PVMFProtocolEngineNode::Init(PVMFSessionId s, const OsclAny* aContext)
232 {
233     LOGINFO((0, "PVMFProtocolEngineNode::Init()"));
234     PVMFProtocolEngineNodeCommand cmd;
235     cmd.PVMFProtocolEngineNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_INIT, aContext);
236     return QueueCommandL(cmd);
237 }
238 
239 
Prepare(PVMFSessionId s,const OsclAny * aContext)240 PVMFCommandId PVMFProtocolEngineNode::Prepare(PVMFSessionId s, const OsclAny* aContext)
241 {
242     LOGINFO((0, "PVMFProtocolEngineNode::Prepare()"));
243     PVMFProtocolEngineNodeCommand cmd;
244     cmd.PVMFProtocolEngineNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_PREPARE, aContext);
245     return QueueCommandL(cmd);
246 }
247 
248 
Start(PVMFSessionId s,const OsclAny * aContext)249 PVMFCommandId PVMFProtocolEngineNode::Start(PVMFSessionId s, const OsclAny* aContext)
250 {
251     LOGINFO((0, "PVMFProtocolEngineNode::Start()"));
252 
253     PVMFProtocolEngineNodeCommand cmd;
254     cmd.PVMFProtocolEngineNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_START, aContext);
255     return QueueCommandL(cmd);
256 }
257 
258 
Stop(PVMFSessionId s,const OsclAny * aContext)259 PVMFCommandId PVMFProtocolEngineNode::Stop(PVMFSessionId s, const OsclAny* aContext)
260 {
261     LOGINFO((0, "PVMFProtocolEngineNode::Stop()"));
262 
263     PVMFProtocolEngineNodeCommand cmd;
264     cmd.PVMFProtocolEngineNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_STOP, aContext);
265     return QueueCommandL(cmd);
266 }
267 
268 
Flush(PVMFSessionId s,const OsclAny * aContext)269 PVMFCommandId PVMFProtocolEngineNode::Flush(PVMFSessionId s, const OsclAny* aContext)
270 {
271     LOGINFO((0, "PVMFProtocolEngineNode::Flush()"));
272     PVMFProtocolEngineNodeCommand cmd;
273     cmd.PVMFProtocolEngineNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_FLUSH, aContext);
274     return QueueCommandL(cmd);
275 }
276 
277 
Pause(PVMFSessionId s,const OsclAny * aContext)278 PVMFCommandId PVMFProtocolEngineNode::Pause(PVMFSessionId s, const OsclAny* aContext)
279 {
280     LOGINFO((0, "PVMFProtocolEngineNode::Pause()"));
281 
282     PVMFProtocolEngineNodeCommand cmd;
283     cmd.PVMFProtocolEngineNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_PAUSE, aContext);
284     return QueueCommandL(cmd);
285 }
286 
287 
Reset(PVMFSessionId s,const OsclAny * aContext)288 PVMFCommandId PVMFProtocolEngineNode::Reset(PVMFSessionId s, const OsclAny* aContext)
289 {
290     LOGINFO((0, "PVMFProtocolEngineNode::Reset()"));
291     PVMFProtocolEngineNodeCommand cmd;
292     cmd.PVMFProtocolEngineNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_RESET, aContext);
293     return QueueCommandL(cmd);
294 }
295 
296 
CancelAllCommands(PVMFSessionId s,const OsclAny * aContext)297 PVMFCommandId PVMFProtocolEngineNode::CancelAllCommands(PVMFSessionId s, const OsclAny* aContext)
298 {
299     LOGINFO((0, "PVMFProtocolEngineNode::CancelAllCommands()"));
300     PVMFProtocolEngineNodeCommand cmd;
301     cmd.PVMFProtocolEngineNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_CANCELALLCOMMANDS, aContext);
302     return QueueCommandL(cmd);
303 }
304 
305 
CancelCommand(PVMFSessionId s,PVMFCommandId aCmdId,const OsclAny * aContext)306 PVMFCommandId PVMFProtocolEngineNode::CancelCommand(PVMFSessionId s, PVMFCommandId aCmdId, const OsclAny* aContext)
307 {
308     LOGINFO((0, "PVMFProtocolEngineNode::CancelCommand()"));
309     PVMFProtocolEngineNodeCommand cmd;
310     cmd.PVMFProtocolEngineNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_CANCELCOMMAND, aCmdId, aContext);
311     return QueueCommandL(cmd);
312 }
313 
314 
Seek(PVMFSessionId aSessionId,uint64 aNPTInMS,uint32 & aFirstSeqNumAfterSeek,OsclAny * aContext)315 PVMFCommandId PVMFProtocolEngineNode::Seek(PVMFSessionId aSessionId, uint64 aNPTInMS, uint32& aFirstSeqNumAfterSeek, OsclAny* aContext)
316 {
317     LOGINFO((0, "PVMFProtocolEngineNode::Seek()"));
318     PVMFProtocolEngineNodeCommand cmd;
319     cmd.PVMFProtocolEngineNodeCommand::Construct(aSessionId, PVPROTOCOLENGINE_NODE_CMD_SEEK, aNPTInMS, aFirstSeqNumAfterSeek, aContext);
320     return QueueCommandL(cmd);
321 }
322 
BitstreamSwitch(PVMFSessionId aSessionId,uint64 aNPTInMS,uint32 & aFirstSeqNumAfterSwitch,OsclAny * aContext)323 PVMFCommandId PVMFProtocolEngineNode::BitstreamSwitch(PVMFSessionId aSessionId, uint64 aNPTInMS, uint32& aFirstSeqNumAfterSwitch, OsclAny* aContext)
324 {
325     LOGINFO((0, "PVMFProtocolEngineNode::BitstreamSwitch()"));
326     PVMFProtocolEngineNodeCommand cmd;
327     cmd.PVMFProtocolEngineNodeCommand::Construct(aSessionId, PVPROTOCOLENGINE_NODE_CMD_BITSTREAM_SWITCH, aNPTInMS, aFirstSeqNumAfterSwitch, aContext);
328     return QueueCommandL(cmd);
329 }
330 
DataStreamRequest(PvmiDataStreamSession aSessionID,PvmiDataStreamRequest aRequestID,OsclAny * aRequestData,OsclAny * aContextData)331 PvmiDataStreamCommandId PVMFProtocolEngineNode::DataStreamRequest(PvmiDataStreamSession aSessionID, PvmiDataStreamRequest aRequestID,
332         OsclAny* aRequestData, OsclAny* aContextData)
333 {
334     LOGINFODATAPATH((0, "PVMFProtocolEngineNode::DataStreamRequest()"));
335 
336     // This is for asynchronous requests, such as repositioning
337     // Caller's SourceRequestCompleted will be called
338     if (aRequestID != PVDS_REQUEST_REPOSITION)
339     {
340         // currently we only define reposition request
341         OSCL_LEAVE(OsclErrArgument);
342         return 0;
343     }
344 
345     PVMFProtocolEngineNodeCommand cmd; // internal command, use 0 as session id.
346     cmd.PVMFProtocolEngineNodeCommand::Construct((PVMFSessionId)0, PVPROTOCOLENGINE_NODE_CMD_DATASTREAM_REQUEST_REPOSITION,
347             aSessionID, aRequestID, aRequestData, iCurrentDataStreamCmdId, aContextData);
348     QueueCommandL(cmd);
349     return iCurrentDataStreamCmdId++;
350 }
351 
DataStreamRequestSync(PvmiDataStreamSession aSessionID,PvmiDataStreamRequest aRequestID,OsclAny * aRequestData)352 PvmiDataStreamStatus PVMFProtocolEngineNode::DataStreamRequestSync(PvmiDataStreamSession aSessionID, PvmiDataStreamRequest aRequestID, OsclAny* aRequestData)
353 {
354     OSCL_UNUSED_ARG(aSessionID);
355     // This is for synchronous requests, such as returning memory fragments
356     PvmiDataStreamStatus status = PVDS_FAILURE;
357     switch (aRequestID)
358     {
359         case PVDS_REQUEST_MEM_FRAG_RELEASED:
360             if (aRequestData != NULL)
361             {
362                 LOGINFODATAPATH((0, "PVMFProtocolEngineNode::DataStreamRequestSync, got PVDS_REQUEST_MEM_FRAG_RELEASED request"));
363                 OsclRefCounterMemFrag* frag = ((OsclRefCounterMemFrag*)aRequestData);
364                 if (iNodeOutput->releaseMemFrag(frag)) status = PVDS_SUCCESS;
365             }
366             break;
367 
368         default:
369             break;
370     }
371 
372     return status;
373 }
374 
IsRepositioningRequestPending()375 bool PVMFProtocolEngineNode::IsRepositioningRequestPending()
376 {
377     PVMFProtocolEngineNodeCommand *pInputCmd   = FindCmd(iInputCommands, PVPROTOCOLENGINE_NODE_CMD_DATASTREAM_REQUEST_REPOSITION);
378     PVMFProtocolEngineNodeCommand *pPendingCmd = FindCmd(iCurrentCommand, PVPROTOCOLENGINE_NODE_CMD_DATASTREAM_REQUEST_REPOSITION);
379 
380     return (pInputCmd || pPendingCmd);
381 }
382 
addRef()383 void PVMFProtocolEngineNode::addRef()
384 {
385     ++iExtensionRefCount;
386 }
387 
removeRef()388 void PVMFProtocolEngineNode::removeRef()
389 {
390     --iExtensionRefCount;
391 }
392 
queryInterface(const PVUuid & uuid,PVInterface * & iface)393 bool PVMFProtocolEngineNode::queryInterface(const PVUuid& uuid, PVInterface*& iface)
394 {
395     if (uuid == PVMF_DATA_SOURCE_INIT_INTERFACE_UUID)
396     {
397         PVMFDataSourceInitializationExtensionInterface* myInterface = OSCL_STATIC_CAST(PVMFDataSourceInitializationExtensionInterface*, this);
398         iface = OSCL_STATIC_CAST(PVInterface*, myInterface);
399         addRef();
400         return true;
401     }
402     else if (uuid == PVMIDatastreamuserInterfaceUuid)
403     {
404         PVMIDatastreamuserInterface* myInterface = OSCL_STATIC_CAST(PVMIDatastreamuserInterface*, this);
405         iface = OSCL_STATIC_CAST(PVInterface*, myInterface);
406         addRef();
407         return true;
408     }
409     else if (uuid == KPVMFProtocolEngineNodeExtensionUuid)
410     {
411         PVMFProtocolEngineNodeExtensionInterface* myInterface = OSCL_STATIC_CAST(PVMFProtocolEngineNodeExtensionInterface*, this);
412         iface = OSCL_STATIC_CAST(PVInterface*, myInterface);
413         addRef();
414         return true;
415     }
416     else if (uuid == PVMF_DOWNLOAD_PROGRESS_INTERFACE_UUID)
417     {
418         PVMFDownloadProgressInterface* myInterface = OSCL_STATIC_CAST(PVMFDownloadProgressInterface*, this);
419         iface = OSCL_STATIC_CAST(PVInterface*, myInterface);
420         addRef();
421         return true;
422     }
423     else if (uuid == KPVMFProtocolEngineNodeMSHTTPStreamingExtensionUuid)
424     {
425         PVMFProtocolEngineNodeMSHTTPStreamingExtensionInterface* myInterface = OSCL_STATIC_CAST(PVMFProtocolEngineNodeMSHTTPStreamingExtensionInterface*, this);
426         iface = OSCL_STATIC_CAST(PVInterface*, myInterface);
427         addRef();
428         return true;
429     }
430     else if (uuid == PVMF_TRACK_SELECTION_INTERFACE_UUID)
431     {
432         if (!iInterfacingObjectContainer || iInterfacingObjectContainer->getDownloadFormat() != PVMF_MIME_DATA_SOURCE_PVX_FILE) return false;
433         PVMFTrackSelectionExtensionInterface* myInterface = OSCL_STATIC_CAST(PVMFTrackSelectionExtensionInterface*, this);
434         iface = OSCL_STATIC_CAST(PVInterface*, myInterface);
435         addRef();
436         return true;
437     }
438 
439     return false;
440 }
441 
442 /**
443 //This routine is called by various command APIs to queue an
444 //asynchronous command for processing by the command handler AO.
445 //This function may leave if the command can't be queued due to
446 //memory allocation failure.
447 */
QueueCommandL(PVMFProtocolEngineNodeCommand & aCmd)448 PVMFCommandId PVMFProtocolEngineNode::QueueCommandL(PVMFProtocolEngineNodeCommand& aCmd)
449 {
450     PVMFCommandId id = iInputCommands.AddL(aCmd);
451 
452     //wakeup the AO
453     RunIfNotReady();
454     return id;
455 }
456 
FindCmd(PVMFProtocolEngineNodeCmdQ & aCmdQueue,int32 aCmdId)457 PVMFProtocolEngineNodeCommand* PVMFProtocolEngineNode::FindCmd(PVMFProtocolEngineNodeCmdQ &aCmdQueue, int32 aCmdId)
458 {
459     for (uint32 i = 0; i < aCmdQueue.size(); i++)
460     {
461         if (aCmdQueue[i].iCmd == aCmdId) return &aCmdQueue[i];
462     }
463     return NULL;
464 }
465 
466 /**
467 /////////////////////////////////////////////////////
468 // Asynchronous Command processing routines.
469 // These routines are all called under the AO.
470 /////////////////////////////////////////////////////
471 */
472 
473 /**
474 //Called by the command handler AO to process a command from
475 //the input queue.
476 //Return true if a command was processed, false if the command
477 //processor is busy and can't process another command now.
478 */
ProcessCommand(PVMFProtocolEngineNodeCommand & aCmd)479 bool PVMFProtocolEngineNode::ProcessCommand(PVMFProtocolEngineNodeCommand& aCmd)
480 {
481     //normally this node will not start processing one command
482     //until the prior one is finished.  However, a hi priority
483     //command such as Cancel must be able to interrupt a command
484     //in progress.
485     if (!iCurrentCommand.empty() && !aCmd.hipri())
486     {
487         return false; // keep waiting
488     }
489 
490     PVMFStatus cmdStatus;
491     switch (aCmd.iCmd)
492     {
493         case PVMF_GENERIC_NODE_REQUESTPORT:
494             cmdStatus = DoRequestPort(aCmd);
495             break;
496 
497         case PVMF_GENERIC_NODE_RELEASEPORT:
498             cmdStatus = DoReleasePort(aCmd);
499             break;
500 
501         case PVMF_GENERIC_NODE_QUERYUUID:
502             cmdStatus = DoQueryUuid(aCmd);
503             break;
504 
505         case PVMF_GENERIC_NODE_QUERYINTERFACE:
506             cmdStatus = DoQueryInterface(aCmd);
507             break;
508 
509         case PVMF_GENERIC_NODE_INIT:
510             cmdStatus = DoInit(aCmd);
511             break;
512 
513         case PVMF_GENERIC_NODE_PREPARE:
514             cmdStatus = DoPrepare(aCmd);
515             break;
516 
517         case PVMF_GENERIC_NODE_START:
518             cmdStatus = DoStart(aCmd);
519             break;
520 
521         case PVMF_GENERIC_NODE_STOP:
522             cmdStatus = DoStop(aCmd);
523             break;
524 
525         case PVMF_GENERIC_NODE_FLUSH:
526             cmdStatus = DoFlush(aCmd);
527             break;
528 
529         case PVMF_GENERIC_NODE_PAUSE:
530             cmdStatus = DoPause(aCmd);
531             break;
532 
533         case PVMF_GENERIC_NODE_RESET:
534             cmdStatus = DoReset(aCmd);
535             break;
536 
537         case PVMF_GENERIC_NODE_CANCELALLCOMMANDS:
538             cmdStatus = DoCancelAllCommands(aCmd);
539             break;
540 
541         case PVMF_GENERIC_NODE_CANCELCOMMAND:
542             cmdStatus = DoCancelCommand(aCmd);
543             break;
544 
545         case PVPROTOCOLENGINE_NODE_CMD_SEEK:
546             cmdStatus = DoSeek(aCmd);
547             break;
548 
549         case PVPROTOCOLENGINE_NODE_CMD_BITSTREAM_SWITCH:
550             cmdStatus = DoBitsteamSwitch(aCmd);
551             break;
552 
553         case PVPROTOCOLENGINE_NODE_CMD_DATASTREAM_REQUEST_REPOSITION:
554             cmdStatus = DoReposition(aCmd);
555             break;
556 
557         default://unknown command type. Assert and treat as not supported error
558             OSCL_ASSERT(false);
559             CommandComplete(iInputCommands, aCmd, PVMFErrNotSupported);
560             cmdStatus = PVMFErrNotSupported;
561             break;
562     }
563 
564     //If completion is pending, move the command from the input queue to the current command.
565     //This is necessary since the input queue could get rearranged by new commands coming in.
566     if (cmdStatus == PVMFPending)
567     {
568         iCurrentCommand.StoreL(aCmd);
569         iInputCommands.Erase(&aCmd);
570     }
571 
572     return true;
573 }
574 
575 /**
576 //The various command handlers call this when a command is complete.
577 */
HandleCommandComplete(PVMFProtocolEngineNodeCmdQ & aCmdQ,PVMFProtocolEngineNodeCommand & aCmd,int32 aStatus)578 int32 PVMFProtocolEngineNode::HandleCommandComplete(PVMFProtocolEngineNodeCmdQ& aCmdQ,
579         PVMFProtocolEngineNodeCommand& aCmd,
580         int32 aStatus)
581 {
582     if (aStatus == PVMFPending) return PVMFPending;
583     if (aStatus > 0 || IsPVMFErrCode(aStatus))
584     {
585         CommandComplete(aCmdQ, aCmd, aStatus); // no extension error code in case of error
586         return aStatus;
587     }
588 
589     // should be PE node extension error code
590     PVUuid uuid = PVProtocolEngineNodeErrorEventTypesUUID;
591     // Check for error code for not enough disk space
592     int32 pvmfReturnCode = PVMFFailure;
593     if (aStatus == PROCESS_DATA_STREAM_OPEN_FAILURE) pvmfReturnCode = PVMFErrResource;
594     int32 errorCode = (int32)PVProtocolEngineNodeErrorProcessingFailure - (PROCESS_ERROR_FIRST - aStatus);
595     CommandComplete(aCmdQ, aCmd, pvmfReturnCode, NULL, &uuid, &errorCode);
596     return pvmfReturnCode;
597 }
598 
599 
CommandComplete(PVMFProtocolEngineNodeCmdQ & aCmdQ,PVMFProtocolEngineNodeCommand & aCmd,PVMFStatus aStatus,OsclAny * aEventData,PVUuid * aEventUUID,int32 * aEventCode,int32 aEventDataLen)600 void PVMFProtocolEngineNode::CommandComplete(PVMFProtocolEngineNodeCmdQ& aCmdQ,
601         PVMFProtocolEngineNodeCommand& aCmd,
602         PVMFStatus aStatus,
603         OsclAny* aEventData,
604         PVUuid* aEventUUID,
605         int32* aEventCode,
606         int32 aEventDataLen)
607 
608 {
609     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFProtocolEngineNode:CommandComplete Id %d Cmd %d Status %d Context %d Data %d"
610                     , aCmd.iId, aCmd.iCmd, aStatus, aCmd.iContext, aEventData));
611 
612     PVInterface* extif = NULL;
613     PVMFBasicErrorInfoMessage* errormsg = NULL;
614     if (aEventUUID && aEventCode)
615     {
616         errormsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (*aEventCode, *aEventUUID, NULL));
617         extif = OSCL_STATIC_CAST(PVInterface*, errormsg);
618     }
619 
620     //create response
621     PVMFCmdResp resp(aCmd.iId, aCmd.iContext, aStatus, extif, aEventData);
622     if (aEventDataLen != 0)
623     {
624         resp.SetEventDataLen(aEventDataLen);
625     }
626 
627     PVMFSessionId session = aCmd.iSession;
628 
629     //Erase the command from the queue.
630     aCmdQ.Erase(&aCmd);
631 
632     //Report completion to the session observer.
633     ReportCmdCompleteEvent(session, resp);
634 
635     if (errormsg) errormsg->removeRef();
636 }
637 
638 
639 /**
640 //Called by the command handler AO to do the node Reset.
641 */
DoReset(PVMFProtocolEngineNodeCommand & aCmd)642 PVMFStatus PVMFProtocolEngineNode::DoReset(PVMFProtocolEngineNodeCommand& aCmd)
643 {
644     LOGINFO((0, "PVMFProtocolEngineNode::DoReset()"));
645 
646     // Allow a reset on ANY state.
647     ResetClear(true); // true means deleting the relevant objects
648 
649     // Logoff and go back to Created state.
650     SetState(EPVMFNodeIdle);
651     PVMFStatus  status = ThreadLogoff();
652     CommandComplete(iInputCommands, aCmd, status);
653     return status;
654 }
655 
656 
657 /**
658 //Called by the command handler AO to do the port request
659 */
DoRequestPort(PVMFProtocolEngineNodeCommand & aCmd)660 PVMFStatus PVMFProtocolEngineNode::DoRequestPort(PVMFProtocolEngineNodeCommand& aCmd)
661 {
662     LOGINFO((0, "PVMFProtocolEngineNode::DoRequestPort()"));
663 
664     //This node supports port request from any state
665 
666     //retrieve port tag.
667     int32 tag;
668     OSCL_String* mimetype;
669     aCmd.PVMFProtocolEngineNodeCommandBase::Parse(tag, mimetype);
670 
671     //(mimetype is not used on this node)
672 
673     //validate the tag...
674     switch (tag)
675     {
676         case PVMF_PROTOCOLENGINENODE_PORT_TYPE_INPUT:
677         case PVMF_PROTOCOLENGINENODE_PORT_TYPE_OUTPUT:
678         case PVMF_PROTOCOLENGINENODE_PORT_TYPE_FEEDBACK:
679             break;
680 
681         default:
682         {
683             //bad port tag
684             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
685                             (0, "PVMFProtocolEngineNode::DoRequestPort: Error - Invalid port tag"));
686             CommandComplete(iInputCommands, aCmd, PVMFFailure);
687             return PVMFFailure;
688         }
689         // break;   This statement was removed to avoid compiler warning for Unreachable Code
690     }
691 
692     //Allocate a new port
693     OsclAny *ptr = NULL;
694     int32 err;
695     OSCL_TRY(err, ptr = iPortVector.Allocate(););
696     if (err != OsclErrNone || !ptr)
697     {
698         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
699                         (0, "PVMFProtocolEngineNode::DoRequestPort: Error - iPortVector Out of memory"));
700         CommandComplete(iInputCommands, aCmd, PVMFErrNoMemory);
701         return PVMFErrNoMemory;
702     }
703 
704     //create base port with default settings...
705     PVMFProtocolEnginePort*port = NULL;
706     switch (tag)
707     {
708         case PVMF_PROTOCOLENGINENODE_PORT_TYPE_INPUT:
709         case PVMF_PROTOCOLENGINENODE_PORT_TYPE_FEEDBACK:
710             //create base port with default settings...
711             port = new(ptr) PVMFProtocolEnginePort(tag, this,
712                                                    DEFAULT_DATA_QUEUE_CAPACITY,
713                                                    DEFAULT_DATA_QUEUE_CAPACITY,
714                                                    DEFAULT_READY_TO_RECEIVE_THRESHOLD_PERCENT,
715                                                    DEFAULT_DATA_QUEUE_CAPACITY,
716                                                    DEFAULT_DATA_QUEUE_CAPACITY,
717                                                    DEFAULT_READY_TO_RECEIVE_THRESHOLD_PERCENT,
718                                                    "ProtocolEngineIn(Protocol)");
719 
720             if (tag == PVMF_PROTOCOLENGINENODE_PORT_TYPE_INPUT)     iPortInForData = port;
721             if (tag == PVMF_PROTOCOLENGINENODE_PORT_TYPE_FEEDBACK)  iPortInForLogging = port;
722             break;
723 
724         case PVMF_PROTOCOLENGINENODE_PORT_TYPE_OUTPUT:
725             port = new(ptr) PVMFProtocolEnginePort(tag, this,
726                                                    0, 0, 0, // input queue isn't needed.
727                                                    DEFAULT_DATA_QUEUE_CAPACITY,
728                                                    DEFAULT_DATA_QUEUE_CAPACITY,
729                                                    DEFAULT_READY_TO_RECEIVE_THRESHOLD_PERCENT,
730                                                    "ProtocolEngineOut(Protocol)");
731 
732             iPortOut = port;
733             break;
734     }
735 
736     iPortActivityQueue.reserve(PVMF_PROTOCOLENGINE_NODE_COMMAND_VECTOR_RESERVE);
737 
738     //Add the port to the port vector.
739     OSCL_TRY(err, iPortVector.AddL(port););
740     if (err != OsclErrNone)
741     {
742         iPortInForData = iPortInForLogging = iPortOut = NULL;
743         OSCL_DELETE(port);
744         CommandComplete(iInputCommands, aCmd, PVMFErrNoMemory);
745         return PVMFErrNoMemory;
746     }
747 
748     //Return the port pointer to the caller.
749     CommandComplete(iInputCommands, aCmd, PVMFSuccess, (OsclAny*)port, 0, 0, sizeof(PVMFProtocolEnginePort));
750     return PVMFSuccess;
751 }
752 
753 /**
754 //Called by the command handler AO to do the port release
755 */
DoReleasePort(PVMFProtocolEngineNodeCommand & aCmd)756 PVMFStatus PVMFProtocolEngineNode::DoReleasePort(PVMFProtocolEngineNodeCommand& aCmd)
757 {
758     LOGINFO((0, "PVMFProtocolEngineNode::DoReleasePort()"));
759 
760     //This node supports release port from any state
761     PVMFStatus status = PVMFSuccess;
762 
763     //Find the port in the port vector
764     PVMFPortInterface* p = NULL;
765     aCmd.PVMFProtocolEngineNodeCommandBase::Parse(p);
766 
767     PVMFProtocolEnginePort* port = (PVMFProtocolEnginePort*)p;
768 
769 
770     if (port == NULL) status = PVMFErrArgument;
771 
772     PVMFProtocolEnginePort** portPtr = iPortVector.FindByValue(port);
773     if (portPtr)
774     {
775         if (*portPtr == iPortInForData) iPortInForData = NULL;
776         if (*portPtr == iPortInForLogging) iPortInForLogging = NULL;
777         if (*portPtr == iPortOut)           iPortOut = NULL;
778 
779         Clear(true);
780 
781         //delete the port.
782         iPortVector.Erase(portPtr);
783         status = PVMFSuccess;
784     }
785     else
786     {
787         //port not found.
788         status = PVMFErrArgument;
789     }
790 
791     CommandComplete(iInputCommands, aCmd, status);
792     return status;
793 }
794 
795 
DoQueryUuid(PVMFProtocolEngineNodeCommand & aCmd)796 PVMFStatus PVMFProtocolEngineNode::DoQueryUuid(PVMFProtocolEngineNodeCommand& aCmd)
797 {
798     LOGINFO((0, "PVMFProtocolEngineNode::DoQueryUuid()"));
799 
800     //This node supports Query UUID from any state
801     OSCL_String* mimetype;
802     Oscl_Vector<PVUuid, OsclMemAllocator> *uuidvec;
803     bool exactmatch;
804     aCmd.PVMFProtocolEngineNodeCommandBase::Parse(mimetype, uuidvec, exactmatch);
805 
806     //TODO: Try to match the input mimetype against any of
807     //the custom interfaces for this node
808     PVUuid uuid1(PVMF_DATA_SOURCE_INIT_INTERFACE_UUID);
809     uuidvec->push_back(uuid1);
810     PVUuid uuid2(PVMIDatastreamuserInterfaceUuid);
811     uuidvec->push_back(uuid2);
812     PVUuid uuid3(KPVMFProtocolEngineNodeExtensionUuid);
813     uuidvec->push_back(uuid3);
814     PVUuid uuid4(PVMF_DOWNLOAD_PROGRESS_INTERFACE_UUID);
815     uuidvec->push_back(uuid4);
816     PVUuid uuid5(KPVMFProtocolEngineNodeMSHTTPStreamingExtensionUuid);
817     uuidvec->push_back(uuid5);
818     PVUuid uuid6(PVMF_TRACK_SELECTION_INTERFACE_UUID);
819     uuidvec->push_back(uuid6);
820 
821     CommandComplete(iInputCommands, aCmd, PVMFSuccess);
822     return PVMFSuccess;
823 }
824 
825 
DoQueryInterface(PVMFProtocolEngineNodeCommand & aCmd)826 PVMFStatus PVMFProtocolEngineNode::DoQueryInterface(PVMFProtocolEngineNodeCommand&  aCmd)
827 {
828     LOGINFO((0, "PVMFProtocolEngineNode::DoQueryInterface()"));
829 
830     PVUuid* uuid;
831     PVInterface** ptr;
832     aCmd.PVMFProtocolEngineNodeCommandBase::Parse(uuid, ptr);
833     PVMFStatus status = PVMFSuccess;
834     if (!queryInterface(*uuid, *ptr))
835     {
836         //Not supported
837         *ptr = NULL;
838         status = PVMFFailure;
839     }
840 
841     CommandComplete(iInputCommands, aCmd, status);
842     return status;
843 }
844 
845 
846 /**
847 //Called by the command handler AO to do the node Init
848 */
DoInit(PVMFProtocolEngineNodeCommand & aCmd)849 PVMFStatus PVMFProtocolEngineNode::DoInit(PVMFProtocolEngineNodeCommand& aCmd)
850 {
851     LOGINFO((0, "PVMFProtocolEngineNode::DoInit()"));
852 
853     PVMFStatus status = PVMFSuccess;
854     // exceptional cases
855     if (!iProtocolContainer) status = PVMFFailure;
856     if (iInterfaceState != EPVMFNodeIdle) status = PVMFErrInvalidState;
857     PassInObjects();
858 
859     // normal case
860     if (iInterfaceState == EPVMFNodeIdle && iProtocolContainer)
861     {
862         // do init, if init is async call, then return PVMFPending
863         if ((status = iProtocolContainer->doInit()) == PVMFSuccess)
864         {
865             SetState(EPVMFNodeInitialized);
866         }
867     }
868     return HandleCommandComplete(iInputCommands, aCmd, status);
869 }
870 
PassInObjects()871 void PVMFProtocolEngineNode::PassInObjects()
872 {
873     iProtocolContainer->setSupportObject((OsclAny*)iPortInForData, NodeObjectType_InputPortForData);
874     iProtocolContainer->setSupportObject((OsclAny*)iPortInForLogging, NodeObjectType_InputPortForLogging);
875     iProtocolContainer->setSupportObject((OsclAny*)iPortOut, NodeObjectType_OutPort);
876     iProtocolContainer->setSupportObject((OsclAny*)(&iInternalEventQueue), NodeObjectType_InternalEventQueue);
877 }
878 
879 
880 /**
881 //Called by the command handler AO to do the node Prepare
882 */
DoPrepare(PVMFProtocolEngineNodeCommand & aCmd)883 PVMFStatus PVMFProtocolEngineNode::DoPrepare(PVMFProtocolEngineNodeCommand& aCmd)
884 {
885     LOGINFO((0, "PVMFProtocolEngineNode::DoPrepare()"));
886     if (!iProtocolContainer)    return PVMFFailure;
887 
888     PVMFStatus status = PVMFSuccess; //PVMFPending;
889     PassInObjects();
890     switch (iInterfaceState)
891     {
892         case EPVMFNodeInitialized:
893         {
894             status = iProtocolContainer->doPrepare();
895             if (status == PVMFSuccess) SetState(EPVMFNodePrepared);
896             break;
897         }
898         default:
899             status = PVMFErrInvalidState;
900             break;
901     }
902 
903     return HandleCommandComplete(iInputCommands, aCmd, status);
904 }
905 
906 
907 /**
908 //Called by the command handler AO to do the node Start
909 */
DoStart(PVMFProtocolEngineNodeCommand & aCmd)910 PVMFStatus PVMFProtocolEngineNode::DoStart(PVMFProtocolEngineNodeCommand& aCmd)
911 {
912     LOGINFO((0, "PVMFProtocolEngineNode::DoStart()"));
913     LOGINFODATAPATH((0, "PVMFProtocolEngineNode::DoStart() : Start command gets called and executed, iInterfaceState=%d, currSocketConnection=%d",
914                      (int32)iInterfaceState, (uint32)iInterfacingObjectContainer->isSocketConnectionUp()));
915 
916     // check if download/streaming is done, if it is done, no need to start/resume download/streaming
917     if (CheckAvailabilityOfDoStart(aCmd)) return PVMFSuccess;
918 
919     PVMFStatus status = PVMFSuccess;
920     iProcessingState = ProcessingState_NormalDataflow;
921     iInterfacingObjectContainer->setInputDataUnwanted(false);
922     switch (iInterfaceState)
923     {
924         case EPVMFNodePrepared:
925         {
926             if (iProtocolContainer->doPreStart() == PROCESS_SUCCESS)
927             {
928                 // do socket reconnect for init->start, prepare->start and stop->start
929                 // for pause->start, no need. For seek, no start command is issued. doseek() will
930                 // do socket reconnect
931                 iProtocolContainer->startDataFlowByCommand(iProtocolContainer->needSocketReconnect()); // make start command (prepare->start) asynchonous
932 
933                 // Transition to BeingStarted
934                 // intentionally set node state as this node internal state to ignore any left-over messages from POST port from previous stop or EOS handling
935                 SetState((TPVMFNodeInterfaceState)PVMFProtocolEngineNodeState_BeingStarted);
936 
937                 return PVMFPending;
938             }
939             status = PVMFSuccess;
940             break;
941         }
942 
943         case EPVMFNodePaused:
944         {
945             // Transition to BeingStarted
946             // intentionally set node state as this node internal state to ignore any left-over messages from POST port because currently node is paused state.
947             // need to differentiate this case from the paused case.
948             SetState((TPVMFNodeInterfaceState)PVMFProtocolEngineNodeState_BeingStarted);
949 
950             iProtocol->resume();
951             iProtocolContainer->startDataFlowByCommand();
952             return PVMFPending;
953 
954             // break;   This statement was removed to avoid compiler warning for Unreachable Code
955         }
956 
957         /*
958          * If the node is already started just return success - multiple starts can happen with
959          * flow control (auto-pause / auto-resume) scenarios
960          */
961         case EPVMFNodeStarted:
962             status = PVMFSuccess;
963             break;
964 
965         default:
966             status = PVMFErrInvalidState;
967             break;
968     }
969 
970     CommandComplete(iInputCommands, aCmd, status);
971     return status;
972 }
973 
CheckAvailabilityOfDoStart(PVMFProtocolEngineNodeCommand & aCmd)974 bool PVMFProtocolEngineNode::CheckAvailabilityOfDoStart(PVMFProtocolEngineNodeCommand& aCmd)
975 {
976     // check if download/streaming is done, if it is done, no need to start/resume download/streaming
977     if (iInterfacingObjectContainer->isDownloadStreamingDone())
978     {
979         SetState(EPVMFNodeStarted);
980         CommandComplete(iInputCommands, aCmd, PVMFSuccess);
981         return true;
982     }
983     return false;
984 }
985 
986 /**
987 //Called by the command handler AO to do the node Pause
988 */
DoPause(PVMFProtocolEngineNodeCommand & aCmd)989 PVMFStatus PVMFProtocolEngineNode::DoPause(PVMFProtocolEngineNodeCommand& aCmd)
990 {
991     LOGINFO((0, "PVMFProtocolEngineNode::DoPause()"));
992     LOGINFODATAPATH((0, "PVMFProtocolEngineNode::DoPause() : Pause command gets called and executed, iInterfaceState=%d", (int32)iInterfaceState));
993 
994     PVMFStatus status = PVMFSuccess;
995     switch (iInterfaceState)
996     {
997         case EPVMFNodeStarted:
998         {
999             TPVMFNodeInterfaceState prevState = iInterfaceState;
1000             SetState(EPVMFNodePaused);
1001             if (!iProtocolContainer->doPause())
1002             {
1003                 SetState(prevState);
1004                 status = PVMFFailure;
1005             }
1006         }
1007         break;
1008 
1009         case EPVMFNodePaused:
1010             status = PVMFSuccess;
1011 
1012         default:
1013             status = PVMFErrInvalidState;
1014             break;
1015     }
1016 
1017     CommandComplete(iInputCommands, aCmd, status);
1018     return status;
1019 }
1020 
1021 /**
1022 //Called by the command handler AO to do the node Seek
1023 */
DoSeek(PVMFProtocolEngineNodeCommand & aCmd)1024 PVMFStatus PVMFProtocolEngineNode::DoSeek(PVMFProtocolEngineNodeCommand& aCmd)
1025 {
1026     return iProtocolContainer->doSeek(aCmd);
1027 }
1028 
1029 
1030 /**
1031 //Called by the command handler AO to do the node BitstreamSwitch
1032 */
DoBitsteamSwitch(PVMFProtocolEngineNodeCommand & aCmd)1033 PVMFStatus PVMFProtocolEngineNode::DoBitsteamSwitch(PVMFProtocolEngineNodeCommand& aCmd)
1034 {
1035     return iProtocolContainer->doBitstreamSwitch(aCmd);
1036 }
1037 
DoReposition(PVMFProtocolEngineNodeCommand & aCmd)1038 PVMFStatus PVMFProtocolEngineNode::DoReposition(PVMFProtocolEngineNodeCommand& aCmd)
1039 {
1040     return iProtocolContainer->doSeek(aCmd);
1041 }
1042 
1043 /**
1044 //Called by the command handler AO to do the node Stop
1045 */
DoStop(PVMFProtocolEngineNodeCommand & aCmd)1046 PVMFStatus PVMFProtocolEngineNode::DoStop(PVMFProtocolEngineNodeCommand& aCmd)
1047 {
1048     LOGINFO((0, "PVMFProtocolEngineNode::DoStop()"));
1049     LOGINFODATAPATH((0, "PVMFProtocolEngineNode::Stop() : Stop command gets called, iInterfaceState=%d", (int32)iInterfaceState));
1050 
1051     PVMFStatus status = PVMFSuccess;
1052     switch (iInterfaceState)
1053     {
1054         case EPVMFNodeStarted:
1055         case EPVMFNodePaused:
1056 
1057             status = iProtocolContainer->doStop();
1058             if (status == PVMFPending) return PVMFPending;
1059             if (status == PVMFSuccess)
1060             {
1061 
1062                 StopClear();
1063                 // Transition to Prepared state
1064                 SetState(EPVMFNodePrepared);
1065             }
1066             break;
1067 
1068         case EPVMFNodeError:
1069             SetState(EPVMFNodePrepared);
1070             break;
1071 
1072         default:
1073             status = PVMFErrInvalidState;
1074             break;
1075     }
1076 
1077     CommandComplete(iInputCommands, aCmd, status);
1078     return status;
1079 }
1080 
1081 /**
1082 //Called by the command handler AO to do the node Flush
1083 */
DoFlush(PVMFProtocolEngineNodeCommand & aCmd)1084 PVMFStatus PVMFProtocolEngineNode::DoFlush(PVMFProtocolEngineNodeCommand& aCmd)
1085 {
1086     LOGINFO((0, "PVMFProtocolEngineNode::DoFlush()"));
1087 
1088     switch (iInterfaceState)
1089     {
1090         case EPVMFNodeStarted:
1091         case EPVMFNodePaused:
1092         {
1093             //the flush is asynchronous. Move the command from
1094             //the input command queue to the current command, where
1095             //it will remain until the flush completes.
1096             int32 err;
1097             OSCL_TRY(err, iCurrentCommand.StoreL(aCmd););
1098             if (err != OsclErrNone)
1099             {
1100                 CommandComplete(iInputCommands, aCmd, PVMFErrNoMemory);
1101                 return PVMFErrNoMemory;
1102             }
1103             iInputCommands.Erase(&aCmd);
1104 
1105             //Notify all ports to suspend their input
1106             for (uint32 i = 0; i < iPortVector.size(); i++)
1107             {
1108                 iPortVector[i]->SuspendInput();
1109             }
1110         }
1111 
1112         break;
1113 
1114         default:
1115             CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState);
1116             return PVMFErrInvalidState;
1117             // break;   This statement was removed to avoid compiler warning for Unreachable Code
1118     }
1119     return PVMFSuccess;
1120 }
1121 
1122 /**
1123 //A routine to tell if a flush operation is in progress.
1124 */
FlushPending()1125 bool PVMFProtocolEngineNode::FlushPending()
1126 {
1127     return (iCurrentCommand.size() > 0 &&
1128             iCurrentCommand.front().iCmd == PVMF_GENERIC_NODE_FLUSH);
1129 }
1130 
1131 
1132 /**
1133 //Called by the command handler AO to do the Cancel All
1134 */
DoCancelAllCommands(PVMFProtocolEngineNodeCommand & aCmd)1135 PVMFStatus PVMFProtocolEngineNode::DoCancelAllCommands(PVMFProtocolEngineNodeCommand& aCmd)
1136 {
1137     LOGINFO((0, "PVMFProtocolEngineNode::DoCancelAllCommands()"));
1138 
1139     //first cancel the current command if any
1140     while (!iCurrentCommand.empty())
1141     {
1142         CancelClear();
1143         CommandComplete(iCurrentCommand, iCurrentCommand[0], PVMFErrCancelled);
1144     }
1145 
1146     //next cancel all queued commands
1147     //start at element 1 since this cancel command is element 0.
1148     while (iInputCommands.size() > 1)
1149     {
1150         CancelClear();
1151         CommandComplete(iInputCommands, iInputCommands[1], PVMFErrCancelled);
1152     }
1153 
1154     //finally, report cancel complete.
1155     CommandComplete(iInputCommands, aCmd, PVMFSuccess);
1156     if (iInterfacingObjectContainer) iInterfacingObjectContainer->setCancelCmdHappened();
1157     if (iInterfacingObjectContainer) iInterfacingObjectContainer->setInputDataUnwanted();
1158     return PVMFSuccess;
1159 }
1160 
1161 /**
1162 //Called by the command handler AO to do the Cancel single command
1163 */
DoCancelCommand(PVMFProtocolEngineNodeCommand & aCmd)1164 PVMFStatus PVMFProtocolEngineNode::DoCancelCommand(PVMFProtocolEngineNodeCommand& aCmd)
1165 {
1166     LOGINFO((0, "PVMFProtocolEngineNode::DoCancelCommand()"));
1167 
1168     //extract the command ID from the parameters.
1169     PVMFCommandId id;
1170     aCmd.PVMFProtocolEngineNodeCommandBase::Parse(id);
1171     if (iInterfacingObjectContainer) iInterfacingObjectContainer->setInputDataUnwanted();
1172 
1173     // first check "current" command if any, and check the input queue starting
1174     // at element 1 since this cancel command is element 0.
1175     PVMFProtocolEngineNodeCommand* cmd = iCurrentCommand.FindById(id);
1176     if (cmd)
1177     {
1178         CancelClear();
1179         //cancel the queued command
1180         CommandComplete(iCurrentCommand, *cmd, PVMFErrCancelled);
1181         //report cancel success
1182         CommandComplete(iInputCommands, aCmd, PVMFSuccess);
1183         return PVMFSuccess;
1184     }
1185 
1186     //next check input queue.
1187     //start at element 1 since this cancel command is element 0.
1188     cmd = iInputCommands.FindById(id, 1);
1189     if (cmd)
1190     {
1191         CancelClear();
1192         //cancel the queued command
1193         CommandComplete(iInputCommands, *cmd, PVMFErrCancelled);
1194         //report cancel success
1195         CommandComplete(iInputCommands, aCmd, PVMFSuccess);
1196         return PVMFSuccess;
1197     }
1198 
1199     //at this point, nothing needs to be cancelled and thus report cancel complete
1200     CommandComplete(iInputCommands, aCmd, PVMFSuccess);
1201     // set cancel cmd happened flag for stop command processing
1202     if (iInterfacingObjectContainer) iInterfacingObjectContainer->setCancelCmdHappened();
1203     if (iInterfacingObjectContainer) iInterfacingObjectContainer->setInputDataUnwanted();
1204     return PVMFSuccess;
1205 }
1206 
1207 
1208 /////////////////////////////////////////////////////
1209 // Event reporting routines.
1210 /////////////////////////////////////////////////////
SetState(TPVMFNodeInterfaceState s)1211 void PVMFProtocolEngineNode::SetState(TPVMFNodeInterfaceState s)
1212 {
1213     LOGINFO((0, "PVMFProtocolEngineNode::SetState() %d", s));
1214     PVMFNodeInterface::SetState(s);
1215 }
1216 
ReportInfoEvent(PVMFEventType aEventType,OsclAny * aEventData,const int32 aEventCode,OsclAny * aEventLocalBuffer,const uint32 aEventLocalBufferSize)1217 void PVMFProtocolEngineNode::ReportInfoEvent(PVMFEventType aEventType, OsclAny* aEventData, const int32 aEventCode, OsclAny* aEventLocalBuffer, const uint32 aEventLocalBufferSize)
1218 {
1219     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFProtocolEngineNode:NodeInfoEvent Type %d Data %d",
1220                     aEventType, aEventData));
1221 
1222     if (aEventCode == 0)
1223     {
1224         //report basic event, no extended event
1225         PVMFNodeInterface::ReportInfoEvent(aEventType, aEventData);
1226     }
1227     else
1228     {
1229         //report extended event.
1230         PVUuid uuid = PVMFPROTOCOLENGINENODEInfoEventTypesUUID;
1231         PVMFBasicErrorInfoMessage *msg = OSCL_NEW(PVMFBasicErrorInfoMessage, (aEventCode, uuid, NULL));
1232 
1233         PVMFAsyncEvent event(PVMFInfoEvent,
1234                              aEventType,
1235                              NULL, //context
1236                              msg,
1237                              aEventData,
1238                              (uint8*)aEventLocalBuffer,
1239                              aEventLocalBufferSize);
1240 
1241         //report to the session observers.
1242         PVMFNodeInterface::ReportInfoEvent(event);
1243 
1244         //remove the ref to the extended response
1245         if (msg) msg->removeRef();
1246     }
1247 }
1248 
ReportErrorEvent(PVMFEventType aEventType,OsclAny * aEventData,const int32 aEventCode,int32 aEventDataLen)1249 void PVMFProtocolEngineNode::ReportErrorEvent(PVMFEventType aEventType,
1250         OsclAny* aEventData,
1251         const int32 aEventCode,
1252         int32 aEventDataLen)
1253 {
1254     LOGINFO((0, "PVMFProtocolEngineNode::ReportErrorEvent() Type %d Data %d"
1255              , aEventType, aEventData));
1256 
1257     PVMFBasicErrorInfoMessage*msg  = NULL;
1258 
1259     if (aEventCode != 0)
1260     {
1261         // extended error event with aEventCode
1262         PVUuid uuid = PVProtocolEngineNodeErrorEventTypesUUID;
1263         msg = OSCL_NEW(PVMFBasicErrorInfoMessage, (aEventCode, uuid, NULL));
1264     }
1265 
1266     PVMFAsyncEvent event(PVMFErrorEvent,
1267                          aEventType,
1268                          NULL, // context
1269                          msg,
1270                          aEventData,
1271                          NULL,
1272                          0);
1273 
1274     if (aEventDataLen != 0)
1275         event.SetEventDataLen(aEventDataLen);
1276 
1277     PVMFNodeInterface::ReportErrorEvent(event);
1278     if (msg) msg->removeRef();
1279 
1280 }
1281 
1282 /////////////////////////////////////////////////////
1283 // Port Processing routines
1284 /////////////////////////////////////////////////////
1285 
QueuePortActivity(const PVMFPortActivity & aActivity)1286 void PVMFProtocolEngineNode::QueuePortActivity(const PVMFPortActivity &aActivity)
1287 {
1288     //queue a new port activity event
1289     int32 err;
1290     OSCL_TRY(err, iPortActivityQueue.push_back(aActivity););
1291     if (err != OsclErrNone)
1292     {
1293         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
1294                         (0, "PVMFProtocolEngineNode::QueuePortActivity() Error - iPortActivityQueue.push_back() failed"));
1295         ReportErrorEvent(PVMFErrPortProcessing, (OsclAny*)(aActivity.iPort), sizeof(PVMFProtocolEnginePort));
1296     }
1297     else
1298     {
1299         //wake up the AO to process the port activity event.
1300         RunIfNotReady();
1301     }
1302 }
1303 
1304 
HandlePortActivity(const PVMFPortActivity & aActivity)1305 void PVMFProtocolEngineNode::HandlePortActivity(const PVMFPortActivity &aActivity)
1306 {
1307     LOGINFODATAPATH((0, "PVMFProtocolEngineNode::HandlePortActivity: port=0x%x, type=%d, IncomingQueueSize=%d, OutgoingQueueSize=%d, PAQSize=%d",
1308                      aActivity.iPort, aActivity.iType, aActivity.iPort->IncomingMsgQueueSize(), aActivity.iPort->OutgoingMsgQueueSize(), iPortActivityQueue.size()));
1309 
1310     //A port is reporting some activity or state change.  This code
1311     //figures out whether we need to  queue a processing event
1312     //for the AO, and/or report a node event to the observer.
1313 
1314     switch (aActivity.iType)
1315     {
1316         case PVMF_PORT_ACTIVITY_CREATED:
1317             //Report port created info event
1318             ReportInfoEvent(PVMFInfoPortCreated, (OsclAny*)aActivity.iPort);
1319             break;
1320 
1321         case PVMF_PORT_ACTIVITY_DELETED:
1322             //Report port deleted info event
1323             ReportInfoEvent(PVMFInfoPortDeleted, (OsclAny*)aActivity.iPort);
1324             //Purge any port activity events already queued
1325             //for this port.
1326             {
1327                 for (uint32 i = 0; i < iPortActivityQueue.size();)
1328                 {
1329                     if (iPortActivityQueue[i].iPort == aActivity.iPort)
1330                     {
1331                         iPortActivityQueue.erase(&iPortActivityQueue[i]);
1332                     }
1333                     else
1334                     {
1335                         i++;
1336                     }
1337                 }
1338             }
1339             break;
1340 
1341         case PVMF_PORT_ACTIVITY_CONNECT:
1342             //nothing needed.
1343             if ((PVMFProtocolEnginePort*)aActivity.iPort == iPortOut)
1344             {
1345                 LOGINFODATAPATH((0, "PVMFProtocolEngineNode::HandlePortActivity: port=0x%x, type=%d(PVMF_PORT_ACTIVITY_CONNECT), PE node output port connected to downstream node port!",
1346                                  aActivity.iPort, aActivity.iType));
1347                 iInterfacingObjectContainer->setOutputPortConnect();
1348             }
1349 
1350             break;
1351 
1352         case PVMF_PORT_ACTIVITY_DISCONNECT:
1353             //clear the node input queue when either port is disconnected.
1354             while (!iDataInQueue.empty())
1355             {
1356                 PVMFSharedMediaMsgPtr msg = iDataInQueue.front();
1357                 iDataInQueue.erase(iDataInQueue.begin());
1358                 ((PVMFProtocolEnginePort*)aActivity.iPort)->LogMediaMsgInfo(msg, "In Msg Cleared", iDataInQueue.size());
1359             }
1360 
1361             if ((PVMFProtocolEnginePort*)aActivity.iPort == iPortOut)
1362             {
1363                 LOGINFODATAPATH((0, "PVMFProtocolEngineNode::HandlePortActivity: port=0x%x, type=%d(PVMF_PORT_ACTIVITY_DISCONNECT), PE node output port disconnected from downstream node port!",
1364                                  aActivity.iPort, aActivity.iType));
1365                 iInterfacingObjectContainer->setOutputPortConnect(false);
1366             }
1367             break;
1368 
1369         case PVMF_PORT_ACTIVITY_OUTGOING_MSG:
1370             //An outgoing message was queued on this port.
1371             //We only need to queue a port activity event on the
1372             //first message.  Additional events will be queued during
1373             //the port processing as needed.
1374             if ((aActivity.iPort->OutgoingMsgQueueSize() == 1) ||
1375                     (iPortActivityQueue.size() == 0))
1376             {
1377                 QueuePortActivity(aActivity);
1378             }
1379             break;
1380 
1381         case PVMF_PORT_ACTIVITY_INCOMING_MSG:
1382             //An incoming message was queued on this port.
1383             //We only need to queue a port activity event on the
1384             //first message.  Additional events will be queued during
1385             //the port processing as needed.
1386             if ((aActivity.iPort->IncomingMsgQueueSize() == 1) ||
1387                     (iPortActivityQueue.size() == 0))
1388             {
1389                 QueuePortActivity(aActivity);
1390             }
1391             break;
1392 
1393         case PVMF_PORT_ACTIVITY_OUTGOING_QUEUE_BUSY:
1394             //Outgoing queue is now busy.
1395             //No action is needed here-- the node checks for
1396             //outgoing queue busy as needed during data processing.
1397             iProcessingState = ProcessingState_Idle; // disable data flow
1398             break;
1399 
1400         case PVMF_PORT_ACTIVITY_OUTGOING_QUEUE_READY:
1401             //Outgoing queue was previously busy, but is now ready.
1402             //it's time to start processing incoming data again.
1403             LOGINFODATAPATH((0, "PVMFProtocolEngineNode::HandlePortActivity() : PVMF_PORT_ACTIVITY_OUTGOING_QUEUE_READY, OutgoingQueueSize=%d",
1404                              aActivity.iPort->OutgoingMsgQueueSize()));
1405             ProcessOutgoingQueueReady();
1406             break;
1407 
1408         case PVMF_PORT_ACTIVITY_CONNECTED_PORT_BUSY:
1409             // The connected port has become busy (its incoming queue is
1410             // busy).
1411             // No action is needed here-- the port processing code
1412             // checks for connected port busy during data processing.
1413             break;
1414 
1415         case PVMF_PORT_ACTIVITY_CONNECTED_PORT_READY:
1416             // The connected port has transitioned from Busy to Ready.
1417             // It's time to start processing outgoing messages again.
1418             LOGINFODATAPATH((0, "PVMFProtocolEngineNode::HandlePortActivity() : PVMF_PORT_ACTIVITY_CONNECTED_PORT_READY, OutgoingQueueSize=%d",
1419                              aActivity.iPort->OutgoingMsgQueueSize()));
1420 
1421             if (aActivity.iPort->OutgoingMsgQueueSize() > 0)
1422             {
1423                 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
1424                                 (0, "0x%x PVMFProtocolEngineNode::PortActivity: Connected port is now ready", this));
1425                 PVMFPortActivity activity(aActivity.iPort, PVMF_PORT_ACTIVITY_OUTGOING_MSG);
1426                 QueuePortActivity(activity);
1427             }
1428             break;
1429 
1430         default:
1431             break;
1432     }
1433 }
1434 
1435 
1436 /////////////////////////////////////////////////////
1437 // Called by the AO to process a port activity message
ProcessPortActivity()1438 bool PVMFProtocolEngineNode::ProcessPortActivity()
1439 {
1440     //Pop the queue...
1441     PVMFPortActivity activity(iPortActivityQueue.front());
1442     iPortActivityQueue.erase(&iPortActivityQueue.front());
1443 
1444     LOGINFODATAPATH((0, "PVMFProtocolEngineNode::ProcessPortActivity() port=0x%x, type=%d, IncomingQueueSize=%d, OutgoingQueueSize=%d, iInterfaceState=%d, PAQSize=%d",
1445                      activity.iPort, activity.iType, activity.iPort->IncomingMsgQueueSize(), activity.iPort->OutgoingMsgQueueSize(), iInterfaceState, iPortActivityQueue.size()));
1446 
1447     PVMFStatus status = PVMFSuccess;
1448     switch (activity.iType)
1449     {
1450         case PVMF_PORT_ACTIVITY_OUTGOING_MSG:
1451             status = ProcessOutgoingMsg(activity.iPort);
1452             //Re-queue the port activity event as long as there's
1453             //more data to process and it isn't in a Busy state.
1454             QueueActivityOutgoingMessage(status, activity);
1455             break;
1456 
1457         case PVMF_PORT_ACTIVITY_INCOMING_MSG:
1458             status = ProcessIncomingMsg(activity.iPort);
1459             //Re-queue the port activity event as long as there's
1460             //more data to process and it isn't in a Busy state.
1461             QueueActivityIncomingMessage(status, activity);
1462             break;
1463 
1464         case PVMF_PORT_ACTIVITY_OUTGOING_QUEUE_READY:
1465             LOGINFODATAPATH((0, "PVMFProtocolEngineNode::ProcessPortActivity() : PVMF_PORT_ACTIVITY_OUTGOING_QUEUE_READY, OutgoingQueueSize=%d",
1466                              activity.iPort->OutgoingMsgQueueSize()));
1467             ProcessOutgoingQueueReady();
1468             break;
1469 
1470         default:
1471             break;
1472     }
1473 
1474     //Report any unexpected failure in port processing...
1475     //(the InvalidState error happens when port input is suspended,
1476     //so don't report it.)
1477     if (status != PVMFErrBusy &&
1478             status != PVMFSuccess &&
1479             status != PVMFErrInvalidState)
1480     {
1481         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
1482                         (0, "PVMFProtocolEngineNode::ProcessPortActivity() Error - ProcessPortActivity failed. port=0x%x, type=%d",
1483                          activity.iPort, activity.iType));
1484         ReportErrorEvent(PVMFErrPortProcessing);
1485     }
1486 
1487     //return true if we processed an activity...
1488     return (status != PVMFErrBusy);
1489 }
1490 
1491 // wrap OSCL_TRY block
QueueActivityOutgoingMessage(const PVMFStatus aStatus,const PVMFPortActivity & aActivity)1492 void PVMFProtocolEngineNode::QueueActivityOutgoingMessage(const PVMFStatus aStatus, const PVMFPortActivity &aActivity)
1493 {
1494     if (aStatus != PVMFErrBusy && aActivity.iPort->OutgoingMsgQueueSize() > 0)
1495     {
1496         int32 err;
1497         OSCL_TRY(err, iPortActivityQueue.push_back(aActivity););
1498         if (err) ReportErrorEvent(PVMFErrPortProcessing);
1499     }
1500 }
1501 
1502 // wrap OSCL_TRY block
QueueActivityIncomingMessage(const PVMFStatus aStatus,const PVMFPortActivity & aActivity)1503 void PVMFProtocolEngineNode::QueueActivityIncomingMessage(const PVMFStatus aStatus, const PVMFPortActivity &aActivity)
1504 {
1505     //Re-queue the port activity event as long as there's more data to process and it isn't in a Busy state.
1506     if (aStatus != PVMFErrBusy && aActivity.iPort->IncomingMsgQueueSize() > 0)
1507     {
1508         //OSCL_TRY(err,iPortActivityQueue.push_back(activity););
1509         // only insert outgoing queue ready event in case of no such event in the port activity queue
1510         if (!SearchPortActivityInQueue(PVMF_PORT_ACTIVITY_INCOMING_MSG))
1511         {
1512             int32 err;
1513             OSCL_TRY(err, iPortActivityQueue.push_back(aActivity););
1514             if (err) ReportErrorEvent(PVMFErrPortProcessing);
1515         }
1516     }
1517 }
1518 
1519 /////////////////////////////////////////////////////
ProcessIncomingMsg(PVMFPortInterface * aPort)1520 PVMFStatus PVMFProtocolEngineNode::ProcessIncomingMsg(PVMFPortInterface* aPort)
1521 {
1522     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1523                     (0, "PVMFProtocolEngineNode::ProcessIncomingMsg() aPort=0x%x, IncomingMsgQueueSize=%d, iProcessingState=%d",
1524                      aPort, aPort->IncomingMsgQueueSize(), iProcessingState));
1525 
1526     // Called by the AO to process one buffer off the port's
1527     // incoming data queue.  This routine will dequeue and dispatch the data.
1528     // for pause, don't dequeue the message
1529     if (aPort->IncomingMsgQueueSize() == 0) return PVMFSuccess;
1530 
1531     if (aPort->GetPortTag() != PVMF_PROTOCOLENGINENODE_PORT_TYPE_INPUT &&
1532             aPort->GetPortTag() != PVMF_PROTOCOLENGINENODE_PORT_TYPE_FEEDBACK)
1533     {
1534         return PVMFFailure;
1535     }
1536 
1537     if (iDataInQueue.size() < DEFAULT_DATA_QUEUE_CAPACITY*DEFAULT_READY_TO_RECEIVE_THRESHOLD_PERCENT / 100)
1538     {
1539         // DEFAULT_DATA_QUEUE_CAPACITY*DEFAULT_READY_TO_RECEIVE_THRESHOLD_PERCENT/100 = 7
1540         // only dequeue the message when data queue buffers less number of media message than the port queue
1541 
1542         // Get one incoming message
1543         PVMFSharedMediaMsgPtr msg;
1544         PVMFStatus status = aPort->DequeueIncomingMsg(msg);
1545         if (status != PVMFSuccess)
1546         {
1547             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
1548                             (0, "PVMFProtocolEngineNode::ProcessIncomingMsg() Error - DequeueIncomingMsg failed"));
1549             return status;
1550         }
1551 
1552         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1553                         (0, "PVMFProtocolEngineNode::ProcessIncomingMsg() FmtId=%d", msg->getFormatID()));
1554 
1555         bool isEOS = (msg->getFormatID() == PVMF_MEDIA_CMD_EOS_FORMAT_ID);
1556         if (aPort->GetPortTag() == PVMF_PROTOCOLENGINENODE_PORT_TYPE_INPUT)
1557         {
1558             iInterfacingObjectContainer->updateSocketConnectFlags(isEOS); // will update flags
1559         }
1560 
1561         if (IgnoreCurrentInputData(aPort, isEOS, msg))
1562         {
1563             LOGINFODATAPATH((0, "PVMFProtocolEngineNode::ProcessIncomingMsg() INCOMING MESSAGE IGNORED!! isEOS=%d, port=0x%x, iInterfaceState=%d",
1564                              (uint32)isEOS, aPort, iInterfaceState));
1565             return PVMFSuccess;
1566         }
1567 
1568         uint32 frameIndex = ((PVMFProtocolEnginePort*)aPort)->iNumFramesConsumed++;
1569         msg->setSeqNum(frameIndex);
1570         iDataInQueue.push_back(msg);
1571 
1572         UpdateTimersInProcessIncomingMsg(isEOS, aPort);
1573         LogIncomingMessage(msg, isEOS, aPort);
1574 
1575     } // end of if(iDataInQueue.size() < 7)
1576     else
1577     {
1578         if (iInterfaceState != EPVMFNodePaused && aPort->GetPortTag() == PVMF_PROTOCOLENGINENODE_PORT_TYPE_INPUT)
1579         {
1580             iNodeTimer->start(SERVER_INACTIVITY_TIMER_ID); // reset inactivity timer to prevent unnessary timeout
1581         }
1582         LOGINFODATAPATH((0, "PVMFProtocolEngineNode::ProcessIncomingMsg() iDataInQueue becomes FULL! iProcessingState = %d (1 for normal data flow), iInterfaceState = %d",
1583                          (uint32)iProcessingState, (uint32)iInterfaceState));
1584         if (iProcessingState != ProcessingState_NormalDataflow) return PVMFErrBusy;
1585     }
1586 
1587     if (iProcessingState == ProcessingState_NormalDataflow)
1588     {
1589         if (!IsDataFlowEventAlreadyInQueue())
1590         {
1591             PVProtocolEngineNodeInternalEvent aEvent(PVProtocolEngineNodeInternalEventType_IncomingMessageReady);
1592             iInternalEventQueue.push_back(aEvent);
1593         }
1594     }
1595 
1596     RunIfNotReady();
1597     return PVMFSuccess;
1598 }
1599 
UpdateTimersInProcessIncomingMsg(const bool aEOSMsg,PVMFPortInterface * aPort)1600 void PVMFProtocolEngineNode::UpdateTimersInProcessIncomingMsg(const bool aEOSMsg, PVMFPortInterface* aPort)
1601 {
1602     // for response timers
1603     if (!aEOSMsg)
1604     {
1605         // only non-EOS media data can cancel the response timer, EOS message shouldn't(that will cause no timeout happens)
1606         iNodeTimer->cancel(SERVER_RESPONSE_TIMER_ID);
1607         iNodeTimer->cancel(SERVER_RESPONSE_TIMER_ID_FOR_STOPEOS_LOGGING);
1608     }
1609 
1610     // for inactivity timer
1611     if (!aEOSMsg && iInterfaceState != EPVMFNodePaused)
1612     {
1613         if (aPort->GetPortTag() == PVMF_PROTOCOLENGINENODE_PORT_TYPE_INPUT) iNodeTimer->start(SERVER_INACTIVITY_TIMER_ID); // set up inactivity timer
1614     }
1615     else   // aEOSMsg=true or iInterfaceState = EPVMFNodePaused
1616     {
1617         iNodeTimer->cancel(SERVER_INACTIVITY_TIMER_ID);
1618     }
1619 }
1620 
IgnoreCurrentInputData(PVMFPortInterface * aPort,const bool isEOS,PVMFSharedMediaMsgPtr & aMsg)1621 bool PVMFProtocolEngineNode::IgnoreCurrentInputData(PVMFPortInterface* aPort, const bool isEOS, PVMFSharedMediaMsgPtr &aMsg)
1622 {
1623     OSCL_UNUSED_ARG(aMsg);
1624     if (iInterfacingObjectContainer->ignoreCurrentInputData())
1625     {
1626         if (aPort->GetPortTag() == PVMF_PROTOCOLENGINENODE_PORT_TYPE_INPUT)
1627         {
1628             CheckEndOfProcessingInIgoreData(isEOS);
1629         }
1630         return true;
1631     }
1632 
1633     // for input port (HTTP GET)
1634     if (aPort->GetPortTag() == PVMF_PROTOCOLENGINENODE_PORT_TYPE_INPUT)
1635     {
1636         // processing done => ignore the rest data
1637         if (CheckEndOfProcessingInIgoreData(isEOS)) return true;
1638 
1639         // paused state, ignore EOS for socket disconnect
1640         if (/*isEOS &&*/ iInterfaceState == EPVMFNodePaused) return true;
1641     }
1642 
1643     // for feedback port (HTTP POST)
1644     if (aPort->GetPortTag() == PVMF_PROTOCOLENGINENODE_PORT_TYPE_FEEDBACK)
1645     {
1646         if (isEOS) return true;
1647         if (!isEOS &&
1648                 (iInterfaceState == EPVMFNodeStarted ||
1649                  iInterfaceState == (TPVMFNodeInterfaceState)PVMFProtocolEngineNodeState_BeingStarted) &&
1650                 !iInterfacingObjectContainer->isDownloadStreamingDone())
1651         {
1652             return true;
1653         }
1654     }
1655 
1656     return false;
1657 }
1658 
CheckEndOfProcessingInIgoreData(const bool isEOS,const bool isDataPort)1659 bool PVMFProtocolEngineNode::CheckEndOfProcessingInIgoreData(const bool isEOS, const bool isDataPort)
1660 {
1661     if (!iInterfacingObjectContainer->isDownloadStreamingDone()) return false;
1662 
1663     EndOfDataProcessingInfo *aInfo = iInterfacingObjectContainer->getEOPInfo();
1664     if (isEOS)
1665     {
1666         if (iProtocolContainer->needCheckEOSAfterDisconnectSocket())
1667         {
1668             aInfo->clear();
1669             aInfo->iSendServerDisconnectEvent = true;
1670         }
1671     }
1672     else
1673     {
1674         if (iProtocolContainer->needCheckExtraDataComeIn())
1675         {
1676             aInfo->clear();
1677             aInfo->iExtraDataComeIn = true;
1678         }
1679     }
1680 
1681     if (aInfo->isValid())
1682     {
1683         PVProtocolEngineNodeInternalEvent aEvent(PVProtocolEngineNodeInternalEventType_EndOfProcessing, (OsclAny*)aInfo);
1684         iInternalEventQueue.push_back(aEvent);
1685         SetProcessingState(ProcessingState_NormalDataflow);
1686         RunIfNotReady();
1687         return true;
1688     }
1689 
1690     // Current situation: iInterfacingObjectContainer->isDownloadStreamingDone() = true
1691     if (isDataPort) return true;
1692     return false;
1693 }
1694 
LogIncomingMessage(PVMFSharedMediaMsgPtr & aMsg,bool isEOS,PVMFPortInterface * aPort)1695 void PVMFProtocolEngineNode::LogIncomingMessage(PVMFSharedMediaMsgPtr &aMsg, bool isEOS, PVMFPortInterface* aPort)
1696 {
1697     if (isEOS)
1698     {
1699         LOGINFODATAPATH((0, "PVMFProtocolEngineNode::LogIncomingMessage() GOT EOS! port=0x%x, iInterfaceState=%d",
1700                          aPort, iInterfaceState));
1701         OSCL_UNUSED_ARG(aPort); // to avoid warning of unused variable, 'aPort'
1702     }
1703     else
1704     {
1705         // Compute data size for logging purposes
1706         PVMFSharedMediaDataPtr mediaData;
1707         convertToPVMFMediaData(mediaData, aMsg);
1708         uint32 dataSize = 0;
1709         uint32 numFrags = mediaData->getNumFragments();
1710         for (uint32 i = 0; i < numFrags; i++)
1711         {
1712             OsclRefCounterMemFrag memFragIn;
1713             mediaData->getMediaFragment(i, memFragIn);
1714             uint32 fragLen = memFragIn.getMemFrag().len;
1715             dataSize += fragLen;
1716         }
1717 
1718         LOGINFODATAPATH((0, "PVMFProtocolEngineNode::LogIncomingMessage()  SEQNUM=%d,SIZE=%d,port=0x%x,portIncomingQueueSize(AfterDequeue)=%d,iInterfaceState=%d",
1719                          aMsg->getSeqNum(), dataSize, aPort, aPort->IncomingMsgQueueSize(), iInterfaceState));
1720     }
1721 }
1722 
1723 
1724 /////////////////////////////////////////////////////
ProcessOutgoingMsg(PVMFPortInterface * aPort)1725 PVMFStatus PVMFProtocolEngineNode::ProcessOutgoingMsg(PVMFPortInterface* aPort)
1726 {
1727     //Called by the AO to process one message off the outgoing
1728     //message queue for the given port.  This routine will
1729     //try to send the data to the connected port.
1730     if (aPort->OutgoingMsgQueueSize() == 0) return PVMFSuccess;
1731 
1732     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFProtocolEngineNode::ProcessOutgoingMsg() aPort=0x%x, OutgoingMsgQueueSize=%d",
1733                     aPort, aPort->OutgoingMsgQueueSize()));
1734 
1735     // check whether outgoing message is media command or media data
1736     PVMFSharedMediaMsgPtr msg;
1737     if (!((PVMFProtocolEnginePort*)aPort)->PeekOutgoingMsg(msg)) return PVMFFailure;
1738 
1739     PVMFStatus status = aPort->Send();
1740     if (status == PVMFErrBusy)
1741     {
1742         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, (0, "PVMFProtocolEngineNode::ProcessOutgoingMsg() Connected port goes into busy state"));
1743     }
1744     if (status != PVMFSuccess) return status;
1745 
1746     return PostProcessForMsgSentSuccess(aPort, msg);
1747 }
1748 
PostProcessForMsgSentSuccess(PVMFPortInterface * aPort,PVMFSharedMediaMsgPtr & aMsg)1749 PVMFStatus PVMFProtocolEngineNode::PostProcessForMsgSentSuccess(PVMFPortInterface* aPort, PVMFSharedMediaMsgPtr &aMsg)
1750 {
1751     PVMFStatus status = PVMFSuccess;
1752 
1753     // keep track the sequence no of the media msg just sent out successfully
1754     uint32 aCurrPacketNumSet = iInterfacingObjectContainer->getLatestPacketNumSent();
1755     if (aMsg->getSeqNum() > aCurrPacketNumSet) iInterfacingObjectContainer->setLatestPacketNumSent(aMsg->getSeqNum());
1756 
1757     // set up server response timer and cancel inactivity timer
1758     bool isMediaData = (aMsg->getFormatID() <  PVMF_MEDIA_CMD_FORMAT_IDS_START) ||
1759                        (aMsg->getFormatID() == PVMF_MEDIA_CMD_SOCKET_CONNECT_FORMAT_ID);
1760     UpdateTimersInProcessOutgoingMsg(isMediaData, aPort);
1761 
1762     // send() success means outgoing queue should always be ready, then send out outgoing queue ready event
1763     if ((PVMFProtocolEnginePort*)aPort == iPortOut) SendOutgoingQueueReadyEvent(aPort);
1764 
1765     // handle the remaining post processing for the different media cmds.
1766     if (aMsg->getFormatID() == PVMF_MEDIA_CMD_EOS_FORMAT_ID)
1767     {
1768         LOGINFODATAPATH((0, "PVMFProtocolEngineNode::PostProcessForMsgSentSuccess() Send() SUCCESS: EOS SENT! SEQNUM= %d, MsgID=%d, port=0x%x", aMsg->getSeqNum(), aMsg->getFormatID(), aPort));
1769 
1770         // complete the pending command if there is, especially for the case of sending EOS due to error
1771         ProtocolStateErrorInfo aInfo(0, false);
1772         PVProtocolEngineNodeInternalEvent aEvent(PVProtocolEngineNodeInternalEventType_ProtocolStateError, (OsclAny*)(&aInfo));
1773         DispatchInternalEvent(&aEvent);
1774     }
1775     else if (aMsg->getFormatID() == PVMF_MEDIA_CMD_RE_CONFIG_FORMAT_ID)
1776     {
1777         LOGINFODATAPATH((0, "PVMFProtocolEngineNode::PostProcessForMsgSentSuccess() Send() SUCCESS: RE_CONFIG SENT! SEQNUM= %d, MsgID=%d, port=0x%x", aMsg->getSeqNum(), aMsg->getFormatID(), aPort));
1778 
1779         uint32 aFirstPacketNum = 0xFFFFFFFF;
1780         PVProtocolEngineNodeInternalEvent aEvent(PVProtocolEngineNodeInternalEventType_FirstPacketAvailable, (OsclAny*)aFirstPacketNum);
1781         DispatchInternalEvent(&aEvent);
1782     }
1783     else if (aMsg->getFormatID() == PVMF_MEDIA_CMD_SOCKET_CONNECT_FORMAT_ID)
1784     {
1785         LOGINFODATAPATH((0, "PVMFProtocolEngineNode::PostProcessForMsgSentSuccess() Send() SUCCESS: SOCKET CONNECT SENT! SEQNUM= %d, MsgID=%d, port=0x%x", aMsg->getSeqNum(), aMsg->getFormatID(), aPort));
1786         bool status = iProtocolContainer->completeRepositionRequest();
1787         if (status) LOGINFODATAPATH((0, "PVMFProtocolEngineNode::PostProcessForMsgSentSuccess() Send() SOCKET CONNECT cmd SUCCESS: complete data stream reposition request"));
1788     }
1789     else
1790     {
1791         LOGINFODATAPATH((0, "PVMFProtocolEngineNode::PostProcessForMsgSentSuccess() Send() SUCCESS: SEQNUM= %d, MsgID=%d, port=0x%x", aMsg->getSeqNum(), aMsg->getFormatID(), aPort));
1792     }
1793 
1794     return status;
1795 }
1796 
1797 
UpdateTimersInProcessOutgoingMsg(const bool isMediaData,PVMFPortInterface * aPort)1798 void PVMFProtocolEngineNode::UpdateTimersInProcessOutgoingMsg(const bool isMediaData, PVMFPortInterface* aPort)
1799 {
1800     // set up server response timer
1801     if (((PVMFProtocolEnginePort*)aPort == iPortInForData ||
1802             (PVMFProtocolEnginePort*)aPort == iPortInForLogging) &&
1803             isMediaData)
1804     {
1805         iNodeTimer->cancel(SERVER_INACTIVITY_TIMER_ID);
1806 
1807         uint32 timerID = SERVER_RESPONSE_TIMER_ID;
1808         if (iInterfacingObjectContainer->isDownloadStreamingDone() && (PVMFProtocolEnginePort*)aPort == iPortInForLogging)
1809         {
1810             // logging POST for EOS and stop
1811             timerID = SERVER_RESPONSE_TIMER_ID_FOR_STOPEOS_LOGGING;
1812         }
1813         iNodeTimer->start(timerID);
1814         LOGINFODATAPATH((0, "PVMFProtocolEngineNode::UpdateTimersInProcessOutgoingMsg() server response timer starts! timerID=%d, timeoutValue=%d", timerID, iNodeTimer->getTimeout(timerID)));
1815     }
1816 }
1817 
SendOutgoingQueueReadyEvent(PVMFPortInterface * aPort)1818 void PVMFProtocolEngineNode::SendOutgoingQueueReadyEvent(PVMFPortInterface* aPort)
1819 {
1820     if (aPort->OutgoingMsgQueueSize() == 0) return;
1821 
1822     // only insert outgoing queue ready event in case of no such event in the port activity queue
1823     if (!SearchPortActivityInQueue(PVMF_PORT_ACTIVITY_OUTGOING_QUEUE_READY))
1824     {
1825         PVMFPortActivity activity(aPort, PVMF_PORT_ACTIVITY_OUTGOING_QUEUE_READY);
1826         QueuePortActivity(activity);
1827     }
1828 }
1829 
SearchPortActivityInQueue(const PVMFPortActivityType aType)1830 bool PVMFProtocolEngineNode::SearchPortActivityInQueue(const PVMFPortActivityType aType)
1831 {
1832     bool bFound = false;
1833     for (uint32 i = 0; i < iPortActivityQueue.size(); i++)
1834     {
1835         if (iPortActivityQueue[i].iType == aType)
1836         {
1837             bFound = true;
1838             break;
1839         }
1840     }
1841     return bFound;
1842 }
1843 
ProcessOutgoingQueueReady()1844 void PVMFProtocolEngineNode::ProcessOutgoingQueueReady()
1845 {
1846     if (iPortInForData)
1847     {
1848         if (iPortInForData->IncomingMsgQueueSize() > 0)
1849         {
1850             ProcessIncomingMsg(iPortInForData);
1851         }
1852     }
1853 
1854     PVProtocolEngineNodeInternalEvent aEvent(PVProtocolEngineNodeInternalEventType_StartDataflowByPortOutgoingQueueReady);
1855     iInternalEventQueue.push_back(aEvent);
1856     iProcessingState = ProcessingState_NormalDataflow; // enable data flow
1857     if (IsAdded())
1858         RunIfNotReady();
1859 }
1860 
1861 /**
1862 /////////////////////////////////////////////////////
1863 // Active object implementation
1864 /////////////////////////////////////////////////////
1865 */
1866 
1867 /**
1868 // The AO will either process one command or service one connected
1869 // port per call.  It will re-schedule itself and run continuously
1870 // until it runs out of things to do.
1871 */
Run()1872 void PVMFProtocolEngineNode::Run()
1873 {
1874     //Process commands.
1875     if (!iInputCommands.empty() && ProcessCommand(iInputCommands.front()))
1876     {
1877         //note: need to check the state before re-scheduling
1878         //since the node could have been reset in the ProcessCommand call.
1879         if (iInterfaceState != EPVMFNodeCreated) RunIfNotReady();
1880         return;
1881     }
1882 
1883     // Process data, higher priority than port processing
1884     // Do this last after handling all node command and port activity but before checking if flush is complete
1885     if (HandleProcessingState())
1886     {
1887         RunIfNotReady();
1888         return;
1889     }
1890 
1891     // Process port activity
1892     if (HandleRunPortActivityProcessing())
1893     {
1894         //Re-schedule
1895         //if(iProcessingState == ProcessingState_NormalDataflow) RunIfNotReady();
1896         RunIfNotReady();
1897         return;
1898     }
1899 
1900 
1901     // If we get here we did not process any node commands, port activity, or decode.
1902     // Check for completion of a flush command...
1903     HandleRunFlush();
1904 
1905     // final check if there is the input command, but no pending command
1906     if (!iInputCommands.empty() && iCurrentCommand.empty()) RunIfNotReady();
1907 }
1908 
HandleRunPortActivityProcessing()1909 bool PVMFProtocolEngineNode::HandleRunPortActivityProcessing()
1910 {
1911     if (!iPortActivityQueue.empty() && !FlushPending()) ///*&& (iInterfaceState==EPVMFNodeStarted || FlushPending())*/)
1912     {
1913         // If the port activity cannot be processed because a port is
1914         // busy, discard the activity and continue to process the next
1915         // activity in queue until getting to one that can be processed.
1916         while (!iPortActivityQueue.empty())
1917         {
1918             if (ProcessPortActivity()) break; //processed a port
1919         }
1920         return true;
1921     }
1922     return false;
1923 }
1924 
HandleRunFlush()1925 void PVMFProtocolEngineNode::HandleRunFlush()
1926 {
1927     if (FlushPending() && iPortActivityQueue.empty())
1928     {
1929         uint32 i;
1930         //Debug check-- all the port queues should be empty at
1931         //this point.
1932         for (i = 0; i < iPortVector.size(); i++)
1933         {
1934             if (iPortVector[i]->IncomingMsgQueueSize() > 0
1935                     || iPortVector[i]->OutgoingMsgQueueSize() > 0)
1936             {
1937                 OSCL_ASSERT(false);
1938             }
1939         }
1940 
1941         //Flush is complete.  Go to prepared state.
1942         SetState(EPVMFNodePrepared);
1943         //resume port input so the ports can be re-started.
1944         for (i = 0; i < iPortVector.size(); i++)
1945         {
1946             iPortVector[i]->ResumeInput();
1947         }
1948         CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFSuccess);
1949         RunIfNotReady();
1950     }
1951 }
1952 
SetProcessingState(PVProtocolEngineNodePrcoessingState aState)1953 void PVMFProtocolEngineNode::SetProcessingState(PVProtocolEngineNodePrcoessingState aState)
1954 {
1955     iProcessingState = aState;
1956     RunIfNotReady();
1957 }
1958 
1959 
1960 // Using state to handle different scenarios
HandleProcessingState()1961 bool PVMFProtocolEngineNode::HandleProcessingState()
1962 {
1963     if (iProcessingState == ProcessingState_NormalDataflow)
1964     {
1965         return DispatchInternalEvent();
1966     }
1967     return false;
1968 }
1969 
1970 // The following method is (internal) event dispatcher, which is an important component for event-driven model
1971 // to handle the interactions inside the node, between protocol engine and the node. All events are defined as
1972 // PVProtocolEngineNodeInternalEventType in pvmf_protocol_engine_node_internal.h.
1973 // Typical events are,
1974 
1975 // ** init/prepar/start/seek/bitstreamSwitch command trigger the data flow (class NormalDataFlowHandler),
1976 // ** multple events based on the callbacks from protocol engine
1977 //      -- http header available (class HttpHeaderAvailableHandler) to complete start command
1978 //      -- first data packet available (class FirstPacketAvailableHandler) to complete seek/bitstreamSwitch command
1979 //      -- normal data packet available (class NormalDataAvailableHandler) to pass down to node output object, and then output data packets
1980 //      -- protocol state complete (class ProtocolStateCompleteHandler) to complete init/prepare command
1981 //      -- protocol state error (class ProtocolStateErrorHandler) to handle all the errors from protocol engine
1982 
1983 // ** timer out event (will go to ProtocolStateErrorHandler) to complete any pending commands or report error event
1984 // ** end of data processing, especially for after download complete, parser node still send resume request, (class EndOfDataProcessingHandler)
1985 // ** by-pass server response for HEAD request in progressive download (class ServerResponseErrorBypassingHandler)
1986 
1987 // The design is OO-based, i.e. each event handler is encapsulated into an object following the simple generic interface (virtual bool handle()=0), a
1988 // typical polymophimic treatment.The dispatching logic is table-based, i.e the mapping between most events and their corresponding handlers is
1989 // achieved by table look-up.
1990 
1991 // aLatestEvent!=NULL means the event source sends the event without pushing it into the event queue
1992 // so no need to dequeue the event from the event queue, and just process it. This way aims to save
1993 // queueing and dequeuing operations on the queue.
DispatchInternalEvent(PVProtocolEngineNodeInternalEvent * aLatestEvent)1994 bool PVMFProtocolEngineNode::DispatchInternalEvent(PVProtocolEngineNodeInternalEvent *aLatestEvent)
1995 {
1996     LOGINFODATAPATH((0, "PVMFProtocolEngineNode::DispatchInternalEvent() IN, iInternalEventQueue.size=%d, aLatestEvent=%x",
1997                      iInternalEventQueue.size(), (uint32)aLatestEvent));
1998 
1999     if (iInternalEventQueue.empty() && !aLatestEvent) return false;
2000 
2001     PVProtocolEngineNodeInternalEvent aEvent = ((aLatestEvent != NULL) ? (*aLatestEvent) : (PVProtocolEngineNodeInternalEvent) iInternalEventQueue[0]);
2002     if (!aLatestEvent) iInternalEventQueue.erase(&(iInternalEventQueue.front()));
2003 
2004     LOGINFODATAPATH((0, "PVMFProtocolEngineNode::DispatchInternalEvent() get the event from iInternalEventQueue, iInternalEventQueue.size=%d, aEvent.iEventId=%d, totalEventNum=%d",
2005                      iInternalEventQueue.size(), (uint32)aEvent.iEventId, (uint32)EVENT_HANDLER_TOTAL));
2006 
2007     if ((uint32)aEvent.iEventId >= (uint32)PVProtocolEngineNodeInternalEventType_IncomingMessageReady)
2008         iCurrEventHandler = iEventHandlers[EVENT_HANDLER_TOTAL-1];
2009     else
2010         iCurrEventHandler = iEventHandlers[(uint32)aEvent.iEventId];
2011 
2012     iCurrEventHandler->handle(aEvent);
2013     if (!iInternalEventQueue.empty()) return true; // true means this function will re-run again
2014     return false; // let specific event handler determine this function needs to be re-run again
2015 }
2016 
IsDataFlowEventAlreadyInQueue()2017 inline bool PVMFProtocolEngineNode::IsDataFlowEventAlreadyInQueue()
2018 {
2019     if (iInternalEventQueue.empty()) return false;
2020 
2021     for (uint32 i = 0; i < iInternalEventQueue.size(); i++)
2022     {
2023         if ((uint32)iInternalEventQueue[i].iEventId >= (uint32)PVProtocolEngineNodeInternalEventType_IncomingMessageReady) return true;
2024     }
2025     return false;
2026 }
2027 
ProtocolStateComplete(const ProtocolStateCompleteInfo & aInfo)2028 void PVMFProtocolEngineNode::ProtocolStateComplete(const ProtocolStateCompleteInfo &aInfo)
2029 {
2030     PVProtocolEngineNodeInternalEvent aEvent(PVProtocolEngineNodeInternalEventType_ProtocolStateComplete);
2031     iInterfacingObjectContainer->setProtocolStateCompleteInfo(aInfo);
2032     //aEvent.iEventInfo = (OsclAny*)iInterfacingObjectContainer->getProtocolStateCompleteInfo();
2033     DispatchInternalEvent(&aEvent);
2034 }
2035 
OutputDataAvailable(OUTPUT_DATA_QUEUE & aOutputQueue,ProtocolEngineOutputDataSideInfo & aSideInfo)2036 void PVMFProtocolEngineNode::OutputDataAvailable(OUTPUT_DATA_QUEUE &aOutputQueue, ProtocolEngineOutputDataSideInfo& aSideInfo)
2037 {
2038     OUTPUT_DATA_QUEUE *pOutput = &aOutputQueue;
2039     PVProtocolEngineNodeInternalEvent aEvent(aSideInfo, (OsclAny*)pOutput);
2040     DispatchInternalEvent(&aEvent);
2041 }
2042 
ProtocolStateError(int32 aErrorCode)2043 void PVMFProtocolEngineNode::ProtocolStateError(int32 aErrorCode)
2044 {
2045     if (iProtocol->isCurrentStateOptional())
2046     {
2047         PVProtocolEngineNodeInternalEvent aEvent(PVProtocolEngineNodeInternalEventType_ServerResponseError_Bypassing);
2048         DispatchInternalEvent(&aEvent);
2049     }
2050     else
2051     {
2052         ProtocolStateErrorInfo aInfo(aErrorCode);
2053         PVProtocolEngineNodeInternalEvent aEvent(PVProtocolEngineNodeInternalEventType_ProtocolStateError, (OsclAny*)(&aInfo));
2054         DispatchInternalEvent(&aEvent);
2055     }
2056 }
2057 
GetBufferForRequest(PVMFSharedMediaDataPtr & aMediaData)2058 bool PVMFProtocolEngineNode::GetBufferForRequest(PVMFSharedMediaDataPtr &aMediaData)
2059 {
2060     return iNodeOutput->getBuffer(aMediaData);
2061 }
2062 
ProtocolRequestAvailable(uint32 aRequestType)2063 void PVMFProtocolEngineNode::ProtocolRequestAvailable(uint32 aRequestType)
2064 {
2065     uint32 aOutputType;
2066     if (aRequestType == ProtocolRequestType_Logging)
2067     {
2068         aOutputType = NodeOutputType_InputPortForLogging;
2069     }
2070     else
2071     {
2072         aOutputType = NodeOutputType_InputPortForData;
2073     }
2074 
2075     iNodeOutput->flushData(aOutputType);
2076 }
2077 
2078 
OutputBufferPoolFull()2079 void PVMFProtocolEngineNode::OutputBufferPoolFull()
2080 {
2081     iProcessingState = ProcessingState_Idle; // hold off any data flow until the output buffer callback
2082 }
2083 
OutputBufferAvailable()2084 void PVMFProtocolEngineNode::OutputBufferAvailable()
2085 {
2086     if (iPortOut && !iPortOut->IsOutgoingQueueBusy())
2087     {
2088         PVProtocolEngineNodeInternalEvent aEvent(PVProtocolEngineNodeInternalEventType_StartDataflowByBufferAvailability);
2089         iInternalEventQueue.push_back(aEvent);
2090         SetProcessingState(ProcessingState_NormalDataflow);
2091         LOGINFODATAPATH((0, "PVMFProtocolEngineNode::OutputBufferAvailable() - MemCallBackReturn"));
2092     }
2093 
2094     if (iPortInForData)
2095     {
2096         if (iPortInForData->IncomingMsgQueueSize() > 0)
2097         {
2098             PVMFPortActivity activity(iPortInForData, PVMF_PORT_ACTIVITY_INCOMING_MSG);
2099             QueuePortActivity(activity);
2100         }
2101     }
2102 }
2103 
ReadyToUpdateDownloadControl()2104 void PVMFProtocolEngineNode::ReadyToUpdateDownloadControl()
2105 {
2106     iProtocolContainer->doInfoUpdate(PROCESS_SUCCESS);
2107 }
2108 
QueueOutgoingMsgSentComplete(PVMFProtocolEnginePort * aPort,PVMFSharedMediaMsgPtr & aMsg,const PVMFStatus aStatus)2109 bool PVMFProtocolEngineNode::QueueOutgoingMsgSentComplete(PVMFProtocolEnginePort *aPort, PVMFSharedMediaMsgPtr &aMsg, const PVMFStatus aStatus)
2110 {
2111     if (aStatus == PVMFErrBusy) return false;
2112     if (aStatus == PVMFSuccess) return true;
2113 
2114     // for other status, PVMFSuccessOutgoingMsgSent, and other failures, and just complete the command process.
2115     LOGINFODATAPATH((0, "PVMFProtocolEngineNode::QueueOutgoingMsgSentComplete() - Msg queued and sent successfully!, Port=0x%x, status=%d", aPort, aStatus));
2116     if (aStatus == PVMFSuccessOutgoingMsgSent) iInterfacingObjectContainer->setLatestPacketNumSent(aMsg->getSeqNum());
2117     RerunForPostProcessAfterOutgoingMsgSent(aPort, aMsg);
2118     return (aStatus == PVMFSuccessOutgoingMsgSent);
2119 }
2120 
TimeoutOccurred(int32 timerID,int32 timeoutInfo)2121 void PVMFProtocolEngineNode::TimeoutOccurred(int32 timerID, int32 timeoutInfo)
2122 {
2123     OSCL_UNUSED_ARG(timeoutInfo);
2124     LOGINFODATAPATH((0, "PVMFProtocolEngineNode::TimeoutOccurred()  timerID = %d, (0-server response, 1-inactivity, 2-KeepAlive, 3-Logging response, 4-Wall clock, 5-Buffer status timer), iInterfaceState=%d",
2125                      timerID, (int32)iInterfaceState));
2126 
2127     iProtocolContainer->handleTimeout(timerID);
2128 }
2129 
2130 
2131 // create iProtocolContainer, iProtocol and iNodeOutput and all other protocol related projects
CreateProtocolObjects(OsclAny * & aProtocolInfo)2132 bool PVMFProtocolEngineNode::CreateProtocolObjects(OsclAny* &aProtocolInfo)
2133 {
2134     AutoCleanup cleanup(this); // cleanup's destructor will automatically call DeleteProtocolObjects() if failure happens
2135 
2136     // use PE node registry to create protocol container
2137     DeleteProtocolObjects();
2138     iProtocolContainer = iRegistry.CreateProtocolEngineContainer(aProtocolInfo, this);
2139     if (!iProtocolContainer) return false;
2140     iProtocolContainer->setObserver(this);
2141 
2142     // use protocol container to create all other protocol objects
2143     if (!iProtocolContainer->createProtocolObjects()) return false;
2144 
2145     // create the rest projects for node use itself
2146     if (!CreateRestObjects()) return false;
2147 
2148     cleanup.cancel();
2149     return true;
2150 }
2151 
2152 
RecheckProtocolObjects(OsclAny * aSourceData,OsclAny * aPluginInfo)2153 bool PVMFProtocolEngineNode::RecheckProtocolObjects(OsclAny* aSourceData, OsclAny* aPluginInfo)
2154 {
2155     uint32 isProgressiveStreaming = (uint32)iProtocolContainer->isStreamingPlayback();
2156     if (isProgressiveStreaming == (uint32)aPluginInfo) return true;
2157 
2158     // in case of progressive streaming
2159     DeleteProtocolObjects();
2160     OsclAny* aNewPluginInfo = (OsclAny*)isProgressiveStreaming;
2161     if (!CreateProtocolObjects(aNewPluginInfo)) return false;
2162 
2163     // add source data again
2164     return iProtocolContainer->addSourceData(aSourceData);
2165 }
2166 
CreateRestObjects()2167 bool PVMFProtocolEngineNode::CreateRestObjects()
2168 {
2169     // create iPortConfigFSInfoAlloc for redirect port config
2170     iPortConfigFSInfoAlloc = OSCL_NEW(OsclRefCounterMemFragAlloc, (&iPortConfigMemPool));
2171     if (!iPortConfigFSInfoAlloc) return false;
2172 
2173     // create event handlers
2174     return CreateEventHandlers();
2175 }
2176 
2177 
CreateEventHandlers()2178 bool PVMFProtocolEngineNode::CreateEventHandlers()
2179 {
2180     iEventHandlers[0] = OSCL_NEW(HttpHeaderAvailableHandler, (this));
2181     if (!iEventHandlers[0]) return false;
2182     iEventHandlers[1] = OSCL_NEW(FirstPacketAvailableHandler, (this));
2183     if (!iEventHandlers[1]) return false;
2184     iEventHandlers[2] = OSCL_NEW(NormalDataAvailableHandler, (this));
2185     if (!iEventHandlers[2]) return false;
2186     iEventHandlers[3] = OSCL_NEW(ProtocolStateCompleteHandler, (this));
2187     if (!iEventHandlers[3]) return false;
2188     iEventHandlers[4] = OSCL_NEW(EndOfDataProcessingHandler, (this));
2189     if (!iEventHandlers[4]) return false;
2190     iEventHandlers[5] = OSCL_NEW(ServerResponseErrorBypassingHandler, (this));
2191     if (!iEventHandlers[5]) return false;
2192     iEventHandlers[6] = OSCL_NEW(ProtocolStateErrorHandler, (this));
2193     if (!iEventHandlers[6]) return false;
2194     iEventHandlers[7] = OSCL_NEW(CheckResumeNotificationHandler, (this));
2195     if (!iEventHandlers[7]) return false;
2196     iEventHandlers[8] = OSCL_NEW(OutgoingMsgSentSuccessHandler, (this));
2197     if (!iEventHandlers[8]) return false;
2198 
2199     iEventHandlers[EVENT_HANDLER_TOTAL-1] = OSCL_NEW(NormalDataFlowHandler, (this));
2200     if (!iEventHandlers[EVENT_HANDLER_TOTAL-1]) return false;
2201     return true;
2202 }
2203 
DeleteProtocolObjects()2204 void PVMFProtocolEngineNode::DeleteProtocolObjects()
2205 {
2206     if (iProtocolContainer)
2207     {
2208         iProtocolContainer->deleteProtocolObjects();
2209         //delete iProtocolContainer
2210         iRegistry.ReleaseProtocolEngineContainer(iProtocolContainer);
2211     }
2212     iProtocolContainer = NULL;
2213     DeleteRestObjects();
2214 }
2215 
2216 
DeleteRestObjects()2217 void PVMFProtocolEngineNode::DeleteRestObjects()
2218 {
2219     if (iPortConfigFSInfoAlloc)     OSCL_DELETE(iPortConfigFSInfoAlloc);
2220     iPortConfigFSInfoAlloc = NULL;
2221 
2222     for (uint32 i = 0; i < EVENT_HANDLER_TOTAL; i++)
2223     {
2224         if (iEventHandlers[i]) OSCL_DELETE(iEventHandlers[i]);
2225         iEventHandlers[i] = NULL;
2226     }
2227 
2228     iInterfacingObjectContainer = NULL;
2229     iNodeTimer                  = NULL;
2230     iProtocol                   = NULL;
2231     iNodeOutput                 = NULL;
2232     iDownloadControl            = NULL;
2233     iDownloadProgess            = NULL;
2234     iUserAgentField             = NULL;
2235     iEventReport                = NULL;
2236 }
2237 
ClearPorts(const bool aNeedDelete)2238 void PVMFProtocolEngineNode::ClearPorts(const bool aNeedDelete)
2239 {
2240     // clear queued messages in ports
2241     uint32 i;
2242     for (i = 0; i < iPortVector.size(); i++) iPortVector[i]->ClearMsgQueues();
2243 
2244     // Discard any port activity events
2245     iPortActivityQueue.clear();
2246 
2247     if (aNeedDelete)
2248     {
2249         while (!iPortVector.empty())
2250         {
2251             PVMFProtocolEnginePort* port = iPortVector.front();
2252             iPortVector.Erase(&iPortVector.front());
2253 
2254             if (port == iPortInForData) iPortInForData = NULL;
2255             if (port == iPortInForLogging) iPortInForLogging = NULL;
2256             if (port == iPortOut) iPortOut = NULL;
2257         }
2258         // Restore original port vector reserve.
2259         iPortVector.Reconstruct();
2260     }
2261 }
2262 
Clear(const bool aNeedDelete)2263 void PVMFProtocolEngineNode::Clear(const bool aNeedDelete)
2264 {
2265     if (iProtocolContainer) iProtocolContainer->doClear(aNeedDelete);
2266     if (aNeedDelete) DeleteProtocolObjects();
2267 
2268 }
2269 
ResetClear(const bool aNeedDelete)2270 void PVMFProtocolEngineNode::ResetClear(const bool aNeedDelete)
2271 {
2272     if (iProtocolContainer) iProtocolContainer->doClear(aNeedDelete);
2273     if (iProtocolContainer) iProtocolContainer->deleteProtocolObjects();
2274     DeleteRestObjects();
2275     // leave iProtocolContainer undeleted
2276 
2277 }
2278 
StopClear()2279 void PVMFProtocolEngineNode::StopClear()
2280 {
2281     if (iProtocolContainer) iProtocolContainer->doStopClear();
2282 }
2283 
CancelClear()2284 void PVMFProtocolEngineNode::CancelClear()
2285 {
2286     if (iProtocolContainer) iProtocolContainer->doCancelClear();
2287 }
2288 
2289 ////////// PVMFDataSourceInitializationExtensionInterface implementation ////////////////////////
SetSourceInitializationData(OSCL_wString & aSourceURL,PVMFFormatType & aSourceFormat,OsclAny * aSourceData)2290 PVMFStatus PVMFProtocolEngineNode::SetSourceInitializationData(OSCL_wString& aSourceURL,
2291         PVMFFormatType& aSourceFormat,
2292         OsclAny* aSourceData)
2293 {
2294     // check supported protocol plugin
2295     if (!iRegistry.CheckPluginAvailability(aSourceFormat, aSourceData)) return PVMFErrNotSupported;
2296 
2297     // create protocol objects
2298     OsclAny *aPluginInfo = NULL;
2299     if (!CreateProtocolObjects(aPluginInfo)) return PVMFErrNoMemory;
2300 
2301     // check and add source data
2302     if (!iProtocolContainer->addSourceData(aSourceData)) return PVMFFailure;
2303 
2304     // need to recreate protocol objects for progressive streaming based on source data
2305     if (!RecheckProtocolObjects(aSourceData, aPluginInfo)) return PVMFErrNoMemory;
2306 
2307     // get references of all the necessary objects from iProtocolContainer
2308     GetObjects();
2309 
2310     // set download format
2311     if (iInterfacingObjectContainer) iInterfacingObjectContainer->setDownloadFormat(aSourceFormat);
2312 
2313     // set URI
2314     if (!iInterfacingObjectContainer->getURIObject().setURI(aSourceURL)) return PVMFFailure;
2315 
2316 
2317     // create and set iCfgFile
2318     if (!iProtocolContainer->createCfgFile(iInterfacingObjectContainer->getURIObject().getURI())) return PVMFFailure;
2319 
2320     return PVMFSuccess;
2321 }
2322 
2323 
SetClientPlayBackClock(PVMFMediaClock * aClientClock)2324 PVMFStatus PVMFProtocolEngineNode::SetClientPlayBackClock(PVMFMediaClock* aClientClock)
2325 {
2326     if (iDownloadControl)
2327     {
2328         iDownloadControl->setSupportObject((OsclAny *)aClientClock, DownloadControlSupportObjectType_EnginePlaybackClock);
2329         return PVMFSuccess;
2330     }
2331     return PVMFFailure;
2332 }
2333 
2334 
2335 // From PVMIDatastreamuserInterface
PassDatastreamFactory(PVMFDataStreamFactory & aFactory,int32 aFactoryTag,const PvmfMimeString * aFactoryConfig)2336 void PVMFProtocolEngineNode::PassDatastreamFactory(PVMFDataStreamFactory& aFactory, int32 aFactoryTag, const PvmfMimeString* aFactoryConfig)
2337 {
2338     OSCL_UNUSED_ARG(aFactoryTag);
2339     OSCL_UNUSED_ARG(aFactoryConfig);
2340     iInterfacingObjectContainer->setDataStreamFactory(&aFactory);
2341 }
2342 
2343 
2344 // From PVMFProtocolEngineNodeExtensionInterface
GetHTTPHeader(uint8 * & aHeader,uint32 & aHeaderLen)2345 PVMFStatus PVMFProtocolEngineNode::GetHTTPHeader(uint8*& aHeader, uint32& aHeaderLen)
2346 {
2347     iInterfacingObjectContainer->getHTTPHeader(aHeader, aHeaderLen);
2348     return PVMFSuccess;
2349 }
2350 
GetSocketConfig(OSCL_String & aPortConfig)2351 bool PVMFProtocolEngineNode::GetSocketConfig(OSCL_String &aPortConfig)
2352 {
2353     if (CheckUsingProxy(aPortConfig)) return true;
2354     return GetSocketConfigImp(iInterfacingObjectContainer->getURIObject(), aPortConfig);
2355 }
2356 
GetSocketConfigForLogging(OSCL_String & aPortConfig)2357 bool PVMFProtocolEngineNode::GetSocketConfigForLogging(OSCL_String &aPortConfig)
2358 {
2359     if (CheckUsingProxy(aPortConfig)) return true;
2360     return GetSocketConfigImp(iInterfacingObjectContainer->getLoggingURIObject(), aPortConfig);
2361 }
2362 
GetSocketConfigImp(const INetURI & aURI,OSCL_String & aPortConfig)2363 bool PVMFProtocolEngineNode::GetSocketConfigImp(const INetURI &aURI, OSCL_String &aPortConfig)
2364 {
2365     INetURI *pURI = &((INetURI &)aURI);
2366     if (pURI->empty()) return false;
2367 
2368     OSCL_HeapString<OsclMemAllocator> serverAddr;
2369     int32 serverPort = 0;
2370     if (!pURI->getHostAndPort(serverAddr, serverPort)) return false;
2371 
2372     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, \
2373                     (0, "PVMFProtocolEngineNode::GetSocketConfigImp(), serverAddr=%s , serverPort=%d", \
2374                      serverAddr.get_cstr(), serverPort));
2375 
2376     return ComposeSocketConfig(serverAddr, serverPort, aPortConfig);
2377 }
2378 
ComposeSocketConfig(OSCL_String & aServerAddr,const uint32 aPortNum,OSCL_String & aPortConfig)2379 bool PVMFProtocolEngineNode::ComposeSocketConfig(OSCL_String &aServerAddr, const uint32 aPortNum, OSCL_String &aPortConfig)
2380 {
2381     // compose port config string: "TCP/remote_address=pvs.pv.com;remote_port=554"
2382     uint32 tempBufSize = aServerAddr.get_size() + 64;
2383     OsclMemAllocator alloc;
2384     char *buffer = (char*)alloc.allocate(tempBufSize);
2385     if (!buffer) return false;
2386     oscl_snprintf(buffer, tempBufSize, "TCP/remote_address=");
2387     oscl_strcat(buffer, aServerAddr.get_cstr());
2388     OSCL_FastString port(_STRLIT_CHAR(";remote_port="));
2389     oscl_strcat(buffer, port.get_cstr());
2390     char portString[16];
2391     oscl_snprintf(portString, 16, "%d", aPortNum);
2392     oscl_strcat(buffer, (char*)portString);
2393 
2394     aPortConfig = OSCL_HeapString<OsclMemAllocator> (buffer, oscl_strlen(buffer));
2395     alloc.deallocate(buffer);
2396     return true;
2397 }
2398 
2399 
CheckUsingProxy(OSCL_String & aPortConfig)2400 bool PVMFProtocolEngineNode::CheckUsingProxy(OSCL_String &aPortConfig)
2401 {
2402     uint32 aProxyPort = 0;
2403     OSCL_HeapString<OsclMemAllocator> aProxyName;
2404     if (!getProxy(aProxyName, aProxyPort)) return false;
2405     iInterfacingObjectContainer->getURIObject().setUsAbsoluteURI();
2406     iInterfacingObjectContainer->getLoggingURIObject().setUsAbsoluteURI();
2407     return ComposeSocketConfig(aProxyName, aProxyPort, aPortConfig);
2408 }
2409 
getProxy(OSCL_String & aProxyName,uint32 & aProxyPort)2410 bool PVMFProtocolEngineNode::getProxy(OSCL_String& aProxyName, uint32 &aProxyPort)
2411 {
2412     if (!iProtocolContainer) return false;
2413     return iProtocolContainer->getProxy(aProxyName, aProxyPort);
2414 }
2415 
2416 
SetUserAgent(OSCL_wString & aUserAgent,const bool isOverwritable)2417 bool PVMFProtocolEngineNode::SetUserAgent(OSCL_wString &aUserAgent, const bool isOverwritable)
2418 {
2419     // assume setsourceinit API already gets called
2420     if (!iUserAgentField) return false;
2421     return iUserAgentField->setUserAgent(aUserAgent, isOverwritable);
2422 }
2423 
SetHttpVersion(const uint32 aHttpVersion)2424 void PVMFProtocolEngineNode::SetHttpVersion(const uint32 aHttpVersion)
2425 {
2426     if (iProtocolContainer) iProtocolContainer->setHttpVersion(aHttpVersion);
2427 }
2428 
SetHttpExtensionHeaderField(OSCL_String & aFieldKey,OSCL_String & aFieldValue,const HttpMethod aMethod,const bool aPurgeOnRedirect)2429 void PVMFProtocolEngineNode::SetHttpExtensionHeaderField(OSCL_String &aFieldKey, OSCL_String &aFieldValue, const HttpMethod aMethod, const bool aPurgeOnRedirect)
2430 {
2431     if (iProtocolContainer) iProtocolContainer->setHttpExtensionHeaderField(aFieldKey, aFieldValue, aMethod, aPurgeOnRedirect);
2432 }
2433 
SetLoggingURL(OSCL_wString & aSourceURL)2434 void PVMFProtocolEngineNode::SetLoggingURL(OSCL_wString& aSourceURL)
2435 {
2436     iInterfacingObjectContainer->setLoggingURI(aSourceURL);
2437 }
2438 
SetNetworkTimeout(const uint32 aTimeout)2439 void PVMFProtocolEngineNode::SetNetworkTimeout(const uint32 aTimeout)
2440 {
2441     LOGINFODATAPATH((0, "PVMFProtocolEngineNode::SetNetworkTimeout(), responseTimeout=%d", aTimeout));
2442     uint32 timeout = aTimeout;
2443     if ((int32)timeout < 0) timeout = 0x7fffffff;
2444     if (iNodeTimer) iNodeTimer->set(SERVER_RESPONSE_TIMER_ID, timeout);
2445 }
2446 
SetNetworkLoggingTimeout(const uint32 aTimeout)2447 void PVMFProtocolEngineNode::SetNetworkLoggingTimeout(const uint32 aTimeout)
2448 {
2449     LOGINFODATAPATH((0, "PVMFProtocolEngineNode::SetNetworkLoggingTimeout(), loggingTimeout=%d", aTimeout));
2450     uint32 timeout = aTimeout;
2451     if ((int32)timeout < 0) timeout = 0x7fffffff;
2452     if (iNodeTimer) iNodeTimer->set(SERVER_RESPONSE_TIMER_ID_FOR_STOPEOS_LOGGING, timeout);
2453 }
2454 
IsWMServerVersion4()2455 bool PVMFProtocolEngineNode::IsWMServerVersion4()
2456 {
2457     if (iProtocol)
2458     {
2459         return (iProtocol->getServerVersionNum() < DEFAULT_MS_HTTP_STREAMING_SERVER_VERSION);
2460     }
2461     return false;
2462 }
2463 
2464 
setFormatDownloadSupportInterface(PVMFFormatProgDownloadSupportInterface * download_support_interface)2465 void PVMFProtocolEngineNode::setFormatDownloadSupportInterface(PVMFFormatProgDownloadSupportInterface* download_support_interface)
2466 {
2467     LOGINFODATAPATH((0, "PVMFProtocolEngineNode::setFormatDownloadSupportInterface() IN, download_support_interface=0x%x", download_support_interface));
2468 
2469     if (iDownloadControl && iDownloadProgess)
2470     {
2471         iDownloadControl->setSupportObject((OsclAny *)download_support_interface, DownloadControlSupportObjectType_SupportInterface);
2472         iDownloadProgess->setSupportObject((OsclAny *)download_support_interface, DownloadControlSupportObjectType_SupportInterface);
2473 
2474         PVMFDownloadProgressInterface *aProgDownload = OSCL_STATIC_CAST(PVMFDownloadProgressInterface*, this);
2475         iDownloadControl->setSupportObject((OsclAny *)aProgDownload, DownloadControlSupportObjectType_ProgressInterface);
2476     }
2477 }
2478 
setClipDuration(const uint32 aClipDurationMsec)2479 void PVMFProtocolEngineNode::setClipDuration(const uint32 aClipDurationMsec)
2480 {
2481     LOGINFODATAPATH((0, "PVMFProtocolEngineNode::setClipDuration(), aClipDurationMsec = %dms", aClipDurationMsec));
2482 
2483     if (iDownloadControl) iDownloadControl->setClipDuration(aClipDurationMsec);
2484     if (iDownloadProgess) iDownloadProgess->setClipDuration(aClipDurationMsec);
2485 }
2486 
getDownloadProgressClock()2487 OsclSharedPtr<PVMFMediaClock> PVMFProtocolEngineNode::getDownloadProgressClock()
2488 {
2489     OsclSharedPtr<PVMFMediaClock> clock;
2490     iDownloadControl->getDownloadClock(clock);
2491     return clock;
2492 }
2493 
requestResumeNotification(const uint32 currentNPTReadPosition,bool & aDownloadComplete)2494 void PVMFProtocolEngineNode::requestResumeNotification(const uint32 currentNPTReadPosition, bool& aDownloadComplete)
2495 {
2496     LOGINFODATAPATH((0, "PVMFProtocolEngineNode::requestResumeNotification() IN, currentNPTReadPosition=%d", currentNPTReadPosition));
2497 
2498     bool needSendUnderflowEvent = false;
2499     iDownloadControl->requestResumeNotification(currentNPTReadPosition, aDownloadComplete, needSendUnderflowEvent);
2500     LOGINFODATAPATH((0, "PVMFProtocolEngineNode::requestResumeNotification(), after iDownloadControl->requestResumeNotification(), currentNPTReadPosition=%d, needSendUnderflowEvent=%d, aDownloadComplete=%d",
2501                      currentNPTReadPosition, (uint32)needSendUnderflowEvent, (uint32)aDownloadComplete));
2502 
2503     // report underflow event for download incomplete
2504     // but only send it once, for multiple back to back requestResumeNotification
2505     if (!aDownloadComplete && needSendUnderflowEvent) ReportInfoEvent(PVMFInfoUnderflow);
2506 
2507     if (aDownloadComplete)  // end of processing
2508     {
2509         EndOfDataProcessingInfo *aInfo = iInterfacingObjectContainer->getEOPInfo();
2510         aInfo->clear();
2511         aInfo->iSendResumeNotification = true;
2512         PVProtocolEngineNodeInternalEvent aEvent(PVProtocolEngineNodeInternalEventType_EndOfProcessing, (OsclAny*)aInfo);
2513         iInternalEventQueue.push_back(aEvent);
2514         SetProcessingState(ProcessingState_NormalDataflow);
2515         RunIfNotReady();
2516     }
2517 
2518     // check the need of sending resume notification manually
2519     iProtocolContainer->checkSendResumeNotification();
2520 }
2521 
cancelResumeNotification()2522 void PVMFProtocolEngineNode::cancelResumeNotification()
2523 {
2524     LOGINFODATAPATH((0, "PVMFProtocolEngineNode::cancelResumeNotification"));
2525 
2526     if (iDownloadControl != NULL)
2527     {
2528         iDownloadControl->cancelResumeNotification();
2529     }
2530 }
2531 
SendPortMediaCommand(PVMFProtocolEnginePort * aPort,PVUid32 aCmdId,const bool isForLogging)2532 bool PVMFProtocolEngineNode::SendPortMediaCommand(PVMFProtocolEnginePort *aPort, PVUid32 aCmdId, const bool isForLogging)
2533 {
2534     // Create an output media command
2535     PVMFSharedMediaCmdPtr aCmdPtr = PVMFMediaCmd::createMediaCmd();
2536 
2537     // Set the input format ID
2538     aCmdPtr->setFormatID(aCmdId);
2539 
2540     // check format specific info
2541     if (!CheckFormatSpecificInfoForMediaCommand(aCmdPtr, aCmdId, isForLogging)) return false;
2542 
2543     // Convert to media message and send it out
2544     PVMFSharedMediaMsgPtr mediaMsgOut;
2545     convertToPVMFMediaCmdMsg(mediaMsgOut, aCmdPtr);
2546     PVMFStatus status = aPort->QueueOutgoingMsg(mediaMsgOut);
2547     if (status < PVMFSuccess) return false;
2548     if (status == PVMFSuccessOutgoingMsgSent)
2549     {
2550         LOGINFODATAPATH((0, "PVMFProtocolEngineNode::SendPortMediaCommand() - Msg queued and sent successfully!, Port=0x%x", aPort));
2551         RerunForPostProcessAfterOutgoingMsgSent(aPort, mediaMsgOut);
2552     }
2553 
2554     LogPortMediaCmdQueued(aPort, aCmdId);
2555     return true;
2556 }
2557 
RerunForPostProcessAfterOutgoingMsgSent(PVMFProtocolEnginePort * aPort,PVMFSharedMediaMsgPtr & aMsg)2558 void PVMFProtocolEngineNode::RerunForPostProcessAfterOutgoingMsgSent(PVMFProtocolEnginePort *aPort, PVMFSharedMediaMsgPtr &aMsg)
2559 {
2560     // form PVProtocolEngineNodeInternalEventType_OutgoingMsgQueuedAndSentSuccessfully event
2561     OutgoingMsgSentSuccessInfo aInfo(aPort, aMsg);
2562     OutgoingMsgSentSuccessInfoVec *aVec = iInterfacingObjectContainer->getOutgoingMsgSentSuccessInfoVec();
2563     aVec->push_back(aInfo);
2564     PVProtocolEngineNodeInternalEvent aEvent(PVProtocolEngineNodeInternalEventType_OutgoingMsgQueuedAndSentSuccessfully,
2565             (OsclAny*)aVec);
2566     iInternalEventQueue.push_back(aEvent);
2567     SetProcessingState(ProcessingState_NormalDataflow);
2568     RunIfNotReady();
2569 }
2570 
LogPortMediaCmdQueued(PVMFProtocolEnginePort * aPort,PVUid32 aCmdId)2571 void PVMFProtocolEngineNode::LogPortMediaCmdQueued(PVMFProtocolEnginePort *aPort, PVUid32 aCmdId)
2572 {
2573     // log message
2574     if (aCmdId == PVMF_MEDIA_CMD_SOCKET_CONNECT_FORMAT_ID)
2575     {
2576         LOGINFODATAPATH((0, "PVMFProtocolEngineNode::LogPortMediaCmdQueued() - RECONNECT SENT, Port=0x%x", aPort));
2577     }
2578     else if (aCmdId == PVMF_MEDIA_CMD_EOS_FORMAT_ID)
2579     {
2580         LOGINFODATAPATH((0, "PVMFProtocolEngineNode::LogPortMediaCmdQueued() - EOS SENT, Port=0x%x", aPort));
2581     }
2582     else if (aCmdId == PVMF_MEDIA_CMD_RE_CONFIG_FORMAT_ID)
2583     {
2584         LOGINFODATAPATH((0, "PVMFProtocolEngineNode::LogPortMediaCmdQueued() - RE_CONFIG SENT, Port=0x%x", aPort));
2585     }
2586     else if (aCmdId == PVMF_MEDIA_CMD_SOCKET_DISCONNECT_FORMAT_ID)
2587     {
2588         LOGINFODATAPATH((0, "PVMFProtocolEngineNode::LogPortMediaCmdQueued() - DISCONNECT SENT, Port=0x%x", aPort));
2589     }
2590 
2591     OSCL_UNUSED_ARG(aPort); // to avoid warning of unused variable 'aPort'
2592 
2593 }
2594 
2595 
CheckFormatSpecificInfoForMediaCommand(PVMFSharedMediaCmdPtr & aCmdPtr,PVUid32 aCmdId,const bool isForLogging)2596 bool PVMFProtocolEngineNode::CheckFormatSpecificInfoForMediaCommand(PVMFSharedMediaCmdPtr &aCmdPtr, PVUid32 aCmdId, const bool isForLogging)
2597 {
2598     if (aCmdId != PVMF_MEDIA_CMD_SOCKET_CONNECT_FORMAT_ID) return true;
2599 
2600     // for socket recconnect command, set port config as format specific info
2601     bool needAttachFormatSpecificInfo = false;
2602     OSCL_HeapString<OsclMemAllocator> aPortConfig;
2603     if (iInterfacingObjectContainer->getCurrNumRedirectTrials() > 0 || iInterfaceState == EPVMFNodePaused)
2604     {
2605         bool hasLoggingUrl = !iInterfacingObjectContainer->getLoggingURIObject().empty();
2606         if (isForLogging && hasLoggingUrl)
2607         {
2608             if (!GetSocketConfigForLogging(aPortConfig)) return false;
2609         }
2610         else
2611         {
2612             if (!GetSocketConfig(aPortConfig)) return false;
2613         }
2614         needAttachFormatSpecificInfo = true;
2615     }
2616     else if (iInterfacingObjectContainer->isDownloadStreamingDone())
2617     {
2618         bool hasLoggingUrl = !iInterfacingObjectContainer->getLoggingURIObject().empty();
2619         if (hasLoggingUrl)
2620         {
2621             if (!GetSocketConfigForLogging(aPortConfig)) return false;
2622         }
2623         else
2624         {
2625             if (!GetSocketConfig(aPortConfig)) return false;
2626         }
2627         needAttachFormatSpecificInfo = true;
2628     }
2629 
2630     if (needAttachFormatSpecificInfo)
2631     {
2632         OsclRefCounterMemFrag socketConfigMemfrag;
2633         int32 err = 0;
2634         OSCL_TRY(err, socketConfigMemfrag = iPortConfigFSInfoAlloc->allocate(aPortConfig.get_size() + 1));
2635         if (err) return false;
2636         oscl_memcpy((char*)(socketConfigMemfrag.getMemFragPtr()), aPortConfig.get_cstr(), aPortConfig.get_size());
2637         char *ptr = (char*)socketConfigMemfrag.getMemFragPtr() + aPortConfig.get_size();
2638         *ptr = 0; // make it string
2639         aCmdPtr->setFormatSpecificInfo(socketConfigMemfrag);
2640     }
2641     return true;
2642 }
2643 
GetMediaPresentationInfo(PVMFMediaPresentationInfo & aInfo)2644 OSCL_EXPORT_REF PVMFStatus PVMFProtocolEngineNode::GetMediaPresentationInfo(PVMFMediaPresentationInfo& aInfo)
2645 {
2646     return iProtocolContainer->getMediaPresentationInfo(aInfo);
2647 }
2648 
SelectTracks(PVMFMediaPresentationInfo & aInfo)2649 PVMFStatus PVMFProtocolEngineNode::SelectTracks(PVMFMediaPresentationInfo& aInfo)
2650 {
2651     return iProtocolContainer->selectTracks(aInfo);
2652 }
2653 
ReportEvent(PVMFEventType aEventType,OsclAny * aEventData,const int32 aEventCode,OsclAny * aEventLocalBuffer,const uint32 aEventLocalBufferSize)2654 void PVMFProtocolEngineNode::ReportEvent(PVMFEventType aEventType, OsclAny* aEventData, const int32 aEventCode, OsclAny* aEventLocalBuffer, const uint32 aEventLocalBufferSize)
2655 {
2656     ReportInfoEvent(aEventType, aEventData, aEventCode, aEventLocalBuffer, aEventLocalBufferSize);
2657 }
2658 
NotifyContentTooLarge()2659 void PVMFProtocolEngineNode::NotifyContentTooLarge()
2660 {
2661     // before error out, settle down the interaction with parser node
2662     iDownloadControl->checkResumeNotification(false);
2663 
2664     ProtocolStateErrorInfo aInfo(PVMFErrContentTooLarge);
2665     PVProtocolEngineNodeInternalEvent aEvent(PVProtocolEngineNodeInternalEventType_ProtocolStateError, (OsclAny*)(&aInfo));
2666     DispatchInternalEvent(&aEvent);
2667 }
2668 
GetObserverState()2669 uint32 PVMFProtocolEngineNode::GetObserverState()
2670 {
2671     return (uint32)iInterfaceState;
2672 }
2673 
SetObserverState(const uint32 aState)2674 void PVMFProtocolEngineNode::SetObserverState(const uint32 aState)
2675 {
2676     iInterfaceState = (TPVMFNodeInterfaceState)aState;
2677 }
2678 
DispatchEvent(PVProtocolEngineNodeInternalEvent * aEvent)2679 bool PVMFProtocolEngineNode::DispatchEvent(PVProtocolEngineNodeInternalEvent *aEvent)
2680 {
2681     return DispatchInternalEvent(aEvent);
2682 }
2683 
SendMediaCommand(PVMFProtocolEnginePort * aPort,PVUid32 aCmdId,const bool isForLogging)2684 bool PVMFProtocolEngineNode::SendMediaCommand(PVMFProtocolEnginePort *aPort, PVUid32 aCmdId, const bool isForLogging)
2685 {
2686     return SendPortMediaCommand(aPort, aCmdId, isForLogging);
2687 }
2688 
ClearRest(const bool aNeedDelete)2689 void PVMFProtocolEngineNode::ClearRest(const bool aNeedDelete)
2690 {
2691     iDataInQueue.clear();
2692     ClearPorts(aNeedDelete); // clear any queued messages in ports
2693 }
2694 
RecheduleDataFlow()2695 void PVMFProtocolEngineNode::RecheduleDataFlow()
2696 {
2697     PVProtocolEngineNodeInternalEvent aEvent(PVProtocolEngineNodeInternalEventType_StartDataflowByCommand);
2698     iInternalEventQueue.push_back(aEvent);
2699     iProcessingState = ProcessingState_NormalDataflow;
2700     iInterfacingObjectContainer->setInputDataUnwanted(false);
2701     RunIfNotReady();
2702 }
2703 
SendManualResumeNotificationEvent()2704 void PVMFProtocolEngineNode::SendManualResumeNotificationEvent()
2705 {
2706     PVProtocolEngineNodeInternalEvent aEvent(PVProtocolEngineNodeInternalEventType_CheckResumeNotificationMaually);
2707     iInternalEventQueue.clear();
2708     iInternalEventQueue.push_back(aEvent);
2709     SetProcessingState(ProcessingState_NormalDataflow);
2710     RunIfNotReady();
2711 }
2712 
IsRepositionCmdPending()2713 bool PVMFProtocolEngineNode::IsRepositionCmdPending()
2714 {
2715     PVMFProtocolEngineNodeCommand *pInputCmd   = FindCmd(iInputCommands, PVPROTOCOLENGINE_NODE_CMD_DATASTREAM_REQUEST_REPOSITION);
2716     PVMFProtocolEngineNodeCommand *pPendingCmd = FindCmd(iCurrentCommand, PVPROTOCOLENGINE_NODE_CMD_DATASTREAM_REQUEST_REPOSITION);
2717 
2718     return (pInputCmd || pPendingCmd);
2719 }
2720 
FindPendingCmd(int32 aCmdId)2721 PVMFProtocolEngineNodeCommand* PVMFProtocolEngineNode::FindPendingCmd(int32 aCmdId)
2722 {
2723     return FindCmd(iCurrentCommand, aCmdId);
2724 }
2725 
CompletePendingCmd(int32 status)2726 void PVMFProtocolEngineNode::CompletePendingCmd(int32 status)
2727 {
2728     CommandComplete(iCurrentCommand, iCurrentCommand.front(), status);
2729 }
2730 
CompleteInputCmd(PVMFProtocolEngineNodeCommand & aCmd,int32 status)2731 void PVMFProtocolEngineNode::CompleteInputCmd(PVMFProtocolEngineNodeCommand& aCmd, int32 status)
2732 {
2733     CommandComplete(iInputCommands, aCmd, status);
2734 }
2735 
ErasePendingCmd(PVMFProtocolEngineNodeCommand * aCmd)2736 void PVMFProtocolEngineNode::ErasePendingCmd(PVMFProtocolEngineNodeCommand *aCmd)
2737 {
2738     iCurrentCommand.Erase(aCmd);
2739 }
2740 
GetObjects()2741 void PVMFProtocolEngineNode::GetObjects()
2742 {
2743     iProtocol           = (HttpBasedProtocol*)iProtocolContainer->getObject(NodeObjectType_Protocol);
2744     iNodeOutput         = (PVMFProtocolEngineNodeOutput*)iProtocolContainer->getObject(NodeObjectType_Output);
2745     iDownloadControl    = (DownloadControlInterface*)iProtocolContainer->getObject(NodeObjectType_DownloadControl);
2746     iDownloadProgess    = (DownloadProgressInterface*)iProtocolContainer->getObject(NodeObjectType_DownloadProgress);
2747     iEventReport        = (EventReporter*)iProtocolContainer->getObject(NodeObjectType_EventReport);
2748     iCfgFileContainer   = (PVDlCfgFileContainer*)iProtocolContainer->getObject(NodeObjectType_DlCfgFileContainer);
2749     iDownloadSource     = (PVMFDownloadDataSourceContainer*)iProtocolContainer->getObject(NodeObjectType_DataSourceContainer);
2750     iNodeTimer          = (PVMFProtocolEngineNodeTimer*)iProtocolContainer->getObject(NodeObjectType_Timer);
2751     iInterfacingObjectContainer = (InterfacingObjectContainer*)iProtocolContainer->getObject(NodeObjectType_InterfacingObjectContainer);
2752     iUserAgentField     = (UserAgentField*)iProtocolContainer->getObject(NodeObjectType_UseAgentField);
2753 }
2754 
2755 ////////////////////////////////////////////////////////////////////////////////////
2756 //////  PVProtocolEngineNodeInternalEventHandler implementation
2757 ////////////////////////////////////////////////////////////////////////////////////
2758 
PVProtocolEngineNodeInternalEventHandler(PVMFProtocolEngineNode * aNode)2759 PVProtocolEngineNodeInternalEventHandler::PVProtocolEngineNodeInternalEventHandler(PVMFProtocolEngineNode *aNode) : iNode(aNode)
2760 {
2761     iDataPathLogger = PVLogger::GetLoggerObject(NODEDATAPATHLOGGER_TAG);
2762 }
2763 
completePendingCommandWithError(PVProtocolEngineNodeInternalEvent & aEvent)2764 bool PVProtocolEngineNodeInternalEventHandler::completePendingCommandWithError(PVProtocolEngineNodeInternalEvent &aEvent)
2765 {
2766     int32 errorCode = (int32)aEvent.iEventInfo;
2767     if (iNode->iCurrentCommand.size() > 0)
2768     {
2769         if (IsPVMFErrCode(errorCode))  // basic error event
2770         {
2771             iNode->CommandComplete(iNode->iCurrentCommand, iNode->iCurrentCommand.front(), errorCode);
2772         }
2773         else   // extension error event
2774         {
2775             PVUuid uuid = PVProtocolEngineNodeErrorEventTypesUUID;
2776             int32 basePVMFErrorCode = getBasePVMFErrorReturnCode(errorCode);
2777             char *errEventData = NULL;
2778             uint32 errEventDataLen = 0;
2779             handleErrResponse(basePVMFErrorCode, errorCode, errEventData, errEventDataLen);
2780             iNode->CommandComplete(iNode->iCurrentCommand, iNode->iCurrentCommand.front(), basePVMFErrorCode, errEventData, &uuid, &errorCode, errEventDataLen);
2781             LOGINFODATAPATH((0, "PVProtocolEngineNodeInternalEventHandler::completePendingCommandWithError(), basePVMFErrorCode=%d, extensionErrorCode=%d",
2782                              basePVMFErrorCode, errorCode));
2783         }
2784     }
2785     else
2786     {
2787         // report error event
2788         if (IsPVMFErrCode(errorCode))
2789             iNode->ReportErrorEvent(errorCode);
2790         else
2791         {
2792             int32 basePVMFErrorCode = getBasePVMFErrorReturnCode(errorCode, false); // false for error event
2793             char *errEventData = NULL;
2794             uint32 eventDataLen = 0;
2795             handleErrResponse(basePVMFErrorCode, errorCode, errEventData, eventDataLen);
2796             iNode->ReportErrorEvent(basePVMFErrorCode, errEventData, errorCode, eventDataLen);
2797             LOGINFODATAPATH((0, "PVProtocolEngineNodeInternalEventHandler::completePendingCommandWithError(), basePVMFErrorCode=%d, extensionErrorCode=%d",
2798                              basePVMFErrorCode, errorCode));
2799         }
2800     }
2801 
2802     iNode->SetState(EPVMFNodeError);
2803     iNode->StopClear();
2804     //iNode->iProcessingState = ProcessingState_Idle;
2805 
2806     if (!iNode->iInputCommands.empty())
2807     {
2808         if (iNode->IsAdded()) iNode->RunIfNotReady();
2809     }
2810 
2811     return true;
2812 }
2813 
getBasePVMFErrorReturnCode(const int32 errorCode,const bool isForCommandComplete)2814 int32 PVProtocolEngineNodeInternalEventHandler::getBasePVMFErrorReturnCode(const int32 errorCode, const bool isForCommandComplete)
2815 {
2816     int32 pvmfReturnCode = PVMFFailure;
2817     if (!isForCommandComplete) pvmfReturnCode = PVMFErrProcessing; // if not for command complete, should for error event
2818     if (iNode->iProtocolContainer->isHTTP409ForLowDiskSpace(errorCode)) pvmfReturnCode = PVMFLowDiskSpace;
2819 
2820     switch (errorCode)
2821     {
2822         case PVProtocolEngineNodeErrorProcessingFailure_TimeoutServerNoResponce:
2823         case PVProtocolEngineNodeErrorProcessingFailure_TimeoutServerInactivity:
2824             pvmfReturnCode = PVMFErrTimeout;
2825             break;
2826 
2827         case PVProtocolEngineNodeErrorHTTPErrorCode401:
2828         case PVProtocolEngineNodeErrorHTTPErrorCode407:
2829         case PVProtocolEngineNodeErrorHTTPErrorCode401_InvalidRealm:
2830             pvmfReturnCode = PVMFErrHTTPAuthenticationRequired;
2831             break;
2832 
2833         case PVProtocolEngineNodeErrorHTTPErrorCode401_UnsupportedAuthenticationType:
2834             pvmfReturnCode = PVMFErrNotSupported;
2835             break;
2836 
2837         case PVProtocolEngineNodeErrorHTTPRedirect_TrialsExceedLimit:
2838             if (iNode->iInterfacingObjectContainer->getNumRedirectTrials() == 0)
2839             {
2840                 pvmfReturnCode = PVMFErrRedirect;
2841             }
2842             break;
2843         default:
2844             break;
2845     }
2846 
2847     return pvmfReturnCode;
2848 }
2849 
handleErrResponse(int32 & aBaseCode,int32 & errCode,char * & aEventData,uint32 & aEventDataLen)2850 void PVProtocolEngineNodeInternalEventHandler::handleErrResponse(int32 &aBaseCode, int32 &errCode, char* &aEventData, uint32 &aEventDataLen)
2851 {
2852     if (aBaseCode == PVMFErrRedirect)
2853     {
2854         handleRedirectErrResponse(aEventData, aEventDataLen);
2855     }
2856     else
2857     {
2858         handleAuthenErrResponse(errCode, aEventData, aEventDataLen);
2859         aBaseCode = getBasePVMFErrorReturnCode(errCode);
2860     }
2861 }
2862 
handleAuthenErrResponse(int32 & aErrCode,char * & aEventData,uint32 & aEventDataLen)2863 void PVProtocolEngineNodeInternalEventHandler::handleAuthenErrResponse(int32 &aErrCode, char* &aEventData, uint32 &aEventDataLen)
2864 {
2865     aEventData = NULL;
2866     aEventDataLen = 0;
2867     if (aErrCode == PVProtocolEngineNodeErrorHTTPErrorCode401)
2868     {
2869         if (false == iNode->iProtocol->isServerSendAuthenticationHeader())
2870         {
2871             aErrCode = PVProtocolEngineNodeErrorHTTPErrorCode401_NoAuthenticationHeader;
2872             return;
2873         }
2874 
2875         if (false == iNode->iProtocol->isServerSupportBasicAuthentication())
2876         {
2877             aErrCode = PVProtocolEngineNodeErrorHTTPErrorCode401_UnsupportedAuthenticationType;
2878             return;
2879         }
2880 
2881         if (iNode->iProtocol->getAuthenInfo(iAuthenInfoRealm))
2882         {
2883             aEventData = (char*)iAuthenInfoRealm.get_cstr();
2884             aEventDataLen = iAuthenInfoRealm.get_size() + 1; //Incremented by one to save c string terminating char ('\0')
2885         }
2886         else
2887         {
2888             aErrCode = PVProtocolEngineNodeErrorHTTPErrorCode401_InvalidRealm;
2889         }
2890     }
2891 }
2892 
handleRedirectErrResponse(char * & aEventData,uint32 & aEventDataLen)2893 void PVProtocolEngineNodeInternalEventHandler::handleRedirectErrResponse(char* &aEventData, uint32 &aEventDataLen)
2894 {
2895     aEventData = NULL;
2896     aEventDataLen = 0;
2897     // set the new url into info event
2898     OSCL_HeapString<OsclMemAllocator> newUrl;
2899     iNode->iProtocol->getRedirectURI(newUrl);
2900 
2901     // then set this value
2902     iNode->iInterfacingObjectContainer->setURI(newUrl, true);
2903     iNode->iProtocol->setURI(iNode->iInterfacingObjectContainer->getURIObject());
2904 
2905     aEventData = (char*)iNode->iInterfacingObjectContainer->getURIObject().getURI().get_cstr();
2906     aEventDataLen = iNode->iInterfacingObjectContainer->getURIObject().getURI().get_size() + 1;
2907 }
2908 
isCurrEventMatchCurrPendingCommand(uint32 aCurrEventId)2909 inline bool PVProtocolEngineNodeInternalEventHandler::isCurrEventMatchCurrPendingCommand(uint32 aCurrEventId)
2910 {
2911     if (iNode->iCurrentCommand.empty()) return false;
2912     PVMFProtocolEngineNodeCommand& aCmd = iNode->iCurrentCommand.front();
2913 
2914     // matching logic for event vs. pending command
2915     // init or prepare command
2916     if ((aCmd.iCmd == PVMF_GENERIC_NODE_INIT ||
2917             aCmd.iCmd == PVMF_GENERIC_NODE_PREPARE) &&
2918             (aCurrEventId == PVProtocolEngineNodeInternalEventType_ProtocolStateComplete ||
2919              aCurrEventId == PVProtocolEngineNodeInternalEventType_ServerResponseError_Bypassing)) return true;
2920 
2921     // start command
2922     if (aCmd.iCmd == PVMF_GENERIC_NODE_START &&
2923             aCurrEventId == PVProtocolEngineNodeInternalEventType_HttpHeaderAvailable) return true;
2924 
2925     //  stop command
2926     if (aCmd.iCmd == PVMF_GENERIC_NODE_STOP &&
2927             (aCurrEventId == PVProtocolEngineNodeInternalEventType_ProtocolStateComplete ||
2928              aCurrEventId == PVProtocolEngineNodeInternalEventType_EndOfProcessing)) return true;
2929 
2930     // seek or bitstream switch command
2931     if ((aCmd.iCmd == PVPROTOCOLENGINE_NODE_CMD_SEEK ||
2932             aCmd.iCmd == PVPROTOCOLENGINE_NODE_CMD_BITSTREAM_SWITCH) &&
2933             (aCurrEventId == PVProtocolEngineNodeInternalEventType_FirstPacketAvailable)) return true;
2934 
2935     return false; // no matching
2936 }
2937 
2938 // return value: true means completing pending command; false means no matching
completePendingCommand(PVProtocolEngineNodeInternalEvent & aEvent)2939 bool PVProtocolEngineNodeInternalEventHandler::completePendingCommand(PVProtocolEngineNodeInternalEvent &aEvent)
2940 {
2941     if (aEvent.iEventId == PVProtocolEngineNodeInternalEventType_ProtocolStateError)
2942     {
2943         return completePendingCommandWithError(aEvent);
2944     }
2945     if (!isCurrEventMatchCurrPendingCommand((uint32)aEvent.iEventId)) return false;
2946 
2947     PVMFProtocolEngineNodeCommand& aCmd = iNode->iCurrentCommand.front();
2948     iNode->SetState(SetStateByCommand[aCmd.iCmd-(int32)PVMF_GENERIC_NODE_INIT]);
2949     iNode->CommandComplete(iNode->iCurrentCommand, aCmd, PVMFSuccess);
2950     return true;
2951 }
2952 
isBeingStopped(const int32 aStatus)2953 bool PVProtocolEngineNodeInternalEventHandler::isBeingStopped(const int32 aStatus)
2954 {
2955     // stopped, stop command is completed and node state is changed to prepared state
2956     if (iNode->iInterfacingObjectContainer->isWholeSessionDone() &&
2957             iNode->iInterfaceState == EPVMFNodePrepared) return true;
2958 
2959     // being stopped, stop command is pending plus protcol state complete
2960     return (iNode->iInterfacingObjectContainer->isWholeSessionDone() &&
2961             isStopCmdPending() &&
2962             isProtocolStateComplete(aStatus));
2963 }
2964 
isStopCmdPending()2965 inline bool PVProtocolEngineNodeInternalEventHandler::isStopCmdPending()
2966 {
2967     for (uint32 i = 0; i < iNode->iCurrentCommand.size(); i++)
2968     {
2969         if (iNode->iCurrentCommand[i].iCmd == PVMF_GENERIC_NODE_STOP) return true;
2970     }
2971     return false;
2972 }
2973 
isProtocolStateComplete(const int32 aStatus)2974 inline bool PVProtocolEngineNodeInternalEventHandler::isProtocolStateComplete(const int32 aStatus)
2975 {
2976     return (aStatus == PROCESS_SUCCESS_END_OF_MESSAGE ||
2977             aStatus == PROCESS_SUCCESS_END_OF_MESSAGE_WITH_EXTRA_DATA ||
2978             aStatus == PROCESS_SUCCESS_END_OF_MESSAGE_TRUNCATED ||
2979             aStatus == PROCESS_SUCCESS_END_OF_MESSAGE_BY_SERVER_DISCONNECT);
2980 }
2981 
needCompletePendingCommandAtThisRound(PVProtocolEngineNodeInternalEvent & aEvent)2982 bool ProtocolStateErrorHandler::needCompletePendingCommandAtThisRound(PVProtocolEngineNodeInternalEvent &aEvent)
2983 {
2984     // get error code if necessary
2985     ProtocolStateErrorInfo *aInfo = (ProtocolStateErrorInfo *)aEvent.iEventInfo;
2986     if (aInfo->iUseInputErrorCode) iErrorCode = aInfo->iErrorCode;
2987 
2988     // check if complete pending command at this round is needed
2989     if (!aInfo->iUseInputErrorCode) return true; // use previous error code, for sure complete pending command
2990     return !iNode->iProtocolContainer->needSendEOSDuetoError(iErrorCode);
2991 }
2992 
handle(PVProtocolEngineNodeInternalEvent & aEvent)2993 bool ProtocolStateErrorHandler::handle(PVProtocolEngineNodeInternalEvent &aEvent)
2994 {
2995     if (!needCompletePendingCommandAtThisRound(aEvent))
2996     {
2997         // send EOS message to downstream node, and doesn't complete pending command at all
2998         iNode->StopClear();
2999         iNode->SendPortMediaCommand(iNode->iPortOut, PVMF_MEDIA_CMD_EOS_FORMAT_ID); // enqueuing EOS should be successful
3000         return true;
3001     }
3002 
3003     int32 errorCode = iErrorCode;
3004     if (errorCode == 0) return true;
3005     if (NeedHandleContentRangeUnmatch(errorCode)) return true;
3006 
3007     if (errorCode < 0)
3008     {
3009         int32 nodeErrorEventTypeCode = (int32)PVProtocolEngineNodeErrorProcessingFailure - (PROCESS_ERROR_FIRST - errorCode);
3010         if (!IsPVMFErrCode(errorCode)) aEvent.iEventInfo = (OsclAny*)nodeErrorEventTypeCode; // convert to PVProtocolEngineNodeErrorEventType error code
3011         else aEvent.iEventInfo = (OsclAny*)errorCode;
3012         completePendingCommand(aEvent);
3013     }
3014     else
3015     {
3016         int32 errCode = checkRedirectHandling(errorCode);
3017         if (errCode == 0)
3018         {
3019             iErrorCode = 0;
3020             return true;
3021         }
3022 
3023         // command complete with error or error event
3024         aEvent.iEventInfo = (OsclAny*)errCode;
3025         completePendingCommand(aEvent);
3026     }
3027 
3028     return true;
3029 }
3030 
3031 // return value: 0 means caller needs to return immediately, not 0 means error
checkRedirectHandling(const int32 aErrorCode)3032 int32 ProtocolStateErrorHandler::checkRedirectHandling(const int32 aErrorCode)
3033 {
3034     bool isInfoEvent = true;
3035     int32 errCode = parseServerResponseCode(aErrorCode, isInfoEvent);
3036     uint32 numRedirectTrials = iNode->iInterfacingObjectContainer->getNumRedirectTrials();
3037     uint32 numCurrRedirectTrials = iNode->iInterfacingObjectContainer->getCurrNumRedirectTrials();
3038 
3039     if (isInfoEvent && ++numCurrRedirectTrials <= numRedirectTrials)
3040     {
3041         iNode->iInterfacingObjectContainer->setCurrNumRedirectTrials(numCurrRedirectTrials);
3042 
3043         if (handleRedirect())
3044         {
3045             // set the new url into info event
3046             OSCL_HeapString<OsclMemAllocator> url(iNode->iInterfacingObjectContainer->getURIObject().getURI());
3047             iNode->ReportInfoEvent(PVMFInfoRemoteSourceNotification, (OsclAny*)(url.get_cstr()), errCode);
3048             return 0;
3049         }
3050 
3051         // treat it as error
3052         errCode = aErrorCode + PVProtocolEngineNodeErrorEventStart;
3053     }
3054 
3055     if (isInfoEvent && numCurrRedirectTrials > numRedirectTrials)
3056     {
3057         // redirect trials out of limit
3058         errCode = PVProtocolEngineNodeErrorHTTPRedirect_TrialsExceedLimit;
3059     }
3060 
3061     return errCode;
3062 }
3063 
3064 
parseServerResponseCode(const int32 aErrorCode,bool & isInfoEvent)3065 int32 ProtocolStateErrorHandler::parseServerResponseCode(const int32 aErrorCode, bool &isInfoEvent)
3066 {
3067     isInfoEvent = true;
3068     int32 errCode = aErrorCode;
3069     // redirect code 3xx
3070     if (errCode >= (int32)PROTOCOLENGINE_REDIRECT_STATUS_CODE_START &&
3071             errCode <= (int32)PROTOCOLENGINE_REDIRECT_STATUS_CODE_END)
3072     {
3073         errCode += PVMFPROTOCOLENGINENODEInfo_Redirect;
3074     }
3075     else
3076     {
3077         errCode += PVProtocolEngineNodeErrorEventStart;
3078         isInfoEvent = false;
3079     }
3080     return errCode;
3081 }
3082 
NeedHandleContentRangeUnmatch(const int32 aErrorCode)3083 bool ProtocolStateErrorHandler::NeedHandleContentRangeUnmatch(const int32 aErrorCode)
3084 {
3085     if (aErrorCode == PROCESS_CONTENT_RANGE_INFO_NOT_MATCH)
3086     {
3087         if (!handleContentRangeUnmatch()) return false;
3088         return true;
3089     }
3090     return false;
3091 }
3092 
handleContentRangeUnmatch()3093 bool ProtocolStateErrorHandler::handleContentRangeUnmatch()
3094 {
3095     return iNode->iProtocolContainer->handleContentRangeUnmatch();
3096 }
3097 
handleRedirect()3098 bool ProtocolStateErrorHandler::handleRedirect()
3099 {
3100     // Get redirect url
3101     OSCL_HeapString<OsclMemAllocator> newUrl;
3102     if (iNode->iProtocol->getRedirectURI(newUrl) && newUrl.get_size() > 0)
3103     {
3104         // then set info to protocol
3105         iNode->iInterfacingObjectContainer->setURI(newUrl, true);
3106         iNode->iProtocol->setURI(iNode->iInterfacingObjectContainer->getURIObject());
3107         iNode->iProtocolContainer->reconnectSocket();
3108         // Activate so processing will continue
3109         iNode->iEventReport->startRealDataflow();
3110         iNode->SetProcessingState(ProcessingState_NormalDataflow);
3111         return true;
3112     }
3113     return false;
3114 }
3115 
handle(PVProtocolEngineNodeInternalEvent & aEvent)3116 bool HttpHeaderAvailableHandler::handle(PVProtocolEngineNodeInternalEvent &aEvent)
3117 {
3118     // enable info update for download
3119     iNode->iProtocolContainer->enableInfoUpdate();
3120 
3121     // get Http header
3122     OUTPUT_DATA_QUEUE aHttpHeader = *((OUTPUT_DATA_QUEUE*)aEvent.iEventData);
3123     uint32 headerLength = iNode->iInterfacingObjectContainer->setHttpHeader(aHttpHeader);
3124     bool status = true;
3125     if (iNode->iProtocol && headerLength > 0)
3126     {
3127         uint32 length = iNode->iProtocol->getContentLength();
3128         iNode->iInterfacingObjectContainer->setFileSize(length);
3129         iNode->iNodeOutput->setContentLength(length);
3130         status = iNode->iProtocolContainer->downloadUpdateForHttpHeaderAvailable();
3131     }
3132 
3133     // check PVMFInfoContentLength, PVMFErrContentTooLarge and PVMFInfoContentTruncated before completing the command
3134     iNode->iEventReport->checkContentInfoEvent(PROCESS_SUCCESS);
3135 
3136     // complete start command if it is not completed
3137     if (completePendingCommand(aEvent))
3138     {
3139         iNode->iEventReport->startRealDataflow();
3140     }
3141 
3142     return status;
3143 }
3144 
handle(PVProtocolEngineNodeInternalEvent & aEvent)3145 bool FirstPacketAvailableHandler::handle(PVProtocolEngineNodeInternalEvent &aEvent)
3146 {
3147     uint32 aFirstPacketNumber = (uint32)aEvent.iEventInfo;
3148 
3149     // first packet number is only needed in seek or bitstream switching
3150     if (iNode->iInterfaceState == EPVMFNodeStarted && iNode->iCurrentCommand.size() > 0)
3151     {
3152         PVMFProtocolEngineNodeCommand& aCmd = iNode->iCurrentCommand.front();
3153 
3154         // for bitstream switching command, guarantee completing command AFTER sending RE_CONFIG port command
3155         if (aFirstPacketNumber == 0xFFFFFFFF && aCmd.iCmd == PVPROTOCOLENGINE_NODE_CMD_BITSTREAM_SWITCH)
3156         {
3157             return completePendingCommand(aEvent);
3158         }
3159 
3160         //extract the parameters.
3161         uint64 aNPTInMS;
3162         uint32 *aFirstSeqNumAfterSeekOrSwitch;
3163         aCmd.PVMFProtocolEngineNodeCommand::Parse(aNPTInMS, aFirstSeqNumAfterSeekOrSwitch);
3164         *aFirstSeqNumAfterSeekOrSwitch = aFirstPacketNumber;
3165 
3166         // send RE_CONFIG port command or complete seek command
3167         if (aCmd.iCmd == PVPROTOCOLENGINE_NODE_CMD_BITSTREAM_SWITCH)
3168         {
3169             // send RE_CONFIG port command
3170             iNode->SendPortMediaCommand(iNode->iPortOut, PVMF_MEDIA_CMD_RE_CONFIG_FORMAT_ID);
3171         }
3172         else   // for seek command, complete the command
3173         {
3174             return completePendingCommand(aEvent);
3175         }
3176     }
3177     return true;
3178 }
handle(PVProtocolEngineNodeInternalEvent & aEvent)3179 bool NormalDataAvailableHandler::handle(PVProtocolEngineNodeInternalEvent &aEvent)
3180 {
3181     OUTPUT_DATA_QUEUE aOutputData;
3182     if (aEvent.iEventData) aOutputData = *((OUTPUT_DATA_QUEUE*)aEvent.iEventData);
3183     if (iNode->iNodeOutput) iNode->iNodeOutput->passDownNewOutputData(aOutputData, aEvent.iEventInfo);
3184 
3185     if (!iNode->IsDataFlowEventAlreadyInQueue())
3186     {
3187         PVProtocolEngineNodeInternalEvent newEvent(PVProtocolEngineNodeInternalEventType_OutputDataReady);
3188         iNode->iInternalEventQueue.push_back(newEvent);
3189     }
3190     iNode->RunIfNotReady();
3191     return true;
3192 }
3193 
handle(PVProtocolEngineNodeInternalEvent & aEvent)3194 bool ProtocolStateCompleteHandler::handle(PVProtocolEngineNodeInternalEvent &aEvent)
3195 {
3196     bool aSessionDone = iNode->iInterfacingObjectContainer->isWholeSessionDone();
3197     bool aDownloadStreamingDone = iNode->iInterfacingObjectContainer->isDownloadStreamingDone();
3198     bool aEOSArrived = iNode->iInterfacingObjectContainer->isEOSAchieved();
3199 
3200     LOGINFODATAPATH((0, "ProtocolStateCompleteHandler::handle() : iNode->iInterfaceState = %d, sessionDone=%d,DownloadStreamingDone=%d,EOSArrived=%d",
3201                      iNode->iInterfaceState, (uint32)aSessionDone, (uint32)aDownloadStreamingDone, (uint32)aEOSArrived));
3202 
3203     OSCL_UNUSED_ARG(aSessionDone);
3204     OSCL_UNUSED_ARG(aDownloadStreamingDone);
3205     OSCL_UNUSED_ARG(aEOSArrived);
3206     return iNode->iProtocolContainer->handleProtocolStateComplete(aEvent, this);
3207 }
3208 
handle(PVProtocolEngineNodeInternalEvent & aEvent)3209 bool NormalDataFlowHandler::handle(PVProtocolEngineNodeInternalEvent &aEvent)
3210 {
3211     OSCL_UNUSED_ARG(aEvent);
3212 
3213     // First check and flush output data
3214     int32 statusFlushData = iNode->iNodeOutput->flushData();
3215     if (!flushDataPostProcessing(statusFlushData)) return false;
3216 
3217     // send reconnect cmd for logging request for stop or EOS packet received
3218     if (!handleEOSLogging()) return false;
3219 
3220     // Second, run state machine to continue data processing
3221     iNode->iProcessingState = ProcessingState_NormalDataflow;
3222     if (iNode->iDataInQueue.size() > 0) LOGINFODATAPATH((0, "NormalDataFlowHandler::handle() : iNode->iDataInQueue.size() = %d", iNode->iDataInQueue.size()));
3223     int32 status = iNode->iProtocol->runStateMachine(iNode->iDataInQueue);
3224     if (status < 0 || statusFlushData != PROCESS_SUCCESS || iNode->iInterfaceState == EPVMFNodeError) return false;
3225 
3226     // handle EOS
3227     if (handleEOS(status)) return true;
3228 
3229     // handle end of processing, e.g., stop
3230     if (handleEndOfProcessing(status)) return true;
3231 
3232     // check the next action, go to next protocol state
3233     return dataFlowContinue(status);
3234 }
3235 
dataFlowContinue(const int32 aStatus)3236 bool NormalDataFlowHandler::dataFlowContinue(const int32 aStatus)
3237 {
3238     // info update for download and for streaming,
3239     if (!iNode->iProtocolContainer->doInfoUpdate(aStatus)) return false;
3240 
3241     // go to next protocol state for end of message in current protocol state
3242     // The reason for making this call explicit is, when end of message happens (protocol state complete),
3243     // the node still needs some information from current state to do some extra work, like the above
3244     // download control update and info events processing. If we make this call implicit or hidden and
3245     // right after ProtcolStateComplete(), then the above info processing would fail.
3246     if (isReadyGotoNextState(aStatus)) iNode->iProtocol->gotoNextState();
3247 
3248 
3249     if (iNode->iDataInQueue.empty() && iNode->iPortInForData->IncomingMsgQueueSize() > 0)
3250     {
3251         iNode->ProcessIncomingMsg(iNode->iPortInForData);
3252     }
3253 
3254     if (iNode->iDataInQueue.size() > 0)
3255     {
3256         if (!iNode->IsDataFlowEventAlreadyInQueue())
3257         {
3258             PVProtocolEngineNodeInternalEvent aEvent(PVProtocolEngineNodeInternalEventType_HasExtraInputData);
3259             iNode->iInternalEventQueue.push_back(aEvent);
3260         }
3261         iNode->RunIfNotReady();
3262         return true;
3263     }
3264 
3265     if (aStatus == PROCESS_WAIT_FOR_INCOMING_DATA) return false;
3266     return true;
3267 }
3268 
isReadyGotoNextState(const int32 aStatus)3269 inline bool NormalDataFlowHandler::isReadyGotoNextState(const int32 aStatus)
3270 {
3271     return (aStatus == PROCESS_SUCCESS_END_OF_MESSAGE &&
3272             !iNode->iInterfacingObjectContainer->isWholeSessionDone() &&
3273             iNode->iInterfaceState != EPVMFNodePaused);
3274 }
3275 
flushDataPostProcessing(const int32 aStatusFlushData)3276 bool NormalDataFlowHandler::flushDataPostProcessing(const int32 aStatusFlushData)
3277 {
3278     // status is ok or need sending new request, then no post processing
3279     if (aStatusFlushData == PROCESS_SUCCESS || iNode->iProtocol->isSendingNewRequest()) return true;
3280 
3281     // post processing only occur for output port failure
3282     if (aStatusFlushData == PROCESS_OUTPUT_TO_OUTPUT_PORT_FAILURE)
3283     {
3284 
3285         if (iNode->iNodeOutput->isPortBusy()) iNode->iProcessingState = ProcessingState_Idle;
3286 
3287         // since queuing mesage for port outgoing queue fails, check the connected port state and try send
3288         if (!iNode->iPortOut->IsConnectedPortBusy()) iNode->ProcessOutgoingMsg(iNode->iPortOut);
3289 
3290         // if port failure is due to no memory for media data, reset inactivity timer to prevent unnessary timeout
3291         if (!iNode->iPortOut->IsOutgoingQueueBusy() && // this means port failure is due to no memory
3292                 iNode->iInterfaceState != EPVMFNodePaused &&
3293                 (iNode->iDataInQueue.size() > 0 || iNode->iPortInForData->IncomingMsgQueueSize() > 0))
3294         {
3295             LOGINFODATAPATH((0, "NormalDataFlowHandler::flushDataPostProcessing() : iNode->iDataInQueue.size()=%d, iNode->iPortInForData->IncomingMsgQueueSize()=%d",
3296                              iNode->iDataInQueue.size(), iNode->iPortInForData->IncomingMsgQueueSize()));
3297             iNode->iNodeTimer->start(SERVER_INACTIVITY_TIMER_ID); // reset inactivity timer to prevent unnessary timeout
3298         }
3299     }
3300     return false;
3301 }
3302 
handleEOSLogging()3303 bool NormalDataFlowHandler::handleEOSLogging()
3304 {
3305     if (iNode->iInterfacingObjectContainer->isDownloadStreamingDone() &&
3306             !iSendSocketReconnect &&
3307             iNode->iPortInForLogging)
3308     {
3309         // reconnect first
3310         if (!iNode->SendPortMediaCommand(iNode->iPortInForLogging, PVMF_MEDIA_CMD_SOCKET_CONNECT_FORMAT_ID)) return false;
3311         iNode->iProtocol->sendRequest();
3312         iSendSocketReconnect = true;
3313 
3314         // start stop/eos logging timer at this point to protect itself from the case where logging request
3315         // cannot be sent out due to connected port busy. For this case, logging timer timeout will help keep going
3316         iNode->iNodeTimer->start(SERVER_RESPONSE_TIMER_ID_FOR_STOPEOS_LOGGING);
3317         LOGINFODATAPATH((0, "NormalDataFlowHandler::handleEOSLogging() server stop/eos logging response timer starts! timerID=3, timeoutValue=%d",
3318                          iNode->iNodeTimer->getTimeout(SERVER_RESPONSE_TIMER_ID_FOR_STOPEOS_LOGGING)));
3319     }
3320     else if (!iNode->iInterfacingObjectContainer->isDownloadStreamingDone())
3321     {
3322         // reset the flag
3323         iSendSocketReconnect = false;
3324     }
3325     return true;
3326 }
3327 
handleEOS(const int32 aStatus)3328 bool NormalDataFlowHandler::handleEOS(const int32 aStatus)
3329 {
3330     if (aStatus != PROCESS_SUCCESS_GOT_EOS) return false;
3331 
3332     if (//(iNode->iInterfaceState==EPVMFNodeStarted || iNode->iInterfaceState==EPVMFNodePrepared || iNode->iInterfaceState==EPVMFNodeInitialized) &&
3333         !iNode->iInterfacingObjectContainer->isDownloadStreamingDone())   // only issue socket reconnect during the streaming
3334     {
3335         LOGINFODATAPATH((0, "NormalDataFlowHandler::handleEOS() : status == PROCESS_SUCCESS_GOT_EOS"));
3336         iNode->iProtocolContainer->doEOS(false);
3337 
3338         PVProtocolEngineNodeInternalEvent aEvent(PVProtocolEngineNodeInternalEventType_StartDataflowBySendRequestAction);
3339         iNode->iInternalEventQueue.push_back(aEvent);
3340         iNode->RunIfNotReady();
3341         return true;
3342     }
3343 
3344     return false;
3345 }
3346 
handleEndOfProcessing(const int32 aStatus)3347 bool NormalDataFlowHandler::handleEndOfProcessing(const int32 aStatus)
3348 {
3349     if (!isBeingStopped(aStatus)) return false;
3350 
3351     // use end of processing event to streamline all end of processing cases for stop
3352     EndOfDataProcessingInfo *aEOPInfo = iNode->iInterfacingObjectContainer->getEOPInfo();
3353     aEOPInfo->clear();
3354     aEOPInfo->iStreamingDone = true;
3355     PVProtocolEngineNodeInternalEvent aEvent(PVProtocolEngineNodeInternalEventType_EndOfProcessing, (OsclAny*)aEOPInfo);
3356     iNode->DispatchInternalEvent(&aEvent);
3357     return true;
3358 }
3359 
handle(PVProtocolEngineNodeInternalEvent & aEvent)3360 bool EndOfDataProcessingHandler::handle(PVProtocolEngineNodeInternalEvent &aEvent)
3361 {
3362     EndOfDataProcessingInfo *aInfo = (EndOfDataProcessingInfo*)aEvent.iEventInfo;
3363     if (!aInfo) return true;
3364 
3365     if (aInfo->iSendResumeNotification)
3366     {
3367         iNode->iDownloadControl->checkResumeNotification();
3368         iNode->iNodeTimer->clear();
3369         LOGINFODATAPATH((0, "EndOfDataProcessingHandler::handle(), send resume notification to parser node, for DOWNLOAD COMPLETE"));
3370     }
3371     if (aInfo->iExtraDataComeIn)
3372     {
3373         iNode->iEventReport->checkReportEvent(PROCESS_SUCCESS_END_OF_MESSAGE_WITH_EXTRA_DATA);
3374         LOGINFODATAPATH((0, "EndOfDataProcessingHandler::handle(), check and send PVMFUnexpectedData info event after DOWNLOAD COMPLETE"));
3375     }
3376     if (aInfo->iSendServerDisconnectEvent)
3377     {
3378         iNode->iEventReport->checkReportEvent(PROCESS_SUCCESS_END_OF_MESSAGE_BY_SERVER_DISCONNECT);
3379         LOGINFODATAPATH((0, "EndOfDataProcessingHandler::handle(), check and send PVMFInfoSessionDisconnect info event after DOWNLOAD COMPLETE"));
3380     }
3381     if (aInfo->iStreamingDone || aInfo->iForceStop)
3382     {
3383         cleanupForStop(aEvent);
3384         LOGINFODATAPATH((0, "EndOfDataProcessingHandler::handle(), handle the remaining stuff for EOS or stop"));
3385     }
3386 
3387     aInfo->clear();
3388     iNode->iProcessingState = ProcessingState_Idle;
3389     return true;
3390 }
3391 
cleanupForStop(PVProtocolEngineNodeInternalEvent & aEvent)3392 void EndOfDataProcessingHandler::cleanupForStop(PVProtocolEngineNodeInternalEvent &aEvent)
3393 {
3394     EndOfDataProcessingInfo *aInfo = (EndOfDataProcessingInfo*)aEvent.iEventInfo;
3395     if (isBeingStopped() || aInfo->iForceStop)
3396     {
3397         completePendingCommand(aEvent);
3398         iNode->iProtocol->stop(true);
3399         iNode->StopClear();
3400     }
3401 }
3402 
handle(PVProtocolEngineNodeInternalEvent & aEvent)3403 bool ServerResponseErrorBypassingHandler::handle(PVProtocolEngineNodeInternalEvent &aEvent)
3404 {
3405     completePendingCommand(aEvent);
3406     iNode->iProtocol->gotoNextState();
3407     //iNode->iProcessingState = ProcessingState_Idle;
3408     return true;
3409 }
3410 
handle(PVProtocolEngineNodeInternalEvent & aEvent)3411 bool CheckResumeNotificationHandler::handle(PVProtocolEngineNodeInternalEvent &aEvent)
3412 {
3413     OSCL_UNUSED_ARG(aEvent);
3414 
3415     // double check if the reposition request is pending or not
3416     if (iNode->IsRepositioningRequestPending()) return true;
3417 
3418     if (iNode->iDownloadControl->checkResumeNotification(false) == 1)   // false means download is not complete yet
3419     {
3420         LOGINFODATAPATH((0, "CheckResumeNotificationHandler::handle(), send resume notification to parser node, in case of MBDS getting full in progressive streaming"));
3421         // report data ready event
3422         iNode->iEventReport->sendDataReadyEvent();
3423     }
3424     return true;
3425 }
3426 
handle(PVProtocolEngineNodeInternalEvent & aEvent)3427 bool OutgoingMsgSentSuccessHandler::handle(PVProtocolEngineNodeInternalEvent &aEvent)
3428 {
3429     OutgoingMsgSentSuccessInfoVec *aVec = (OutgoingMsgSentSuccessInfoVec*)aEvent.iEventInfo;
3430     if (!aVec || aVec->empty()) return false;
3431     bool retVal = (iNode->PostProcessForMsgSentSuccess(aVec->front().iPort, aVec->front().iMsg) == PVMFSuccess);
3432     if (!aVec->empty()) aVec->erase(aVec->begin());
3433     return retVal;
3434 }
3435 
3436 
3437 
3438