• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* ------------------------------------------------------------------
2  * Copyright (C) 1998-2009 PacketVideo
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13  * express or implied.
14  * See the License for the specific language governing permissions
15  * and limitations under the License.
16  * -------------------------------------------------------------------
17  */
18 #include "pvmf_protocol_engine_node.h"
19 #include "pvmf_protocol_engine_command_format_ids.h"
20 #include "pvmf_protocolengine_node_tunables.h"
21 
22 #include "pvlogger.h"
23 #include "oscl_utf8conv.h"
24 
25 /**
26 //Macros for calling PVLogger
27 */
28 #define LOGERROR(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_REL,iLogger,PVLOGMSG_ERR,m);
29 #define LOGINFOHI(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG,iLogger,PVLOGMSG_INFO,m);
30 #define LOGINFOMED(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG,iLogger,PVLOGMSG_INFO,m);
31 #define LOGINFOLOW(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG,iLogger,PVLOGMSG_INFO,m);
32 #define LOGINFO(m) LOGINFOMED(m)
33 #define LOGINFODATAPATH(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG,iDataPathLogger,PVLOGMSG_INFO,m);
34 #define LOGERRORDATAPATH(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_REL,iDataPathLogger,PVLOGMSG_ERR,m);
35 #define LOGINFOCLOCK(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG,iClockLogger,PVLOGMSG_INFO,m);
36 #define PVMF_PROTOCOL_ENGINE_LOGBIN(iPortLogger, m) PVLOGGER_LOGBIN(PVLOGMSG_INST_LLDBG, iPortLogger, PVLOGMSG_ERR, m);
37 #define NODEDATAPATHLOGGER_TAG "datapath.sourcenode.protocolenginenode"
38 
39 ////////////////////////////////////////////////////////////////////////////////////
40 //////  ProtocolContainer implementation
41 ////////////////////////////////////////////////////////////////////////////////////
42 
43 // constructor
ProtocolContainer(PVMFProtocolEngineNode * aNode)44 OSCL_EXPORT_REF ProtocolContainer::ProtocolContainer(PVMFProtocolEngineNode *aNode) : iNode(aNode)
45 {
46     clear();
47     iDataPathLogger = PVLogger::GetLoggerObject(NODEDATAPATHLOGGER_TAG);
48 }
49 
clear()50 OSCL_EXPORT_REF void ProtocolContainer::clear()
51 {
52     iProtocol           = NULL;
53     iNodeOutput         = NULL;
54     iDownloadControl    = NULL;
55     iDownloadProgess    = NULL;
56     iEventReport        = NULL;
57     iCfgFileContainer   = NULL;
58     iDownloadSource     = NULL;
59     iNodeTimer          = NULL;
60     iInterfacingObjectContainer = NULL;
61     iUserAgentField     = NULL;
62     iPortInForData = iPortInForLogging = iPortOut = NULL;
63     iInternalEventQueue = NULL;
64 }
65 
getObject(const NodeObjectType aObjectType)66 OSCL_EXPORT_REF OsclAny* ProtocolContainer::getObject(const NodeObjectType aObjectType)
67 {
68     switch (aObjectType)
69     {
70         case NodeObjectType_Protocol:
71             return (OsclAny*)iProtocol;
72             break;
73 
74         case NodeObjectType_Output:
75             return (OsclAny*)iNodeOutput;
76             break;
77 
78         case NodeObjectType_DownloadControl:
79             return (OsclAny*)iDownloadControl;
80             break;
81 
82         case NodeObjectType_DownloadProgress:
83             return (OsclAny*)iDownloadProgess;
84             break;
85 
86         case NodeObjectType_EventReport:
87             return (OsclAny*)iEventReport;
88             break;
89 
90         case NodeObjectType_DlCfgFileContainer:
91             return (OsclAny*)iCfgFileContainer;
92             break;
93 
94         case NodeObjectType_DataSourceContainer:
95             return (OsclAny*)iDownloadSource;
96             break;
97 
98         case NodeObjectType_Timer:
99             return (OsclAny*)iNodeTimer;
100             break;
101 
102         case NodeObjectType_InterfacingObjectContainer:
103             return (OsclAny*)iInterfacingObjectContainer;
104             break;
105 
106         case NodeObjectType_UseAgentField:
107             return (OsclAny*)iUserAgentField;
108             break;
109 
110         default:
111             break;
112     }
113     return NULL;
114 }
115 
isObjectsReady()116 OSCL_EXPORT_REF bool ProtocolContainer::isObjectsReady()
117 {
118     if (!iProtocol          ||
119             !iNodeOutput            ||
120             !iInterfacingObjectContainer ||
121             iInterfacingObjectContainer->getURIObject().empty() ||
122             !iInterfacingObjectContainer->getDataStreamFactory() ||
123             !iPortInForData) return false;
124     return true;
125 }
126 
setSupportObject(OsclAny * aSupportObject,const uint32 aType)127 OSCL_EXPORT_REF void ProtocolContainer::setSupportObject(OsclAny* aSupportObject, const uint32 aType)
128 {
129     switch ((NodeObjectType)aType)
130     {
131         case NodeObjectType_InputPortForData:
132             iPortInForData = (PVMFProtocolEnginePort*)aSupportObject;
133             break;
134 
135         case NodeObjectType_InputPortForLogging:
136             iPortInForLogging = (PVMFProtocolEnginePort*)aSupportObject;
137             break;
138 
139         case NodeObjectType_OutPort:
140             iPortOut = (PVMFProtocolEnginePort*)aSupportObject;
141             break;
142 
143         case NodeObjectType_InternalEventQueue:
144             iInternalEventQueue = (Oscl_Vector<PVProtocolEngineNodeInternalEvent, PVMFProtocolEngineNodeAllocator>*)aSupportObject;
145             break;
146         default:
147             break;
148     }
149 }
150 
doPrepare()151 OSCL_EXPORT_REF PVMFStatus ProtocolContainer::doPrepare()
152 {
153     return initImpl();
154 }
155 
initImpl()156 OSCL_EXPORT_REF PVMFStatus ProtocolContainer::initImpl()
157 {
158     if (!isObjectsReady())
159     {
160         return PVMFErrNotReady;
161     }
162 
163     // initialize output object
164     int32 status = initNodeOutput();
165     if (status != PVMFSuccess) return status;
166 
167     // initialize protocol object
168     if (!initProtocol()) return PVMFFailure;
169 
170     // initialize download control object
171     initDownloadControl();
172 
173     // start data flow
174     // if the current socket connection is down, then do socket reconnect
175     bool needSocketReconnect = !iInterfacingObjectContainer->isSocketConnectionUp();
176     startDataFlowByCommand(needSocketReconnect);
177 
178     return PVMFPending;
179 }
180 
181 
initProtocol()182 OSCL_EXPORT_REF bool ProtocolContainer::initProtocol()
183 {
184     // then pass objects to protocol object (note that the order matters)
185     iProtocol->setURI(iInterfacingObjectContainer->getURIObject());
186 
187     // update user-agent field
188     if (!initProtocol_SetConfigInfo()) return false;
189     iProtocol->setObserver(iNode);
190 
191     // protocol initialization and objects dispatch
192     iProtocol->initialize();
193     return true;
194 }
195 
doStop()196 OSCL_EXPORT_REF PVMFStatus ProtocolContainer::doStop()
197 {
198     // send socket disconnect command if necessary
199     sendSocketDisconnectCmd();
200 
201     // disable sending logging message, but try to disconnect socket
202     // use end of processing event to streamline all end of processing cases for stop
203     EndOfDataProcessingInfo *aEOPInfo = iInterfacingObjectContainer->getEOPInfo();
204     aEOPInfo->clear();
205     aEOPInfo->iForceStop = true;
206     PVProtocolEngineNodeInternalEvent aEvent(PVProtocolEngineNodeInternalEventType_EndOfProcessing, (OsclAny*)aEOPInfo);
207     iObserver->DispatchEvent(&aEvent);
208 
209     return PVMFSuccess;
210 }
211 
sendSocketDisconnectCmd()212 OSCL_EXPORT_REF void ProtocolContainer::sendSocketDisconnectCmd()
213 {
214     if (iObserver->SendMediaCommand(iPortInForData, PVMF_MEDIA_CMD_SOCKET_DISCONNECT_FORMAT_ID))
215     {
216         if (iPortInForData->Send())
217         {
218             LOGINFODATAPATH((0, "ProtocolContainer::doStop()->sendSocketDisconnectCmd(), Send() SUCCESS: MsgID=%d(SOCKET DISCONNECT)", (uint32)PVMF_MEDIA_CMD_SOCKET_DISCONNECT_FORMAT_ID));
219         }
220     }
221 }
222 
startDataFlowByCommand(const bool needDoSocketReconnect)223 void ProtocolContainer::startDataFlowByCommand(const bool needDoSocketReconnect)
224 {
225     // flush out existing data at this point
226     checkEOSMsgFromInputPort();
227     iObserver->ClearRest();
228 
229     // cancel all the existing timers
230     iNodeTimer->clear();
231 
232     // disable info update at this point, will be enabled when new response comes in
233     enableInfoUpdate(false);
234 
235     // socket reconnect
236     if (needDoSocketReconnect) reconnectSocket();
237 
238     iObserver->RecheduleDataFlow();
239 }
240 
checkEOSMsgFromInputPort()241 void ProtocolContainer::checkEOSMsgFromInputPort()
242 {
243     if (iPortInForData->IncomingMsgQueueSize() == 0)  return;
244 
245     // input port has media message
246     while (iPortInForData->IncomingMsgQueueSize() > 0)
247     {
248         PVMFSharedMediaMsgPtr msg;
249         PVMFStatus status = iPortInForData->DequeueIncomingMsg(msg);
250         if (status != PVMFSuccess) continue;
251         if (msg->getFormatID() == PVMF_MEDIA_CMD_EOS_FORMAT_ID)
252         {
253             iInterfacingObjectContainer->updateSocketConnectFlags(true);
254             return;
255         }
256     }
257 }
258 
doClear(const bool aNeedDelete)259 OSCL_EXPORT_REF void ProtocolContainer::doClear(const bool aNeedDelete)
260 {
261     iObserver->ClearRest(aNeedDelete);
262     if (iInternalEventQueue) iInternalEventQueue->clear();
263     if (iInterfacingObjectContainer) iInterfacingObjectContainer->clear();
264     if (iNodeTimer) iNodeTimer->clear();
265 }
266 
doStopClear()267 OSCL_EXPORT_REF void ProtocolContainer::doStopClear()
268 {
269     doClear();
270     if (iDownloadControl) iDownloadControl->clear();
271     iEventReport->clear();
272 }
273 
doCancelClear()274 OSCL_EXPORT_REF void ProtocolContainer::doCancelClear()
275 {
276     iObserver->ClearRest();
277     if (iInternalEventQueue) iInternalEventQueue->clear();
278     if (iNodeTimer) iNodeTimer->clear();
279     if (iDownloadControl) iDownloadControl->clear();
280     if (iEventReport) iEventReport->clear();
281     //if (iInterfacingObjectContainer) iInterfacingObjectContainer->setInputDataUnwanted();
282 
283     // if re-do cancelled command, start from sending http request
284     if (iProtocol) iProtocol->sendRequest();
285 }
286 
reconnectSocket(const bool aForceSocketReconnect)287 OSCL_EXPORT_REF bool ProtocolContainer::reconnectSocket(const bool aForceSocketReconnect)
288 {
289     if (!aForceSocketReconnect)
290     {
291         // Do not force to do socket reconnect, and then need to check the possibility
292         if (iInterfacingObjectContainer->isSocketReconnectCmdSent()) return true;
293     }
294     if (!iObserver->SendMediaCommand(iPortInForData, PVMF_MEDIA_CMD_SOCKET_CONNECT_FORMAT_ID)) return false;
295     iProtocol->sendRequest();
296     iInterfacingObjectContainer->setSocketReconnectCmdSent();
297     return true;
298 }
299 
doEOS(const bool isTrueEOS)300 OSCL_EXPORT_REF bool ProtocolContainer::doEOS(const bool isTrueEOS)
301 {
302     // download done
303     if (isTrueEOS)
304     {
305         iObserver->SendMediaCommand(iPortInForData, PVMF_MEDIA_CMD_SOCKET_DISCONNECT_FORMAT_ID);
306     }
307     else   // EOS packet hasn't been received, so re-connect socket
308     {
309         bool aForceSocketReconnect = false;
310         if (!iInterfacingObjectContainer->isPrevSocketConnectionUp())
311         {
312             // the situation is, previous connection is down and the current connection is down.
313             // then force reconnect
314             aForceSocketReconnect = true;
315         }
316         reconnectSocket(aForceSocketReconnect);
317     }
318 
319     return true;
320 }
321 
getBitMaskForHTTPMethod(const HttpMethod aMethod)322 OSCL_EXPORT_REF uint32 ProtocolContainer::getBitMaskForHTTPMethod(const HttpMethod aMethod)
323 {
324     uint32 bitMaskForHttpMethod = 0;
325     if (aMethod == HTTP_GET) bitMaskForHttpMethod  = BITMASK_HTTPGET;
326     if (aMethod == HTTP_POST) bitMaskForHttpMethod = BITMASK_HTTPPOST;
327     if (aMethod == HTTP_HEAD) bitMaskForHttpMethod = BITMASK_HTTPHEAD;
328     if (aMethod == HTTP_ALLMETHOD) bitMaskForHttpMethod = ~0;
329     return bitMaskForHttpMethod;
330 }
331 
createProtocolObjects()332 OSCL_EXPORT_REF bool ProtocolContainer::createProtocolObjects()
333 {
334     // create iInterfacingObjectContainer
335     iInterfacingObjectContainer = OSCL_NEW(InterfacingObjectContainer, ());
336     if (!iInterfacingObjectContainer) return false;
337 
338     // create iNodeTimer
339     return createNetworkTimer();
340 }
341 
createNetworkTimer()342 bool ProtocolContainer::createNetworkTimer()
343 {
344     iNodeTimer = PVMFProtocolEngineNodeTimer::create(iNode);
345     if (!iNodeTimer) return false;
346     iNodeTimer->set(SERVER_RESPONSE_TIMER_ID);
347     iNodeTimer->set(SERVER_INACTIVITY_TIMER_ID);
348     iNodeTimer->set(SERVER_RESPONSE_TIMER_ID_FOR_STOPEOS_LOGGING);
349     iNodeTimer->set(WALL_CLOCK_TIMER_ID);
350     iNodeTimer->set(BUFFER_STATUS_TIMER_ID);
351     return true;
352 }
353 
deleteProtocolObjects()354 OSCL_EXPORT_REF void ProtocolContainer::deleteProtocolObjects()
355 {
356     if (iInterfacingObjectContainer)    OSCL_DELETE(iInterfacingObjectContainer);
357     iInterfacingObjectContainer = NULL;
358 
359     if (iNodeTimer) OSCL_DELETE(iNodeTimer);
360     iNodeTimer  = NULL;
361 
362 
363     if (iProtocol)                  OSCL_DELETE(iProtocol);
364     iProtocol             = NULL;
365     if (iNodeOutput)                    OSCL_DELETE(iNodeOutput);
366     iNodeOutput           = NULL;
367     if (iDownloadControl)               OSCL_DELETE(iDownloadControl);
368     iDownloadControl          = NULL;
369     if (iDownloadProgess)               OSCL_DELETE(iDownloadProgess);
370     iDownloadProgess          = NULL;
371     if (iUserAgentField)                OSCL_DELETE(iUserAgentField);
372     iUserAgentField       = NULL;
373     if (iEventReport)                   OSCL_DELETE(iEventReport);
374     iEventReport              = NULL;
375 }
376 
handleTimeout(const int32 timerID)377 OSCL_EXPORT_REF void ProtocolContainer::handleTimeout(const int32 timerID)
378 {
379     if (ignoreThisTimeout(timerID)) return;
380     handleTimeoutErr(timerID);
381 
382     // currently for wm http streaming only
383     handleTimeoutInPause(timerID);
384     // may clean flags to cause handleTimeoutErr() to get excecuted, so move handleTimeoutErr() above
385     handleTimeoutInDownloadStreamingDone(timerID);
386 }
387 
ignoreThisTimeout(const int32 timerID)388 OSCL_EXPORT_REF bool ProtocolContainer::ignoreThisTimeout(const int32 timerID)
389 {
390     // check the end processing status: EOS recved and whole session is done
391     if (iInterfacingObjectContainer->isEOSAchieved() &&
392             iInterfacingObjectContainer->isWholeSessionDone()) return true;
393 
394     // Next, all focus on checking server inactivity timeout
395     if (timerID != (int32)SERVER_INACTIVITY_TIMER_ID) return false;
396 
397     // inactivity timeout should be ignored in the following cases:
398     // (i)  input/output port queue still has data,
399     // (ii) buffer full in progressive streaming
400     if (iPortInForData)
401     {
402         if (iPortInForData->IncomingMsgQueueSize() > 0) return true;
403     }
404     if (iPortOut)
405     {
406         if (iPortOut->OutgoingMsgQueueSize() > 0) return true;
407     }
408 
409     if (iNodeOutput)
410     {
411         if (iNodeOutput->getAvailableOutputSize() == 0) return true;
412     }
413     return false;
414 }
415 
handleTimeoutErr(const int32 timerID)416 bool ProtocolContainer::handleTimeoutErr(const int32 timerID)
417 {
418     if (iInterfacingObjectContainer->isDownloadStreamingDone() ||
419             iObserver->GetObserverState() == EPVMFNodePaused) return false;
420 
421     int32 timeoutErr = PVMFErrTimeout;
422     if (timerID == SERVER_RESPONSE_TIMER_ID)   timeoutErr = PROCESS_TIMEOUT_SERVER_NO_RESPONCE;
423     if (timerID == SERVER_INACTIVITY_TIMER_ID) timeoutErr = PROCESS_TIMEOUT_SERVER_INACTIVITY;
424 
425     ProtocolStateErrorInfo aInfo(timeoutErr);
426     PVProtocolEngineNodeInternalEvent aEvent(PVProtocolEngineNodeInternalEventType_ProtocolStateError, (OsclAny*)(&aInfo));
427     iObserver->DispatchEvent(&aEvent);
428     return true;
429 }
430 
handleProtocolStateComplete(PVProtocolEngineNodeInternalEvent & aEvent,PVProtocolEngineNodeInternalEventHandler * aEventHandler)431 OSCL_EXPORT_REF bool ProtocolContainer::handleProtocolStateComplete(PVProtocolEngineNodeInternalEvent &aEvent, PVProtocolEngineNodeInternalEventHandler *aEventHandler)
432 {
433     bool aSessionDone = iInterfacingObjectContainer->isWholeSessionDone();
434     bool aDownloadStreamingDone = iInterfacingObjectContainer->isDownloadStreamingDone();
435     OSCL_UNUSED_ARG(aDownloadStreamingDone);
436     bool aEOSArrived = iInterfacingObjectContainer->isEOSAchieved();
437 
438     iInterfacingObjectContainer->setInputDataUnwanted();
439     if (aSessionDone)
440     {
441         // flush all the remaining output
442         iNodeOutput->flushData();
443         iNodeTimer->clear();
444         if (aEOSArrived && iInterfacingObjectContainer->getOutputPortConnect())
445         {
446             doEOS(); // true EOS
447             return aEventHandler->completePendingCommand(aEvent);
448         }
449     }
450     return aEventHandler->completePendingCommand(aEvent);
451 }
452 
453 
454 ////////////////////////////////////////////////////////////////////////////////////
455 //////  PVMFProtocolEngineNodeOutput implementation
456 ////////////////////////////////////////////////////////////////////////////////////
457 
458 // constructor
PVMFProtocolEngineNodeOutput(PVMFProtocolEngineNodeOutputObserver * aObserver)459 OSCL_EXPORT_REF PVMFProtocolEngineNodeOutput::PVMFProtocolEngineNodeOutput(PVMFProtocolEngineNodeOutputObserver *aObserver) :
460         iPortIn(NULL),
461         iContentDataMemPool(NULL),
462         iMediaDataAlloc(NULL),
463         iMediaDataMemPool("PVMFProtocolEngineNodeOutput(PVMFProtocolEngineNode)",
464                           PVHTTPDOWNLOADOUTPUT_CONTENTDATA_POOLNUM,
465                           PVHTTPDOWNLOADOUTPUT_MEDIADATA_CHUNKSIZE),
466         iObserver(aObserver),
467         iCurrTotalOutputSize(0)
468 
469 {
470     iOutputFramesQueue.reserve(PVPROTOCOLENGINE_RESERVED_NUMBER_OF_FRAMES);
471     iLogger = PVLogger::GetLoggerObject("PVMFProtocolEngineNode");
472     iDataPathLogger = PVLogger::GetLoggerObject(NODEDATAPATHLOGGER_TAG);
473     iClockLogger = PVLogger::GetLoggerObject("clock");
474     iMediaDataMemPool.enablenullpointerreturn();
475 }
476 
~PVMFProtocolEngineNodeOutput()477 OSCL_EXPORT_REF PVMFProtocolEngineNodeOutput::~PVMFProtocolEngineNodeOutput()
478 {
479     reset();
480 }
481 
482 // reset
reset()483 OSCL_EXPORT_REF void PVMFProtocolEngineNodeOutput::reset()
484 {
485     iPortIn = NULL;
486     iLogger = NULL;
487     iDataPathLogger = NULL;
488     iClockLogger = NULL;
489     iOutputFramesQueue.clear();
490     iMediaData.Unbind();
491     deleteMemPool();
492 }
493 
setOutputObject(OsclAny * aOutputObject,const uint32 aObjectType)494 OSCL_EXPORT_REF void PVMFProtocolEngineNodeOutput::setOutputObject(OsclAny* aOutputObject, const uint32 aObjectType)
495 {
496     if (aObjectType == NodeOutputType_InputPortForData && aOutputObject) iPortIn = (PVMFProtocolEnginePort *)aOutputObject;
497 }
498 
499 
sendToPort(PVMFSharedMediaDataPtr & aMediaData,const uint32 aPortType)500 OSCL_EXPORT_REF bool PVMFProtocolEngineNodeOutput::sendToPort(PVMFSharedMediaDataPtr &aMediaData, const uint32 aPortType)
501 {
502     OSCL_UNUSED_ARG(aPortType);
503     return sendToDestPort(aMediaData, iPortIn);
504 }
505 
createMediaData(PVMFSharedMediaDataPtr & aMediaData,uint32 aRequestSize)506 OSCL_EXPORT_REF bool PVMFProtocolEngineNodeOutput::createMediaData(PVMFSharedMediaDataPtr &aMediaData, uint32 aRequestSize)
507 {
508     // check if need to create memory pool
509     int32 errcode = OsclErrNone;
510     if (!iMediaDataAlloc)
511     {
512         errcode = createMemPool();
513         if (errcode != PVMFSuccess) return false;
514     }
515 
516     OsclSharedPtr<PVMFMediaDataImpl> mediadataImpl;
517     errcode = 0;
518     OSCL_TRY(errcode, mediadataImpl = iMediaDataAlloc->allocate(aRequestSize));
519     if (errcode != OsclErrNone) return false;
520 
521 
522     // Then wrap it around with PVMFMediaData
523     iMediaData.Unbind();
524 
525     errcode = OsclErrNoResources;
526 
527     iMediaData = PVMFMediaData::createMediaData(mediadataImpl, &iMediaDataMemPool);
528 
529     if (iMediaData.GetRep() != NULL)
530     {
531         errcode = OsclErrNone;
532     }
533 
534     if (errcode != OsclErrNone) return false;
535 
536     aMediaData = iMediaData;
537     return true;
538 }
539 
createMemPool()540 OSCL_EXPORT_REF PVMFStatus PVMFProtocolEngineNodeOutput::createMemPool()
541 {
542     // Create the memory pool
543     int32 errcode = 0;
544     OSCL_TRY(errcode, iContentDataMemPool = OSCL_NEW(OsclMemPoolFixedChunkAllocator, (PVHTTPDOWNLOADOUTPUT_CONTENTDATA_POOLNUM)));
545     if (errcode || iContentDataMemPool == NULL) return PVMFErrNoMemory;
546 
547 
548     OSCL_TRY(errcode, iMediaDataAlloc = OSCL_NEW(PVMFSimpleMediaBufferCombinedAlloc, (iContentDataMemPool)));
549     if (errcode || iMediaDataAlloc == NULL) return PVMFErrNoMemory;
550 
551     return PVMFSuccess;
552 }
553 
deleteMemPool()554 OSCL_EXPORT_REF void PVMFProtocolEngineNodeOutput::deleteMemPool()
555 {
556     // Cleanup output media data memory pool
557     if (iMediaDataAlloc != NULL)
558     {
559         OSCL_DELETE(iMediaDataAlloc);
560         iMediaDataAlloc = NULL;
561     }
562 
563     if (iContentDataMemPool != NULL)
564     {
565         OSCL_DELETE(iContentDataMemPool);
566         iContentDataMemPool = NULL;
567     }
568 }
569 
sendToDestPort(PVMFSharedMediaDataPtr & aMediaData,PVMFProtocolEnginePort * aPort)570 OSCL_EXPORT_REF bool PVMFProtocolEngineNodeOutput::sendToDestPort(PVMFSharedMediaDataPtr &aMediaData, PVMFProtocolEnginePort *aPort)
571 {
572     // compute data frag size for log purposes
573     uint32 dataSize = 0;
574     uint32 numFrags = aMediaData->getNumFragments();
575     for (uint32 i = 0; i < numFrags; i++)
576     {
577         OsclRefCounterMemFrag memFragIn;
578         aMediaData->getMediaFragment(i, memFragIn);
579         uint32 fragLen = memFragIn.getMemFrag().len;
580         dataSize += fragLen;
581     }
582 
583     // Send frame to downstream node
584     PVMFSharedMediaMsgPtr mediaMsgOut;
585     convertToPVMFMediaMsg(mediaMsgOut, aMediaData);
586 
587     LOGINFODATAPATH((0, "PVMFProtocolEngineNodeOutput::sendToDestPort() SEQNUM= %d, SIZE= %d, port = 0x%x",
588                      mediaMsgOut->getSeqNum(), dataSize, aPort));
589 
590     PVMFStatus status = aPort->QueueOutgoingMsg(mediaMsgOut);
591     return iObserver->QueueOutgoingMsgSentComplete(aPort, mediaMsgOut, status);
592 }
593 
passDownNewOutputData(OUTPUT_DATA_QUEUE & aOutputQueue,OsclAny * aSideInfo)594 OSCL_EXPORT_REF bool PVMFProtocolEngineNodeOutput::passDownNewOutputData(OUTPUT_DATA_QUEUE &aOutputQueue, OsclAny* aSideInfo)
595 {
596     OSCL_UNUSED_ARG(aSideInfo);
597     int32 err = 0;
598     OSCL_TRY(err, iOutputFramesQueue.push_back(aOutputQueue););
599     return (err == 0);
600 }
601 
flushData(const uint32 aOutputType)602 OSCL_EXPORT_REF int32 PVMFProtocolEngineNodeOutput::flushData(const uint32 aOutputType)
603 {
604     if (iMediaData.GetRep() == NULL)  return PROCESS_SUCCESS;
605 
606     // send to port
607     if (!sendToPort(iMediaData, aOutputType)) return PROCESS_OUTPUT_PORT_IS_BUSY;
608     iMediaData.Unbind();
609     return PROCESS_SUCCESS;
610 }
611 
getBuffer(PVMFSharedMediaDataPtr & aMediaData,uint32 aRequestSize)612 OSCL_EXPORT_REF bool PVMFProtocolEngineNodeOutput::getBuffer(PVMFSharedMediaDataPtr &aMediaData, uint32 aRequestSize)
613 {
614     if (!createMediaData(aMediaData, aRequestSize)) return false;
615     return true;
616 }
617 
discardData(const bool aNeedReopen)618 OSCL_EXPORT_REF void PVMFProtocolEngineNodeOutput::discardData(const bool aNeedReopen)
619 {
620     OSCL_UNUSED_ARG(aNeedReopen);
621     iOutputFramesQueue.clear();
622     iMediaData.Unbind();
623 }
624 
isPortBusy()625 OSCL_EXPORT_REF bool PVMFProtocolEngineNodeOutput::isPortBusy()
626 {
627     return iPortIn->IsOutgoingQueueBusy();
628 }
629 
630 
631 
632 ////////////////////////////////////////////////////////////////////////////////////
633 //////  UserAgentField implementation
634 ////////////////////////////////////////////////////////////////////////////////////
635 // constructor
UserAgentField(OSCL_wString & aUserAgent,const bool isOverwritable)636 OSCL_EXPORT_REF UserAgentField::UserAgentField(OSCL_wString &aUserAgent, const bool isOverwritable)
637 {
638     setUserAgent(aUserAgent, isOverwritable);
639 }
640 
UserAgentField(OSCL_String & aUserAgent,const bool isOverwritable)641 OSCL_EXPORT_REF UserAgentField::UserAgentField(OSCL_String &aUserAgent, const bool isOverwritable)
642 {
643     setUserAgent(aUserAgent, isOverwritable);
644 }
645 
646 // set user agent
setUserAgent(OSCL_wString & aUserAgent,const bool isOverwritable)647 OSCL_EXPORT_REF bool UserAgentField::setUserAgent(OSCL_wString &aUserAgent, const bool isOverwritable)
648 {
649     iOverwritable = isOverwritable;
650 
651     // check for empty string
652     if (aUserAgent.get_size() == 0) return true;
653 
654     OsclMemAllocator alloc;
655     char *buf = (char*)alloc.allocate(aUserAgent.get_size() + 1);
656     if (!buf) return false;
657     uint32 size = 0;
658     if ((size = oscl_UnicodeToUTF8(aUserAgent.get_cstr(), aUserAgent.get_size(), buf, aUserAgent.get_size() + 1)) == 0)
659     {
660         alloc.deallocate(buf);
661         return false;
662     }
663     iInputUserAgent = OSCL_HeapString<OsclMemAllocator> (buf, size);
664     alloc.deallocate(buf);
665     return true;
666 }
667 
setUserAgent(OSCL_String & aUserAgent,const bool isOverwritable)668 OSCL_EXPORT_REF bool UserAgentField::setUserAgent(OSCL_String &aUserAgent, const bool isOverwritable)
669 {
670     iOverwritable = isOverwritable;
671     // check for empty string
672     if (aUserAgent.get_size() == 0) return true;
673 
674     iInputUserAgent = OSCL_HeapString<OsclMemAllocator> (aUserAgent.get_str(), aUserAgent.get_size());
675     return true;
676 }
677 
678 // get the actual user agent (not wide string version) based on overwrite mode or replace mode (set the input user agent to the default one)
getUserAgent(OSCL_String & aUserAgent)679 OSCL_EXPORT_REF bool UserAgentField::getUserAgent(OSCL_String &aUserAgent)
680 {
681     if (iActualUserAgent.get_size() > 0)
682     {
683         aUserAgent = iActualUserAgent;
684         return true;
685     }
686 
687     // create iActualUserAgent at the first call
688     if (iOverwritable && iInputUserAgent.get_size() > 0)
689     {
690         iActualUserAgent = iInputUserAgent;
691     }
692     else   // append
693     {
694         //OSCL_FastString defaultUserAgent(_STRLIT_CHAR("PVPlayer/4.0 (Beta release)"));
695         OSCL_HeapString<OsclMemAllocator> defaultUserAgent;
696         getDefaultUserAgent(defaultUserAgent);
697         uint32 size = defaultUserAgent.get_size() + iInputUserAgent.get_size() + 1; // 1 => space
698         OsclMemAllocator alloc;
699         char *buf = (char*)alloc.allocate(size + 1);
700         if (!buf) return false;
701         oscl_memcpy(buf, defaultUserAgent.get_cstr(), defaultUserAgent.get_size());
702         buf[defaultUserAgent.get_size()] = PROTOCOLENGINENODE_SPACE_ASCIICODE;
703         if (iInputUserAgent.get_size() > 0)
704         {
705             oscl_memcpy(buf + defaultUserAgent.get_size() + 1, iInputUserAgent.get_cstr(), iInputUserAgent.get_size());
706         }
707         buf[size] = 0;
708         iActualUserAgent = OSCL_HeapString<OsclMemAllocator> (buf, size);
709         alloc.deallocate(buf);
710     }
711     aUserAgent = iActualUserAgent;
712     return true;
713 }
714 
715 ////////////////////////////////////////////////////////////////////////////////////
716 //////  EventReporter implementation
717 ////////////////////////////////////////////////////////////////////////////////////
EventReporter(EventReporterObserver * aObserver)718 OSCL_EXPORT_REF EventReporter::EventReporter(EventReporterObserver *aObserver) : iObserver(aObserver)
719 {
720     clear();
721     iDataPathLogger = PVLogger::GetLoggerObject(NODEDATAPATHLOGGER_TAG);
722 }
723 
clear()724 OSCL_EXPORT_REF void EventReporter::clear()
725 {
726     iStarted = false;
727 }
728 
startRealDataflow()729 OSCL_EXPORT_REF void EventReporter::startRealDataflow()
730 {
731     iStarted = true;
732 }
733 
734 
735 ////////////////////////////////////////////////////////////////////////////////////
736 //////  InterfacingObjectContainer implementation
737 ////////////////////////////////////////////////////////////////////////////////////
738 
739 // constructor
InterfacingObjectContainer()740 InterfacingObjectContainer::InterfacingObjectContainer() :
741         iDownloadFormat(PVMF_MIME_DATA_SOURCE_HTTP_URL),
742         iDataStreamFactory(NULL),
743         iNumBuffersInAllocator(PVHTTPSTREAMINGOUTPUT_CONTENTDATA_POOLNUM),
744         iNumRedirectTrials(PVPROTOCOLENGINE_DEFAULT_NUMBER_OF_REDIRECT_TRIALS),
745         iNumBuffersInMediaDataPoolSMCalc(PVHTTPSTREAMINGOUTPUT_CONTENTDATA_POOLNUM),
746         iCurrSocketConnection(true),
747         iPrevSocketConnection(true),
748         iLatestDataPacketNumSent(0),
749         iOutputPortConnected(false)
750 {
751     clear();
752     iOutgoingMsgSentSuccessInfoVec.reserve(PVMF_PROTOCOLENGINE_NODE_COMMAND_VECTOR_RESERVE / 4);
753 }
754 
755 // set and get http header
setHttpHeader(OUTPUT_DATA_QUEUE & aHttpHeader)756 OSCL_EXPORT_REF uint32 InterfacingObjectContainer::setHttpHeader(OUTPUT_DATA_QUEUE &aHttpHeader)
757 {
758     iHttpHeaderLength = 0;
759     uint32 i = 0;
760     char *ptr = (char*)iHttpHeaderBuffer;
761     for (i = 0; i < aHttpHeader.size(); i++)
762     {
763         uint32 fragSize = aHttpHeader[i].getMemFragSize();
764         oscl_memcpy(ptr, (char*)aHttpHeader[i].getMemFragPtr(), fragSize);
765         iHttpHeaderLength += fragSize;
766         ptr += fragSize;
767     }
768     iHttpHeaderBuffer[iHttpHeaderLength] = 0;
769     return iHttpHeaderLength;
770 }
771 
setStreamingProxy(OSCL_wString & aProxyName,const uint32 aProxyPort)772 OSCL_EXPORT_REF bool InterfacingObjectContainer::setStreamingProxy(OSCL_wString& aProxyName, const uint32 aProxyPort)
773 {
774     if (aProxyName.get_size() == 0) return false;
775 
776     OsclMemAllocator alloc;
777     char *buf = (char*)alloc.allocate(aProxyName.get_size() + 1);
778     if (!buf) return false;
779     uint32 size = oscl_UnicodeToUTF8(aProxyName.get_cstr(), aProxyName.get_size(), buf, aProxyName.get_size() + 1);
780     if (size == 0)
781     {
782         alloc.deallocate(buf);
783         return false;
784     }
785     iProxyName = OSCL_HeapString<OsclMemAllocator> (buf, size);
786     iProxyPort = aProxyPort;
787     alloc.deallocate(buf);
788     return true;
789 }
790 
setNumBuffersInMediaDataPoolSMCalc(uint32 aVal)791 OSCL_EXPORT_REF void InterfacingObjectContainer::setNumBuffersInMediaDataPoolSMCalc(uint32 aVal)
792 {
793     iNumBuffersInMediaDataPoolSMCalc = aVal;
794 }
795 
796 
797 ////////////////////////////////////////////////////////////////////////////////////
798 //////  PVMFProtocolEngineNodeTimer implementation
799 ////////////////////////////////////////////////////////////////////////////////////
800 
create(OsclTimerObserver * aObserver)801 OSCL_EXPORT_REF PVMFProtocolEngineNodeTimer* PVMFProtocolEngineNodeTimer::create(OsclTimerObserver *aObserver)
802 {
803     PVMFProtocolEngineNodeTimer *timer = OSCL_NEW(PVMFProtocolEngineNodeTimer, ());
804     if (!timer) return NULL;
805     if (!timer->construct(aObserver))
806     {
807         OSCL_DELETE(timer);
808         return NULL;
809     }
810     return timer;
811 }
812 
construct(OsclTimerObserver * aObserver)813 bool PVMFProtocolEngineNodeTimer::construct(OsclTimerObserver *aObserver)
814 {
815     // create iWatchdogTimer
816     iWatchdogTimer = OSCL_NEW(OsclTimer<PVMFProtocolEngineNodeAllocator>, ("ProtEngineNodeWatchdogTimer"));
817     if (!iWatchdogTimer) return false;
818     iWatchdogTimer->SetObserver(aObserver);
819     iWatchdogTimer->SetFrequency(PVPROTOCOLENGINENODE_TIMER_FREQUENCY);
820 
821     int32 err = 0;
822     OSCL_TRY(err, iTimerVec.reserve(DEFAULT_TIMER_VECTOR_RESERVE_NUMBER);)
823     return (err ? false : true);
824 }
825 
~PVMFProtocolEngineNodeTimer()826 OSCL_EXPORT_REF PVMFProtocolEngineNodeTimer::~PVMFProtocolEngineNodeTimer()
827 {
828     if (iWatchdogTimer)
829     {
830         OSCL_DELETE(iWatchdogTimer);
831         iWatchdogTimer = NULL;
832     }
833 
834     iTimerVec.clear();
835 }
836 
set(const uint32 aTimerID,const int32 aTimeout)837 OSCL_EXPORT_REF void PVMFProtocolEngineNodeTimer::set(const uint32 aTimerID, const int32 aTimeout)
838 {
839     uint32 index = getTimerVectorIndex(aTimerID);
840     if (index == 0xffffffff)
841     {
842         // attach the new timer
843         uint32 timeout = aTimeout;
844         if (timeout == 0) timeout = getDefaultTimeout(aTimerID);
845         TimerUnit timerUnit(aTimerID, timeout);
846         iTimerVec.push_back(timerUnit);
847     }
848     else
849     {
850         // existing timer
851         uint32 timeout = iTimerVec[index].iTimeout;
852         if (aTimeout > 0 || (aTimeout == 0 && aTimerID == SERVER_RESPONSE_TIMER_ID_FOR_STOPEOS_LOGGING))
853         {
854             // for stop/eos logging timeout, allow zero timeout
855             iTimerVec[index].iTimeout = aTimeout;
856         }
857         timeout = iTimerVec[index].iTimeout;
858     }
859 }
860 
getTimeout(const uint32 aTimerID)861 OSCL_EXPORT_REF uint32 PVMFProtocolEngineNodeTimer::getTimeout(const uint32 aTimerID)
862 {
863     uint32 aTimeout = 0xffffffff;
864     uint32 index = getTimerVectorIndex(aTimerID);
865     if (index != 0xffffffff)
866     {
867         // existing timer
868         aTimeout = iTimerVec[index].iTimeout;
869     }
870     return aTimeout;
871 }
872 
873 
cancel(const uint32 aTimerID)874 OSCL_EXPORT_REF void PVMFProtocolEngineNodeTimer::cancel(const uint32 aTimerID)
875 {
876     uint32 index = getTimerVectorIndex(aTimerID);
877     if (index != 0xffffffff)
878     {
879         // find this timer and cancel it
880         iWatchdogTimer->Cancel(aTimerID);
881     }
882 }
883 
clear()884 void PVMFProtocolEngineNodeTimer::clear()
885 {
886     for (uint32 i = 0; i < iTimerVec.size(); i++)
887     {
888         iWatchdogTimer->Cancel(iTimerVec[i].iTimerID);
889     }
890 }
891 
clearExcept(const uint32 aTimerID)892 OSCL_EXPORT_REF void PVMFProtocolEngineNodeTimer::clearExcept(const uint32 aTimerID)
893 {
894     for (uint32 i = 0; i < iTimerVec.size(); i++)
895     {
896         if (iTimerVec[i].iTimerID != aTimerID)
897         {
898             iWatchdogTimer->Cancel(iTimerVec[i].iTimerID);
899         }
900     }
901 }
902 
start(const uint32 aTimerID,const int32 aTimeout)903 OSCL_EXPORT_REF bool PVMFProtocolEngineNodeTimer::start(const uint32 aTimerID, const int32 aTimeout)
904 {
905     uint32 index = getTimerVectorIndex(aTimerID);
906     if (index == 0xffffffff) return false;
907     if (aTimeout) iTimerVec[index].iTimeout = aTimeout;
908     if (iTimerVec[index].iTimeout == 0)
909     {
910         iTimerVec[index].iTimeout = getDefaultTimeout(aTimerID);
911     }
912 
913     iWatchdogTimer->Cancel(iTimerVec[index].iTimerID);
914     iWatchdogTimer->Request(iTimerVec[index].iTimerID, 0, iTimerVec[index].iTimeout);
915     return true;
916 }
917 
getDefaultTimeout(const uint32 aTimerID)918 uint32 PVMFProtocolEngineNodeTimer::getDefaultTimeout(const uint32 aTimerID)
919 {
920     switch (aTimerID)
921     {
922         case SERVER_RESPONSE_TIMER_ID:
923             return DEFAULT_MAX_SERVER_RESPONSE_DURATION_IN_SEC;
924         case SERVER_INACTIVITY_TIMER_ID:
925             return DEFAULT_MAX_SERVER_INACTIVITY_DURATION_IN_SEC;
926         case SERVER_KEEPALIVE_TIMER_ID:
927             return DEFAULT_KEEPALIVE_TIMEOUT_IN_SEC;
928         case SERVER_RESPONSE_TIMER_ID_FOR_STOPEOS_LOGGING:
929             return DEFAULT_MAX_SERVER_RESPONSE_DURATION_IN_SEC_FOR_STOPEOS_LOGGING;
930         case WALL_CLOCK_TIMER_ID:
931             return DEFAULT_WALLCLOCK_TIMEOUT_IN_SEC;
932         case BUFFER_STATUS_TIMER_ID:
933             return DEFAULT_BUFFER_STATUS_CLOCK_TIMEOUT_IN_SEC;
934         default:
935             break;
936     }
937     return 0;
938 }
939 
getTimerVectorIndex(const uint32 aTimerID)940 uint32 PVMFProtocolEngineNodeTimer::getTimerVectorIndex(const uint32 aTimerID)
941 {
942     for (uint32 i = 0; i < iTimerVec.size(); i++)
943     {
944         if (iTimerVec[i].iTimerID == aTimerID) return i;
945     }
946     return ~0;
947 }
948 
949