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