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
19 #include "pvmf_clientserver_socket_node.h"
20 #include "oscl_string_utils.h"
21 #include "pvmf_basic_errorinfomessage.h"
22 #include "pvmf_errorinfomessage_extension.h"
23 #include "oscl_byte_order.h"
24 #include "pvmf_media_cmd.h"
25 #include "pvmf_media_msg_format_ids.h"
26 #include "oscl_tickcount.h"
27 #include "oscl_rand.h"
28 #include "oscl_time.h"
29 #include "oscl_bin_stream.h"
30
31 // Use default DLL entry point for Symbian
32 #include "oscl_dll.h"
33
34 //////////////////////////////////////////////////
35 // Standard Node APIs
36 //////////////////////////////////////////////////
37
PVMFClientServerSocketNode(OsclTCPSocket * aSocketHandle,int32 aPriority)38 OSCL_EXPORT_REF PVMFClientServerSocketNode::PVMFClientServerSocketNode(OsclTCPSocket* aSocketHandle, int32 aPriority)
39 : OsclActiveObject(aPriority, "PVMFClientServerSocketNode")
40 , iSockServ(NULL)
41 , TIMEOUT_CONNECT(-1)
42 , TIMEOUT_SEND(-1)
43 , TIMEOUT_RECV(-1)
44 , TIMEOUT_SHUTDOWN(-1)
45 , iSocketHandle(aSocketHandle)
46 , iSockConfig(NULL)
47 {
48 iLogger = NULL;
49 iDataPathLogger = NULL;
50 iOsclErrorTrapImp = NULL;
51 iExtensionRefCount = 0;
52 iMaxTcpRecvBufferSize = SNODE_DEFAULT_SOCKET_TCP_BUFFER_SIZE;
53 iMaxTcpRecvBufferCount = SNODE_DEFAULT_SOCKET_TCP_BUFFER_COUNT;
54 iSocketID = 0;
55 iCommandErrorCode = PVMFSocketNodeErrorEventStart;
56 iErrorEventErrorCode = PVMFSocketNodeErrorEventStart;
57
58 iPVMFPort = NULL;
59 iNumStopPortActivityPending = (-1);//inactive.
60
61 int32 err;
62 OSCL_TRY(err,
63
64 iPendingCmdQueue.Construct(PVMF_SOCKET_NODE_COMMAND_ID_START,
65 PVMF_SOCKET_NODE_COMMAND_VECTOR_RESERVE);
66
67 //Create the "current command" queue. It will only contain one
68 //command at a time, so use a reserve of 1.
69 iCurrentCmdQueue.Construct(0, 1);
70 iCancelCmdQueue.Construct(0, 1);
71 );
72
73 if (err != OsclErrNone)
74 {
75 //if a leave happened, cleanup and re-throw the error
76 iPendingCmdQueue.clear();
77 iCurrentCmdQueue.clear();
78 iCancelCmdQueue.clear();
79 if (iPVMFPort)
80 {
81 iPVMFPort->Disconnect();
82 delete iPVMFPort;
83 iPVMFPort = NULL;
84 }
85 OSCL_CLEANUP_BASE_CLASS(PVMFNodeInterface);
86 OSCL_CLEANUP_BASE_CLASS(OsclActiveObject);
87 OSCL_LEAVE(err);
88 }
89 }
90
91
~PVMFClientServerSocketNode()92 OSCL_EXPORT_REF PVMFClientServerSocketNode::~PVMFClientServerSocketNode()
93 {
94 Cancel();
95
96 //thread logoff
97 if (IsAdded())
98 RemoveFromScheduler();
99
100 /* Cleanup allocated ports */
101 CleanupPorts();
102
103 //Cleanup commands
104 while (!iCurrentCmdQueue.empty())
105 {
106 CommandComplete(iCurrentCmdQueue, iCurrentCmdQueue.front(), PVMFFailure);
107 }
108 while (!iPendingCmdQueue.empty())
109 {
110 CommandComplete(iPendingCmdQueue, iPendingCmdQueue.front(), PVMFFailure);
111 }
112 while (!iCancelCmdQueue.empty())
113 {
114 CommandComplete(iCancelCmdQueue, iCancelCmdQueue.front(), PVMFFailure);
115 }
116 }
117
118
ThreadLogon()119 OSCL_EXPORT_REF PVMFStatus PVMFClientServerSocketNode::ThreadLogon()
120 {
121 switch (iInterfaceState)
122 {
123 case EPVMFNodeCreated:
124 if (!IsAdded())
125 AddToScheduler();
126 iLogger = PVLogger::GetLoggerObject("PVMFClientServerSocketNode");
127 iDataPathLogger = PVLogger::GetLoggerObject("datapath.socketnode");
128 iOsclErrorTrapImp = OsclErrorTrap::GetErrorTrapImp();
129 SetState(EPVMFNodeIdle);
130 return PVMFSuccess;
131 default:
132 return PVMFErrInvalidState;
133 }
134 }
135
136
ThreadLogoff()137 OSCL_EXPORT_REF PVMFStatus PVMFClientServerSocketNode::ThreadLogoff()
138 {
139 PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFClientServerSocketNode:ThreadLogoff"));
140
141 switch (iInterfaceState)
142 {
143 case EPVMFNodeIdle:
144 {
145 if (IsAdded())
146 RemoveFromScheduler();
147 iLogger = NULL;
148 iDataPathLogger = NULL;
149 iOsclErrorTrapImp = NULL;
150 SetState(EPVMFNodeCreated);
151 return PVMFSuccess;
152 }
153 default:
154 return PVMFErrInvalidState;
155 }
156 }
157
158
GetCapability(PVMFNodeCapability & aNodeCapability)159 OSCL_EXPORT_REF PVMFStatus PVMFClientServerSocketNode::GetCapability(PVMFNodeCapability& aNodeCapability)
160 {
161 OSCL_UNUSED_ARG(aNodeCapability);
162 return PVMFSuccess;
163 }
164
GetPorts(const PVMFPortFilter * aFilter)165 OSCL_EXPORT_REF PVMFPortIter* PVMFClientServerSocketNode::GetPorts(const PVMFPortFilter* aFilter)
166 {
167 OSCL_UNUSED_ARG(aFilter);
168 //retrive a port iterator
169 return (PVMFPortIter*)iPVMFPort;
170 }
171
QueryUUID(PVMFSessionId s,const PvmfMimeString & aMimeType,Oscl_Vector<PVUuid,OsclMemAllocator> & aUuids,bool aExactUuidsOnly,const OsclAny * aContext)172 OSCL_EXPORT_REF PVMFCommandId PVMFClientServerSocketNode::QueryUUID(PVMFSessionId s, const PvmfMimeString& aMimeType,
173 Oscl_Vector<PVUuid, OsclMemAllocator>& aUuids,
174 bool aExactUuidsOnly,
175 const OsclAny* aContext)
176 {
177 PVMFSocketNodeCommand cmd;
178 cmd.PVMFSocketNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_QUERYUUID, aMimeType, aUuids, aExactUuidsOnly, aContext);
179 return QueueCommandL(cmd);
180 }
181
QueryInterface(PVMFSessionId s,const PVUuid & aUuid,PVInterface * & aInterfacePtr,const OsclAny * aContext)182 OSCL_EXPORT_REF PVMFCommandId PVMFClientServerSocketNode::QueryInterface(PVMFSessionId s, const PVUuid& aUuid,
183 PVInterface*& aInterfacePtr,
184 const OsclAny* aContext)
185 {
186 PVMFSocketNodeCommand cmd;
187 cmd.PVMFSocketNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_QUERYINTERFACE, aUuid, aInterfacePtr, aContext);
188 return QueueCommandL(cmd);
189 }
190
RequestPort(PVMFSessionId s,int32 aPortTag,const PvmfMimeString * aPortConfig,const OsclAny * aContext)191 OSCL_EXPORT_REF PVMFCommandId PVMFClientServerSocketNode::RequestPort(PVMFSessionId s, int32 aPortTag, const PvmfMimeString* aPortConfig, const OsclAny* aContext)
192 {
193 PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFClientServerSocketNode:RequestPort"));
194 PVMFSocketNodeCommand cmd;
195 cmd.PVMFSocketNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_REQUESTPORT, aPortTag, aPortConfig, aContext);
196 return QueueCommandL(cmd);
197 }
198
ReleasePort(PVMFSessionId s,PVMFPortInterface & aPort,const OsclAny * aContext)199 OSCL_EXPORT_REF PVMFCommandId PVMFClientServerSocketNode::ReleasePort(PVMFSessionId s, PVMFPortInterface& aPort, const OsclAny* aContext)
200 {
201 PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFClientServerSocketNode:ReleasePort"));
202 PVMFSocketNodeCommand cmd;
203 cmd.PVMFSocketNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_RELEASEPORT, aPort, aContext);
204 return QueueCommandL(cmd);
205 }
206
Init(PVMFSessionId s,const OsclAny * aContext)207 OSCL_EXPORT_REF PVMFCommandId PVMFClientServerSocketNode::Init(PVMFSessionId s, const OsclAny* aContext)
208 {
209 PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFClientServerSocketNode:Init"));
210 PVMFSocketNodeCommand cmd;
211 cmd.PVMFSocketNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_INIT, aContext);
212 return QueueCommandL(cmd);
213 }
214
Prepare(PVMFSessionId s,const OsclAny * aContext)215 OSCL_EXPORT_REF PVMFCommandId PVMFClientServerSocketNode::Prepare(PVMFSessionId s, const OsclAny* aContext)
216 {
217 PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFClientServerSocketNode:Init"));
218 PVMFSocketNodeCommand cmd;
219 cmd.PVMFSocketNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_PREPARE, aContext);
220 return QueueCommandL(cmd);
221 }
222
Start(PVMFSessionId s,const OsclAny * aContext)223 OSCL_EXPORT_REF PVMFCommandId PVMFClientServerSocketNode::Start(PVMFSessionId s, const OsclAny* aContext)
224 {
225 PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFClientServerSocketNode:Start"));
226 PVMFSocketNodeCommand cmd;
227 cmd.PVMFSocketNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_START, aContext);
228 return QueueCommandL(cmd);
229 }
230
Stop(PVMFSessionId s,const OsclAny * aContext)231 OSCL_EXPORT_REF PVMFCommandId PVMFClientServerSocketNode::Stop(PVMFSessionId s, const OsclAny* aContext)
232 {
233 PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFClientServerSocketNode:Stop"));
234 PVMFSocketNodeCommand cmd;
235 cmd.PVMFSocketNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_STOP, aContext);
236 return QueueCommandL(cmd);
237 }
238
Flush(PVMFSessionId s,const OsclAny * aContext)239 OSCL_EXPORT_REF PVMFCommandId PVMFClientServerSocketNode::Flush(PVMFSessionId s, const OsclAny* aContext)
240 {
241 PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFClientServerSocketNode:Flush"));
242 PVMFSocketNodeCommand cmd;
243 cmd.PVMFSocketNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_FLUSH, aContext);
244 return QueueCommandL(cmd);
245 }
246
Pause(PVMFSessionId s,const OsclAny * aContext)247 OSCL_EXPORT_REF PVMFCommandId PVMFClientServerSocketNode::Pause(PVMFSessionId s, const OsclAny* aContext)
248 {
249 PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFClientServerSocketNode:Pause"));
250 PVMFSocketNodeCommand cmd;
251 cmd.PVMFSocketNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_PAUSE, aContext);
252 return QueueCommandL(cmd);
253 }
254
Reset(PVMFSessionId s,const OsclAny * aContext)255 OSCL_EXPORT_REF PVMFCommandId PVMFClientServerSocketNode::Reset(PVMFSessionId s, const OsclAny* aContext)
256 {
257 PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFClientServerSocketNode:Reset"));
258 PVMFSocketNodeCommand cmd;
259 cmd.PVMFSocketNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_RESET, aContext);
260 return QueueCommandL(cmd);
261 }
262
CancelAllCommands(PVMFSessionId s,const OsclAny * aContext)263 OSCL_EXPORT_REF PVMFCommandId PVMFClientServerSocketNode::CancelAllCommands(PVMFSessionId s, const OsclAny* aContext)
264 {
265 PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFClientServerSocketNode:CancelAllCommands"));
266 PVMFSocketNodeCommand cmd;
267 cmd.PVMFSocketNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_CANCELALLCOMMANDS, aContext);
268 return QueueCommandL(cmd);
269 }
270
CancelCommand(PVMFSessionId s,PVMFCommandId aCmdId,const OsclAny * aContext)271 OSCL_EXPORT_REF PVMFCommandId PVMFClientServerSocketNode::CancelCommand(PVMFSessionId s, PVMFCommandId aCmdId, const OsclAny* aContext)
272 {
273 PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFClientServerSocketNode:CancelCommand"));
274 PVMFSocketNodeCommand cmd;
275 cmd.PVMFSocketNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_CANCELCOMMAND, aCmdId, aContext);
276 return QueueCommandL(cmd);
277 }
278
279 //Port activity handler
HandlePortActivity(const PVMFPortActivity & aActivity)280 void PVMFClientServerSocketNode::HandlePortActivity(const PVMFPortActivity &aActivity)
281 {
282 PVMFClientServerSocketPort* sockPort = NULL;
283 switch (aActivity.iType)
284 {
285 case PVMF_PORT_ACTIVITY_CONNECT:
286 {
287 sockPort = OSCL_STATIC_CAST(PVMFClientServerSocketPort*, aActivity.iPort);
288 OSCL_ASSERT(sockPort && sockPort->iConfig);
289 *iSockConfig = *sockPort->iConfig;
290
291 setSocketPortMemAllocator(aActivity.iPort, sockPort->iAllocSharedPtr);
292
293 //Receives may have been blocked waiting on the port to be connected, so check here.
294 if (CanReceive())
295 StartRecvOperation();
296 }
297 break;
298
299 case PVMF_PORT_ACTIVITY_INCOMING_MSG:
300 {
301 sockPort = (PVMFClientServerSocketPort*)(aActivity.iPort);
302 OSCL_ASSERT(sockPort && sockPort->iConfig);
303
304 //Try to process this message now.
305 if (CanProcessIncomingMsg())
306 ProcessIncomingMsg();
307 //Otherwise, ignore this event now. Other code will check
308 //the input queue as needed.
309 }
310 break;
311
312 case PVMF_PORT_ACTIVITY_CONNECTED_PORT_READY:
313 {
314 sockPort = (PVMFClientServerSocketPort*)(aActivity.iPort);
315 OSCL_ASSERT(sockPort && sockPort->iConfig);
316 SocketPortConfig& aSockConfig = *sockPort->iConfig;
317
318 if (aSockConfig.iState.iRecvOperation == EPVSocketPortRecvOperation_WaitOnConnectedPort)
319 {
320 RecvOperationComplete(PVMFSuccess, NULL);
321 }
322
323 //Otherwise ignore this event now. Other code will check connected
324 //port status as needed.
325 }
326 break;
327
328 default:
329 //all other events can be ignored.
330 break;
331 }
332 }
333
334
addRef()335 OSCL_EXPORT_REF void PVMFClientServerSocketNode::addRef()
336 {
337 ++iExtensionRefCount;
338 }
339
removeRef()340 OSCL_EXPORT_REF void PVMFClientServerSocketNode::removeRef()
341 {
342 --iExtensionRefCount;
343 }
344
queryInterface(const PVUuid & uuid,PVInterface * & iface)345 OSCL_EXPORT_REF bool PVMFClientServerSocketNode::queryInterface(const PVUuid& uuid, PVInterface*& iface)
346 {
347 OSCL_UNUSED_ARG(uuid);
348 OSCL_UNUSED_ARG(iface);
349 return false;
350 }
351
Run()352 void PVMFClientServerSocketNode::Run()
353 {
354 //Process node commands
355 while (CanProcessCommand())
356 ProcessCommand(iPendingCmdQueue, iPendingCmdQueue.front());
357 }
358
359
CanProcessCommand()360 bool PVMFClientServerSocketNode::CanProcessCommand()
361 {
362 return (!iPendingCmdQueue.empty()
363 && (iCurrentCmdQueue.empty()
364 || (iPendingCmdQueue.front().hipri() && iCancelCmdQueue.empty())));
365 }
366
367 //Process an input command.
ProcessCommand(PVMFSocketNodeCmdQ & aCmdQ,PVMFSocketNodeCommand & aCmd)368 void PVMFClientServerSocketNode::ProcessCommand(PVMFSocketNodeCmdQ& aCmdQ, PVMFSocketNodeCommand& aCmd)
369 {
370 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFSocketNodeCommand::ProcessCommand() in"));
371
372 PVMFStatus status = PVMFFailure;
373 iCommandErrorCode = PVMFSocketNodeErrorEventStart; //no error
374
375 if (aCmd.hipri())
376 {
377 //calling logic should prevent multiple cancels in progress.
378 OSCL_ASSERT(iCancelCmdQueue.empty());
379
380 switch (aCmd.iCmd)
381 {
382 case PVMF_GENERIC_NODE_CANCELALLCOMMANDS:
383 status = DoCancelAllCommands(aCmd);
384 break;
385
386 case PVMF_GENERIC_NODE_CANCELCOMMAND:
387 status = DoCancelCommand(aCmd);
388 break;
389
390 default://unknown command type
391 status = PVMFFailure;
392 break;
393 }
394
395 //If the command was not finished in this call, then move it to the
396 //"cancel cmd" queue where it will remain until it is completed.
397 if (status == PVMFPending)
398 {
399 //move the new cmd to the "cancel cmd" queue where it will
400 //remain until complete.
401 int32 err;
402 OSCL_TRY(err, iCancelCmdQueue.StoreL(aCmd););
403
404 //we reserved space in the CancelCmdQueue already, so
405 //it should not be possible to fail here.
406 OSCL_ASSERT(err == OsclErrNone);
407
408 //erase the original command
409 aCmdQ.Erase(&aCmd);
410 }
411 else
412 {
413 CommandComplete(aCmdQ, aCmd, status, NULL);
414 }
415 }
416 else
417 {
418 //calling logic should prevent multiple commands in progress.
419 OSCL_ASSERT(iCurrentCmdQueue.empty());
420
421 OsclAny* eventData = NULL;
422
423 switch (aCmd.iCmd)
424 {
425 case PVMF_GENERIC_NODE_QUERYUUID:
426 status = DoQueryUuid(aCmd);
427 break;
428
429 case PVMF_GENERIC_NODE_QUERYINTERFACE:
430 status = DoQueryInterface(aCmd);
431 break;
432
433 case PVMF_GENERIC_NODE_REQUESTPORT:
434 {
435 status = DoRequestPort(aCmd);
436 eventData = iPVMFPort;
437 break;
438 }
439
440 case PVMF_GENERIC_NODE_RELEASEPORT:
441 status = DoReleasePort(aCmd);
442 break;
443
444 case PVMF_GENERIC_NODE_INIT:
445 status = DoInit(aCmd);
446 break;
447
448 case PVMF_GENERIC_NODE_PREPARE:
449 status = DoPrepare(aCmd);
450 if (status == PVMFSuccess)
451 {
452 ChangeExternalState(EPVMFNodePrepared);
453 }
454 break;
455
456 case PVMF_GENERIC_NODE_START:
457 status = DoStart(aCmd);
458 break;
459
460 case PVMF_GENERIC_NODE_STOP:
461 status = DoStop(aCmd);
462 break;
463
464 case PVMF_GENERIC_NODE_FLUSH:
465 status = DoFlush(aCmd);
466 break;
467
468 case PVMF_GENERIC_NODE_PAUSE:
469 status = DoPause(aCmd);
470 break;
471
472 case PVMF_GENERIC_NODE_RESET:
473 status = DoReset(aCmd);
474 break;
475
476 default://unknown command type
477 status = PVMFFailure;
478 break;
479 }
480
481 if (status == PVMFPending)
482 {
483 int32 err;
484 OSCL_TRY(err, iCurrentCmdQueue.StoreL(aCmd););
485 OSCL_ASSERT(err == OsclErrNone);
486
487 //erase the original command
488 aCmdQ.Erase(&aCmd);
489 }
490 else
491 {
492 CommandComplete(aCmdQ, aCmd, status, eventData);
493 }
494 }
495 }
496
497 //Called to complete a node command.
CommandComplete(PVMFSocketNodeCmdQ & aCmdQ,PVMFSocketNodeCommand & aCmd,PVMFStatus aStatus,OsclAny * aEventData,PVUuid * aEventUUID,int32 * aEventCode)498 void PVMFClientServerSocketNode::CommandComplete(PVMFSocketNodeCmdQ& aCmdQ,
499 PVMFSocketNodeCommand& aCmd,
500 PVMFStatus aStatus,
501 OsclAny* aEventData,
502 PVUuid* aEventUUID,
503 int32* aEventCode)
504
505 {
506 PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFClientServerSocketNode:CommandComplete Id %d Cmd %d Status %d Context %d Data %d"
507 , aCmd.iId, aCmd.iCmd, aStatus, aCmd.iContext, aEventData));
508
509 bool canProcess = CanProcessCommand();
510
511 PVMFStatus status = aStatus;
512
513 if (aStatus == PVMFSuccess)
514 {
515 switch (aCmd.iCmd)
516 {
517 case PVMF_GENERIC_NODE_INIT:
518 ChangeExternalState(EPVMFNodeInitialized);
519 break;
520
521 case PVMF_GENERIC_NODE_PREPARE:
522 ChangeExternalState(EPVMFNodePrepared);
523 break;
524
525 case PVMF_GENERIC_NODE_START:
526 ChangeExternalState(EPVMFNodeStarted);
527 break;
528
529 case PVMF_GENERIC_NODE_STOP:
530 ChangeExternalState(EPVMFNodePrepared);
531 break;
532
533 case PVMF_GENERIC_NODE_PAUSE:
534 ChangeExternalState(EPVMFNodePaused);
535 break;
536
537 case PVMF_GENERIC_NODE_RESET:
538 ChangeExternalState(EPVMFNodeCreated);
539
540 //Complete the reset command.
541 {
542 //cleanup all ports.
543 CleanupPorts();
544 SetState(EPVMFNodeIdle);
545 }
546 break;
547
548 case PVMF_GENERIC_NODE_CANCELALLCOMMANDS:
549 //Complete the reset command.
550 {
551 //Since "cancel all" is effectively used as a Reset,
552 //go ahead and cleanup all ports.
553 CleanupPorts();
554 }
555 break;
556 default:
557 break;
558 }
559 }
560
561 PVInterface* extif = NULL;
562 PVMFBasicErrorInfoMessage* errormsg = NULL;
563 if (aEventUUID && aEventCode)
564 {
565 errormsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (*aEventCode, *aEventUUID, NULL));
566 extif = OSCL_STATIC_CAST(PVInterface*, errormsg);
567 }
568 //else if no error input, see if "command error code" was set.
569 else if (iCommandErrorCode != PVMFSocketNodeErrorEventStart)
570 {
571 PVUuid eventuuid = PVMFSocketNodeEventTypeUUID;
572 errormsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (iCommandErrorCode, eventuuid, NULL));
573 extif = OSCL_STATIC_CAST(PVInterface*, errormsg);
574 }
575
576 //create response
577 PVMFCmdResp resp(aCmd.iId, aCmd.iContext, status, extif, aEventData);
578 PVMFSessionId session = aCmd.iSession;
579
580 //Erase the command from the queue.
581 aCmdQ.Erase(&aCmd);
582
583 //Report completion to the session observer.
584 ReportCmdCompleteEvent(session, resp);
585
586 if (errormsg)
587 {
588 errormsg->removeRef();
589 }
590 iCommandErrorCode = PVMFSocketNodeErrorEventStart;//reset.
591
592 //See if there was a pending cancel waiting on the current command to
593 //complete.
594 if (!iCancelCmdQueue.empty()
595 && iCancelCmdQueue.front().iCmd == PVMF_GENERIC_NODE_CANCELCOMMAND)
596 {
597 CommandComplete(iCancelCmdQueue, iCancelCmdQueue.front(), PVMFSuccess);
598 }
599
600 //May need to resume command handling if the AO was blocked
601 //waiting on asynchronous command completion, but it's unblocked now.
602 if (!canProcess
603 && CanProcessCommand()
604 && IsAdded())
605 {
606 RunIfNotReady();
607 }
608 }
609
QueueCommandL(PVMFSocketNodeCommand & aCmd)610 PVMFCommandId PVMFClientServerSocketNode::QueueCommandL(PVMFSocketNodeCommand& aCmd)
611 {
612 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFClientServerSocketNode::QueueCommandL()"));
613 PVMFCommandId id;
614
615 id = iPendingCmdQueue.AddL(aCmd);
616
617 //This may be a processing trigger.
618 //Wakeup the AO if needed.
619 if (IsAdded()
620 && CanProcessCommand())
621 {
622 RunIfNotReady();
623 }
624
625 return id;
626 }
627
628 //This is the callback from Oscl Sockets for socket operation completion.
HandleSocketEvent(int32 aId,TPVSocketFxn aFxn,TPVSocketEvent aEvent,int32 aError)629 OSCL_EXPORT_REF void PVMFClientServerSocketNode::HandleSocketEvent(int32 aId, TPVSocketFxn aFxn, TPVSocketEvent aEvent, int32 aError)
630 {
631 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFClientServerSocketNode::HandleSocketEvent() In aId=%d, aFxn=%d, aEvent=%d, aError=%d", aId, aFxn, aEvent, aError));
632
633 if (iSockConfig && aEvent == EPVSocketSuccess)
634 {
635 PVMFSocketActivity activity((aEvent == EPVSocketSuccess) ? PVMFSuccess : PVMFFailure, aId, aFxn, aEvent, aError);
636
637 //Call the appropriate handler
638 switch (aFxn)
639 {
640 case EPVSocketRecv:
641 OSCL_ASSERT(iSockConfig->iState.iRecvOperation == EPVSocketPortRecvOperation_Recv);
642
643 RecvOperationComplete(activity.iStatus, &activity);
644 break;
645
646 case EPVSocketSend:
647 OSCL_ASSERT(iSockConfig->iState.iSendOperation == EPVSocketPortSendOperation_Send);
648
649 SendOperationComplete(activity.iStatus, &activity);
650 break;
651
652 case EPVSocketShutdown:
653 //OSCL_ASSERT(iSockConfig->iState.iConnectOperation==EPVSocketPortConnectOperation_Shutdown);
654 SequenceComplete(PVMFSuccess);
655 //ConnectOperationComplete(activity.iStatus,&activity);
656 break;
657
658 default:
659 OSCL_ASSERT(0);//unexpected
660 break;
661 }
662 }
663 else if (aEvent == EPVSocketCancel)
664 {
665 switch (aFxn)
666 {
667 case EPVSocketRecv:
668 if (iSockConfig->iState.iSendOperation == EPVSocketPortSendOperation_Send
669 && iSockConfig->iState.iSendOperationCanceled == false)
670 {//if does hv anything to send, cancel it
671 CancelSendOperation();
672 }
673 else
674 { //shutdown
675 CloseSocketConnection();
676 }
677 break;
678
679 case EPVSocketSend:
680 if (iSockConfig->iState.iRecvOperation == EPVSocketPortRecvOperation_Recv
681 && iSockConfig->iState.iRecvOperationCanceled == false)
682 {
683 CancelRecvOperation();
684 }
685 else
686 {
687 //shutdown
688 CloseSocketConnection();
689 }
690 break;
691
692 case EPVSocketShutdown:
693 //quite difficult to cancel shutdown
694 break;
695
696 default:
697 OSCL_ASSERT(0);//unexpected
698 break;
699 }
700 }
701 else
702 {//failure
703 switch (aFxn)
704 {
705 case EPVSocketRecv:
706 iSockConfig->iState.iRecvOperation = EPVSocketPortRecvOperation_None;
707 iSockConfig->iState.iRecvOperationCanceled = true;
708 break;
709
710 case EPVSocketSend:
711 iSockConfig->iState.iSendOperation = EPVSocketPortSendOperation_None;
712 iSockConfig->iState.iSendOperationCanceled = true;
713 break;
714
715 case EPVSocketShutdown:
716 default:
717 OSCL_ASSERT(0);//unexpected
718 break;
719 }
720 }
721 }
722
723
724 //Allocate a node port and add it to the port vector.
AddPort(int32 tag)725 PVMFStatus PVMFClientServerSocketNode::AddPort(int32 tag)
726 {
727 iPVMFPort = new PVMFClientServerSocketPort((int32)tag,
728 this,
729 DEFAULT_DATA_QUEUE_CAPACITY,
730 DEFAULT_DATA_QUEUE_CAPACITY,
731 DEFAULT_READY_TO_RECEIVE_THRESHOLD_PERCENT,
732 //the output queue is empty because
733 //this node pushes data directly to the
734 //connecte port's input.
735 0, 0, 0);
736
737 return PVMFSuccess;
738 }
739
740
AllocatePortMemPool(int32 tag,PVMFSocketNodeMemPool * & aMemPool)741 PVMFStatus PVMFClientServerSocketNode::AllocatePortMemPool(int32 tag, PVMFSocketNodeMemPool* & aMemPool)
742 {
743 aMemPool = NULL;
744 OsclAny *MemPtr = NULL;
745 MemPtr = iAlloc.ALLOCATE(sizeof(PVMFSocketNodeMemPool));
746 if (MemPtr == NULL)
747 {
748 return PVMFErrNoMemory;
749 }
750
751 int32 errcode = 0;
752 OSCL_TRY(errcode, aMemPool = OSCL_PLACEMENT_NEW(MemPtr, PVMFSocketNodeMemPool(SNODE_DEFAULT_NUMBER_MEDIADATA_IN_MEMPOOL);));
753 if (errcode != OsclErrNone)
754 {
755 PVMF_SOCKETNODE_LOGERROR((0, "PVMFClientServerSocketNode::DoRequestPort: PVMFSocketNodeMemPool Construct Failed Ln %d", errcode, __LINE__));
756 iAlloc.deallocate(MemPtr);
757 return PVMFErrNoMemory;
758 }
759
760 aMemPool->iPortTag = tag;
761 return PVMFSuccess;
762 }
763
764
CancelSendOperation()765 PVMFStatus PVMFClientServerSocketNode::CancelSendOperation()
766 {
767 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFClientServerSocketNode::CancelSendOperation()"));
768
769 PVMFStatus status = PVMFSuccess;
770
771 switch (iSockConfig->iState.iSendOperation)
772 {
773 case EPVSocketPortSendOperation_None:
774 break;
775
776 case EPVSocketPortSendOperation_Send:
777 if (iSockConfig->iTCPSocket)
778 {
779 if (!iSockConfig->iState.iSendOperationCanceled)
780 {
781 iSockConfig->iState.iSendOperationCanceled = true;
782 iSockConfig->iTCPSocket->CancelSend();
783 }
784 status = PVMFPending;
785 //wait on send to complete in HandleSocketEvent
786 }
787 break;
788
789 default:
790 OSCL_ASSERT(0);
791 status = PVMFFailure;
792 break;
793 }
794 return status;
795 }
796
797
DoStopNodeActivity()798 PVMFStatus PVMFClientServerSocketNode::DoStopNodeActivity()
799 {
800 if (iNumStopPortActivityPending > 0)
801 return PVMFPending;
802
803 //Stop socket activity on all ports.
804 uint32 nPortsPending = 0;
805 if (iSockConfig)
806 {
807 // discard any saved socket activity events
808 iSockConfig->iSocketRecvActivity.iValid = false;
809
810 //if a request port is going on, be sure to complete the command,
811 //although we will interrupt the current processing.
812 if (iSockConfig->iState.iSequence == EPVSocketPortSequence_RequestPort
813 && iCurrentCmdQueue.size()
814 && iCurrentCmdQueue.front().iCmd == PVMF_GENERIC_NODE_REQUESTPORT)
815 {
816 CommandComplete(iCurrentCmdQueue, iCurrentCmdQueue.front(), PVMFErrCancelled, NULL);
817 }
818
819 //if a cleanup is already underway, just keep waiting for it to complete,
820 //else start a new sequence
821 if (iSockConfig->iState.iSequence == EPVSocketPortSequence_SocketCleanup)
822 {
823 nPortsPending++;
824 }
825 else if (StartSequence(iSockConfig->iState.iSequence = EPVSocketPortSequence_SocketCleanup) == PVMFPending)
826 {
827 nPortsPending++;
828 }
829 }
830
831 if (nPortsPending > 0)
832 iNumStopPortActivityPending = nPortsPending;
833
834 if (iNumStopPortActivityPending > 0)
835 return PVMFPending; //wait on completion in SequenceComplete.
836
837 return PVMFSuccess;
838 }
839
840 //Flush is implemented for this node, but hasn't been tested.
DoFlush(PVMFSocketNodeCommand & aCmd)841 PVMFStatus PVMFClientServerSocketNode::DoFlush(PVMFSocketNodeCommand& aCmd)
842 {
843 OSCL_UNUSED_ARG(aCmd);
844 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFClientServerSocketNode::DoFlush() In"));
845
846 if ((iInterfaceState != EPVMFNodeStarted) && (iInterfaceState != EPVMFNodePaused))
847 {
848 return PVMFErrInvalidState;
849 }
850
851 PVMFStatus status = PVMFSuccess;
852 {
853 iPVMFPort->SuspendInput();
854 if (status != PVMFPending
855 && iPVMFPort->IncomingMsgQueueSize() > 0)
856 {
857 status = PVMFPending;//Wait on this queue to empty.
858 //Completion is detected in SequenceComplete.
859 }
860 }
861 return status;
862 }
863
864 //Pause is a do-nothing for this node.
DoPause(PVMFSocketNodeCommand & aCmd)865 PVMFStatus PVMFClientServerSocketNode::DoPause(PVMFSocketNodeCommand& aCmd)
866 {
867 OSCL_UNUSED_ARG(aCmd);
868 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFClientServerSocketNode::DoPause() In"));
869
870 if (iInterfaceState == EPVMFNodePaused)
871 {
872 return PVMFSuccess;
873 }
874
875 if (iInterfaceState != EPVMFNodeStarted)
876 {
877 return PVMFErrInvalidState;
878 }
879
880 return PVMFSuccess;
881 }
882
883
DoReset(PVMFSocketNodeCommand & aCmd)884 PVMFStatus PVMFClientServerSocketNode::DoReset(PVMFSocketNodeCommand& aCmd)
885 {
886 OSCL_UNUSED_ARG(aCmd);
887 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFClientServerSocketNode::DoReset()"));
888
889 /* This node allows a reset from any state */
890
891 return DoStopNodeActivity();
892 }
893
DoQueryUuid(PVMFSocketNodeCommand & aCmd)894 PVMFStatus PVMFClientServerSocketNode::DoQueryUuid(PVMFSocketNodeCommand& aCmd)
895 {
896 OSCL_UNUSED_ARG(aCmd);
897 /* //This node supports Query UUID from any state
898
899 OSCL_String* mimetype;
900 Oscl_Vector<PVUuid, OsclMemAllocator> *uuidvec;
901 bool exactmatch;
902 aCmd.PVMFSocketNodeCommandBase::Parse(mimetype,uuidvec,exactmatch);
903
904 //Try to match the input mimetype against any of
905 //the custom interfaces for this node
906
907 //Match against custom interface1...
908 if (*mimetype==PVMF_SOCKET_NODE_EXTENSION_INTERFACE_MIMETYPE
909 //also match against base mimetypes for custom interface1,
910 //unless exactmatch is set.
911 || (!exactmatch && *mimetype==PVMF_SOCKET_NODE_MIMETYPE)
912 || (!exactmatch && *mimetype==PVMF_SOCKET_NODE_BASEMIMETYPE))
913 {
914
915 PVUuid uuid(PVMF_SOCKET_NODE_EXTENSION_INTERFACE_UUID);
916 uuidvec->push_back(uuid);
917 }*/
918 return PVMFSuccess;
919 }
920
921
DoQueryInterface(PVMFSocketNodeCommand & aCmd)922 PVMFStatus PVMFClientServerSocketNode::DoQueryInterface(PVMFSocketNodeCommand& aCmd)
923 {
924 OSCL_UNUSED_ARG(aCmd);
925 return PVMFSuccess;
926 }
927
DoRequestPort(PVMFSocketNodeCommand & aCmd)928 PVMFStatus PVMFClientServerSocketNode::DoRequestPort(PVMFSocketNodeCommand& aCmd)
929 {
930 OSCL_UNUSED_ARG(aCmd);
931 //retrieve port tag.
932 int32 tag;
933 OSCL_String* portconfig;
934 aCmd.PVMFSocketNodeCommandBase::Parse(tag, portconfig);
935
936 PVMFStatus status = AddPort(tag);
937 if (status != PVMFSuccess)
938 return status;
939
940 //create the socket config
941 iSockConfig = OSCL_NEW(SocketPortConfig, ());
942 iPVMFPort->iConfig = iSockConfig;
943 iSockConfig->iPVMFPort = iPVMFPort;
944
945 iSockConfig->iContainer = this;
946 iSockConfig->iSockId = iSocketID++;
947 iSockConfig->iTag = tag;
948 iSockConfig->iTCPSocket = iSocketHandle;
949
950 //create the mem pool
951 PVMFSocketNodeMemPool* memPool;
952 status = AllocatePortMemPool(tag, memPool);
953 if (status == PVMFSuccess)
954 iSockConfig->iMemPool = memPool;
955 return status;
956 }
957
958
959 //Release ports is a do-nothing for this node.
DoReleasePort(PVMFSocketNodeCommand & aCmd)960 PVMFStatus PVMFClientServerSocketNode::DoReleasePort(PVMFSocketNodeCommand& aCmd)
961 {
962 OSCL_UNUSED_ARG(aCmd);
963 return PVMFSuccess;
964 }
965
966
DoInit(PVMFSocketNodeCommand & aCmd)967 PVMFStatus PVMFClientServerSocketNode::DoInit(PVMFSocketNodeCommand& aCmd)
968 {
969 OSCL_UNUSED_ARG(aCmd);
970 if (iInterfaceState != EPVMFNodeIdle)
971 {
972 return PVMFErrInvalidState;
973 }
974 return PVMFSuccess;
975 }
976
977
978 //Prepare is a do-nothing for this node.
DoPrepare(PVMFSocketNodeCommand & aCmd)979 PVMFStatus PVMFClientServerSocketNode::DoPrepare(PVMFSocketNodeCommand& aCmd)
980 {
981 OSCL_UNUSED_ARG(aCmd);
982 PVMF_SOCKETNODE_LOGSTACKTRACE((0, "PVMFClientServerSocketNode::DoPrepare() In"));
983
984 if (iInterfaceState != EPVMFNodeInitialized)
985 {
986 return PVMFErrInvalidState;
987 }
988 return PVMFSuccess;
989 }
990
991
DoStart(PVMFSocketNodeCommand & aCmd)992 PVMFStatus PVMFClientServerSocketNode::DoStart(PVMFSocketNodeCommand& aCmd)
993 {
994 OSCL_UNUSED_ARG(aCmd);
995 if (iInterfaceState == EPVMFNodeStarted)
996 {
997 return PVMFSuccess;//already started.
998 }
999
1000 if (iInterfaceState != EPVMFNodePrepared &&
1001 iInterfaceState != EPVMFNodePaused)
1002 {
1003 return PVMFErrInvalidState;
1004 }
1005
1006 TPVMFNodeInterfaceState curState = iInterfaceState;
1007 ChangeExternalState(EPVMFNodeStarted);
1008
1009 PVMFStatus status = PVMFSuccess;
1010 if (iSockConfig)
1011 {
1012 //Start handling incoming messages
1013 if (CanProcessIncomingMsg())
1014 ProcessIncomingMsg();
1015
1016 //Start the receives.
1017 if (CanReceive())
1018 {
1019 status = StartRecvOperation();
1020 if (status == PVMFPending)
1021 {
1022 status = PVMFSuccess;
1023 }
1024 else if (status != PVMFSuccess)
1025 {
1026 ChangeExternalState(curState);
1027 }
1028 }
1029 }
1030 return status;
1031 }
1032
1033
1034
DoStop(PVMFSocketNodeCommand & aCmd)1035 PVMFStatus PVMFClientServerSocketNode::DoStop(PVMFSocketNodeCommand& aCmd)
1036 {
1037 OSCL_UNUSED_ARG(aCmd);
1038 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFClientServerSocketNode::DoStop() In"));
1039
1040 if ((iInterfaceState != EPVMFNodeStarted) && (iInterfaceState != EPVMFNodePaused))
1041 {
1042 return PVMFErrInvalidState;
1043 }
1044 return PVMFSuccess;
1045 }
1046
1047
DoCancelCommand(PVMFSocketNodeCommand & aCmd)1048 PVMFStatus PVMFClientServerSocketNode::DoCancelCommand(PVMFSocketNodeCommand& aCmd)
1049 {
1050 OSCL_UNUSED_ARG(aCmd);
1051 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFClientServerSocketNode::DoCancelCommand() Called"));
1052
1053 // extract the command ID from the parameters.
1054 PVMFCommandId cmdId;
1055 aCmd.PVMFSocketNodeCommandBase::Parse(cmdId);
1056
1057 if (!iCurrentCmdQueue.empty()
1058 && iCurrentCmdQueue.front().iId == cmdId)
1059 {
1060 return DoCancelCurrentCommand(iCurrentCmdQueue, iCurrentCmdQueue.front());
1061 //wait on current command to complete. The cancel command
1062 //will ultimately be completed in the "CommandComplete" for the current command.
1063 }
1064
1065 {
1066 // start at element 1 since this cancel command is element 0
1067 PVMFSocketNodeCommand* cmd = iPendingCmdQueue.FindById(cmdId, 1);
1068 if (cmd)
1069 {
1070 // cancel the queued command. Note this will complete out-of-order.
1071 CommandComplete(iPendingCmdQueue, *cmd, PVMFErrCancelled);
1072 // no further action is required.
1073 return PVMFSuccess;
1074 }
1075 }
1076
1077 //this command fails if the given command is not queued or in progress.
1078 return PVMFErrArgument;
1079 }
1080
DoCancelAllCommands(PVMFSocketNodeCommand & aCmd)1081 PVMFStatus PVMFClientServerSocketNode::DoCancelAllCommands(PVMFSocketNodeCommand& aCmd)
1082 {
1083 OSCL_UNUSED_ARG(aCmd);
1084 PVMFStatus status = DoStopNodeActivity();
1085
1086 if (!iCurrentCmdQueue.empty())
1087 CommandComplete(iCurrentCmdQueue, iCurrentCmdQueue.front(), PVMFErrCancelled);
1088
1089 //Cancel all other pending commands, except for this one which is
1090 //element 0 in the queue
1091 for (uint32 i = 1; i < iPendingCmdQueue.size(); i++)
1092 CommandComplete(iPendingCmdQueue, iPendingCmdQueue[i], PVMFErrCancelled);
1093
1094 //May need to wait on completion of StopNodeActivity.
1095 return status;
1096 }
1097
1098
DoCancelCurrentCommand(PVMFSocketNodeCmdQ & aCmdQ,PVMFSocketNodeCommand & aCmd)1099 PVMFStatus PVMFClientServerSocketNode::DoCancelCurrentCommand(PVMFSocketNodeCmdQ& aCmdQ, PVMFSocketNodeCommand& aCmd)
1100 {
1101 OSCL_UNUSED_ARG(aCmdQ);
1102 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFClientServerSocketNode::DoCancelCurrentCommand()"));
1103 switch (aCmd.iCmd)
1104 {
1105
1106 case PVMF_GENERIC_NODE_REQUESTPORT:
1107 //there may be a connect operation pending-- cancel it.
1108 {
1109 if (iPVMFPort)
1110 {
1111 //SocketPortConfig* iSockConfig=iRequestedPort->iConfig;
1112 if (iSockConfig)
1113 {
1114 // CancelConnectOperation();
1115 return PVMFPending;//wait on the operation to complete
1116 //in HandleSocketEvent or HandleDNSEvent
1117 }
1118 }
1119 //shouldn't get here...
1120 return PVMFFailure;
1121 }
1122 break;
1123
1124 case PVMF_GENERIC_NODE_RESET:
1125 //it's too complicated to cancel a reset, so just wait on completion
1126 return PVMFPending;
1127
1128 case PVMF_GENERIC_NODE_FLUSH:
1129 //to cancel a flush, just discard all remaining port messages
1130 //and keep waiting on completion of current message.
1131 {
1132 iPVMFPort->ClearMsgQueues();
1133 }
1134 return PVMFPending;//keep waiting on flush completion in SequenceComplete.
1135
1136 case PVMF_GENERIC_NODE_CANCELCOMMAND:
1137 case PVMF_GENERIC_NODE_CANCELALLCOMMANDS:
1138 //these have asynchronous completion, but the command handling prevents
1139 //processing a cancel during a cancel, so we shouldn't get here.
1140 OSCL_ASSERT(0);
1141 return PVMFFailure;
1142
1143 default:
1144 //no other node commands have asynchronous completion, so this is unexpected.
1145 OSCL_ASSERT(0);
1146 return PVMFFailure;
1147 }
1148 }
1149
CancelRecvOperation()1150 PVMFStatus PVMFClientServerSocketNode::CancelRecvOperation()
1151 {
1152 PVMF_SOCKETNODE_LOGSTACKTRACE((0, "PVMFClientServerSocketNode::CancelRecvOperation() In"));
1153
1154 PVMFStatus status = PVMFSuccess;
1155
1156 switch (iSockConfig->iState.iRecvOperation)
1157 {
1158 case EPVSocketPortRecvOperation_None:
1159 break;
1160
1161 case EPVSocketPortRecvOperation_Recv:
1162 if (iSockConfig->iTCPSocket)
1163 {
1164 if (!iSockConfig->iState.iRecvOperationCanceled)
1165 {
1166 iSockConfig->iState.iRecvOperationCanceled = true;
1167 iSockConfig->iTCPSocket->CancelRecv();
1168 }
1169 status = PVMFPending;
1170 //wait on recv to complete in HandleSocketEvent
1171 }
1172 break;
1173
1174 case EPVSocketPortRecvOperation_WaitOnConnectedPort:
1175 //just clear the state
1176 iSockConfig->iState.iRecvOperation = EPVSocketPortRecvOperation_None;
1177 //also discard the received data and the associated recv activity
1178 if (iSockConfig->iSocketRecvActivity.iValid)
1179 iSockConfig->iSocketRecvActivity.iValid = false;
1180 if (iSockConfig->iPendingRecvMediaData.GetRep())
1181 iSockConfig->iPendingRecvMediaData.Unbind();
1182 break;
1183
1184 case EPVSocketPortRecvOperation_WaitOnMemory:
1185 if (iSockConfig->iMemPool != NULL)
1186 iSockConfig->iMemPool->CancelFreeChunkAvailableCallback();
1187 //clear the state
1188 iSockConfig->iState.iRecvOperation = EPVSocketPortRecvOperation_None;
1189 break;
1190
1191 default:
1192 OSCL_ASSERT(0);//add code for this case
1193 status = PVMFFailure;
1194 break;
1195 }
1196 return status;
1197 }
1198
1199 //a memory pool callback
freechunkavailable(OsclAny * aContextData)1200 void SocketPortConfig::freechunkavailable(OsclAny* aContextData)
1201 {
1202 OSCL_UNUSED_ARG(aContextData);
1203 //complete the "wait on memory" state
1204 if (iState.iRecvOperation == EPVSocketPortRecvOperation_WaitOnMemory)
1205 {
1206 iContainer->RecvOperationComplete(PVMFSuccess, NULL); //*this,
1207 }
1208 }
1209
1210
CleanupTCP()1211 void PVMFClientServerSocketNode::CleanupTCP()
1212 {
1213 //cleanup media messages
1214 if (iSockConfig->iPendingRecvMediaData.GetRep() != NULL)
1215 {
1216 iSockConfig->iPendingRecvMediaData.Unbind();
1217
1218 }
1219 if (iSockConfig->iPendingSendMediaData.GetRep() != NULL)
1220 {
1221 iSockConfig->iPendingSendMediaData.Unbind();
1222 }
1223 }
1224
1225
CleanupPorts()1226 void PVMFClientServerSocketNode::CleanupPorts()
1227 {
1228 if (iPVMFPort)
1229 {
1230 SocketPortConfig* it = iPVMFPort->iConfig;
1231 if (it)
1232 {
1233 //unlink the PVMFPort so we won't try to send any EOS msg
1234 //during the TCP cleanup.
1235 it->iPVMFPort = NULL;
1236 it->CleanupMemPools();
1237 OSCL_DELETE(it);
1238 iPVMFPort->iConfig = NULL;
1239 }
1240
1241 iPVMFPort->Disconnect();
1242 delete iPVMFPort;
1243 iPVMFPort = NULL;
1244 }
1245 }
1246
1247
PVMFSocketNodeMemPool(uint32 aMemPoolNumBufs)1248 PVMFSocketNodeMemPool::PVMFSocketNodeMemPool(uint32 aMemPoolNumBufs)
1249 : iMediaDataMemPool(NULL)
1250 {
1251 iMediaDataMemPool = OSCL_NEW(OsclMemPoolFixedChunkAllocator, (aMemPoolNumBufs, MEDIA_DATA_CLASS_SIZE));
1252 iInternalAlloc = NULL;
1253 }
1254
1255
DoSetSocketPortMemAllocator(PVLogger * aLogger,OsclSharedPtr<PVMFSharedSocketDataBufferAlloc> aAlloc)1256 void SocketPortConfig::DoSetSocketPortMemAllocator(PVLogger* aLogger, OsclSharedPtr<PVMFSharedSocketDataBufferAlloc> aAlloc)
1257 {
1258 if (aAlloc.GetRep())
1259 {
1260 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, aLogger, PVLOGMSG_INFO, (0, "SocketPortConfig::DoSetSocketPortMemAllocator() Using input mem allocator"));
1261 /*
1262 * Deletion of any previously created allocators is handled as part of
1263 * reset / node delete. So just re-assign the shared ptr here.
1264 */
1265 if (iMemPool->iSocketAllocSharedPtr.GetRep() != NULL)
1266 {
1267 iMemPool->iSocketAllocSharedPtr.Unbind();
1268 }
1269 iMemPool->iSocketAllocSharedPtr = aAlloc;
1270 }
1271 else
1272 {
1273 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, aLogger, PVLOGMSG_INFO, (0, "SocketPortConfig::DoSetSocketPortMemAllocator() no mem allocator. Create one"));
1274
1275 uint aligned_socket_alloc_size = oscl_mem_aligned_size(sizeof(PVMFSMSharedBufferAllocWithReSize));
1276
1277 uint aligned_refcnt_size = oscl_mem_aligned_size(sizeof(OsclRefCounterSA<PVMFSharedSocketDataBufferAllocCleanupSA>));
1278
1279 OsclMemAllocator my_alloc;
1280 uint8 *my_ptr = (uint8*) my_alloc.ALLOCATE(aligned_refcnt_size + aligned_socket_alloc_size);
1281 OsclRefCounter *my_refcnt = OSCL_PLACEMENT_NEW(my_ptr, OsclRefCounterSA<PVMFSharedSocketDataBufferAllocCleanupSA>(my_ptr));
1282 my_ptr += aligned_refcnt_size;
1283
1284 // allow one resize for a maximum mempool size of TCP_BUFFER_SIZE*TCP_BUFFER_IN_MEMPOOL
1285 iMemPool->iInternalAlloc = OSCL_NEW(PVMFSMSharedBufferAllocWithReSize, (
1286 iContainer->iMaxTcpRecvBufferSize * (iContainer->iMaxTcpRecvBufferCount - 1), "TCPsocketBuffer",
1287 1, iContainer->iMaxTcpRecvBufferSize));
1288
1289 PVMFSharedSocketDataBufferAlloc *alloc_ptr = OSCL_PLACEMENT_NEW(my_ptr, PVMFSharedSocketDataBufferAlloc(iMemPool->iInternalAlloc));
1290
1291 OsclSharedPtr<PVMFSharedSocketDataBufferAlloc> shared_alloc(alloc_ptr, my_refcnt);
1292 iMemPool->iSocketAllocSharedPtr = shared_alloc;
1293 }
1294 }
1295
CleanupMemPools()1296 void SocketPortConfig::CleanupMemPools()
1297 {
1298 if (iMemPool->iInternalAlloc != NULL)
1299 {
1300 iMemPool->iInternalAlloc->DecrementKeepAliveCount();
1301 uint32 numOutStandingBuffers =
1302 iMemPool->iInternalAlloc->getNumOutStandingBuffers();
1303 if (numOutStandingBuffers == 0)
1304 {
1305 OSCL_DELETE((iMemPool->iInternalAlloc));
1306 iMemPool->iInternalAlloc = NULL;
1307 }
1308 }
1309 PVMFSocketNodeAllocator alloc;
1310 iMemPool->~PVMFSocketNodeMemPool();
1311 alloc.deallocate((OsclAny*)(iMemPool));
1312 iMemPool = NULL;
1313 }
1314
1315
ReportErrorEvent(PVMFEventType aEventType,OsclAny * aEventData,PVUuid * aEventUUID,int32 * aEventCode)1316 void PVMFClientServerSocketNode::ReportErrorEvent(PVMFEventType aEventType,
1317 OsclAny* aEventData,
1318 PVUuid* aEventUUID,
1319 int32* aEventCode)
1320 {
1321 if (aEventUUID && aEventCode)
1322 {
1323 PVMFBasicErrorInfoMessage* eventmsg =
1324 OSCL_NEW(PVMFBasicErrorInfoMessage, (*aEventCode, *aEventUUID, NULL));
1325 PVMFAsyncEvent asyncevent(PVMFErrorEvent,
1326 aEventType,
1327 NULL,
1328 OSCL_STATIC_CAST(PVInterface*, eventmsg),
1329 aEventData,
1330 NULL,
1331 0);
1332 PVMFNodeInterface::ReportErrorEvent(asyncevent);
1333 eventmsg->removeRef();
1334 }
1335 else
1336 {
1337 PVMFNodeInterface::ReportErrorEvent(aEventType, aEventData);
1338 }
1339 }
1340
ReportInfoEvent(PVMFEventType aEventType,OsclAny * aEventData,PVUuid * aEventUUID,int32 * aEventCode)1341 void PVMFClientServerSocketNode::ReportInfoEvent(PVMFEventType aEventType,
1342 OsclAny* aEventData,
1343 PVUuid* aEventUUID,
1344 int32* aEventCode)
1345 {
1346 if (aEventUUID && aEventCode)
1347 {
1348 PVMFBasicErrorInfoMessage* eventmsg =
1349 OSCL_NEW(PVMFBasicErrorInfoMessage, (*aEventCode, *aEventUUID, NULL));
1350 PVMFAsyncEvent asyncevent(PVMFInfoEvent,
1351 aEventType,
1352 NULL,
1353 OSCL_STATIC_CAST(PVInterface*, eventmsg),
1354 aEventData,
1355 NULL,
1356 0);
1357 PVMFNodeInterface::ReportInfoEvent(asyncevent);
1358 eventmsg->removeRef();
1359 }
1360 else
1361 {
1362 PVMFNodeInterface::ReportInfoEvent(aEventType, aEventData);
1363 }
1364 }
1365
setSocketPortMemAllocator(PVMFPortInterface * aInPort,OsclSharedPtr<PVMFSharedSocketDataBufferAlloc> aAlloc)1366 OSCL_EXPORT_REF bool PVMFClientServerSocketNode::setSocketPortMemAllocator(PVMFPortInterface* aInPort,
1367 OsclSharedPtr<PVMFSharedSocketDataBufferAlloc> aAlloc)
1368 {
1369
1370 PVMFClientServerSocketPort* aPort = OSCL_STATIC_CAST(PVMFClientServerSocketPort*, aInPort);
1371 SocketPortConfig* tmpSockConfig = (aPort) ? aPort->iConfig : NULL;
1372 if (NULL != tmpSockConfig)
1373 {
1374 tmpSockConfig->DoSetSocketPortMemAllocator(iLogger, aAlloc);
1375 return true;
1376 }
1377 return false;
1378 }
1379
1380
CanProcessIncomingMsg()1381 bool PVMFClientServerSocketNode::CanProcessIncomingMsg()
1382 {
1383 return
1384 //node is started
1385 iInterfaceState == EPVMFNodeStarted
1386 //port has input messages
1387 && iSockConfig->iPVMFPort && iSockConfig->iPVMFPort->IncomingMsgQueueSize() > 0
1388 //port is not busy with any sequence
1389 && iSockConfig->iState.iSequence == EPVSocketPortSequence_None;
1390 }
1391
1392
ProcessIncomingMsg()1393 void PVMFClientServerSocketNode::ProcessIncomingMsg()
1394 {
1395 PVMF_SOCKETNODE_LOGSTACKTRACE((0, "PVMFClientServerSocketNode::ProcessIncomingMsg: aPort=0x%x", iSockConfig->iPVMFPort));
1396
1397 //Dequeue the incoming message
1398 PVMFSharedMediaMsgPtr msg;
1399 PVMFStatus status = iSockConfig->iPVMFPort->DequeueIncomingMsg(msg);
1400 if (status != PVMFSuccess)
1401 {
1402 PVMF_SOCKETNODE_LOGERROR((0, "PVMFClientServerSocketNode::ProcessIncomingDataMsg: Error - DequeueIncomingMsg failed"));
1403 ReportErrorEvent(PVMFErrPortProcessing);
1404 return ;
1405 }
1406
1407 OSCL_ASSERT(iSockConfig->iState.iSequence == EPVSocketPortSequence_None);
1408
1409 //Handle 3 types of messages
1410 if (msg->getFormatID() == PVMF_MEDIA_CMD_SOCKET_DISCONNECT_FORMAT_ID)
1411 {
1412 //Disconnect message
1413 StartSequence(EPVSocketPortSequence_InputDisconnectMsg);
1414 }
1415 else if (msg->getFormatID() == PVMF_MEDIA_MSG_DATA_FORMAT_ID)
1416 {
1417 //Start the sequence
1418 StartSequence(EPVSocketPortSequence_InputDataMsg, (OsclAny*)&msg);
1419 }
1420 else
1421 {
1422 //unexpected message type
1423 ReportErrorEvent(PVMFErrPortProcessing);
1424 }
1425 }
1426
1427
StartSendOperation(PVMFSharedMediaMsgPtr & aMsg)1428 PVMFStatus PVMFClientServerSocketNode::StartSendOperation(PVMFSharedMediaMsgPtr& aMsg)
1429 {
1430 PVMF_SOCKETNODE_LOGSTACKTRACE((0, "PVMFClientServerSocketNode::StartSendOperation() In"));
1431
1432 //caller should have verified we can send now.
1433 OSCL_ASSERT(iSockConfig->iState.iSendOperation == EPVSocketPortSendOperation_None);
1434
1435 //caller should provide a media data message as input
1436 OSCL_ASSERT(aMsg->getFormatID() == PVMF_MEDIA_MSG_DATA_FORMAT_ID);
1437
1438 //there should be either a UDP or TCP socket on this port
1439 if (!iSockConfig->iTCPSocket)
1440 {
1441 return PVMFFailure;
1442 }
1443
1444 // Retrieve memory fragment to write to
1445 if (iSockConfig->iPendingSendMediaData.GetRep())
1446 iSockConfig->iPendingSendMediaData.Unbind();
1447
1448 convertToPVMFMediaData(iSockConfig->iPendingSendMediaData, aMsg);
1449 OsclRefCounterMemFrag refCtrMemFragOut;
1450 iSockConfig->iPendingSendMediaData->getMediaFragment(0, refCtrMemFragOut);
1451
1452 PVMFStatus status = PVMFFailure;
1453
1454 if (iSockConfig->iTCPSocket)
1455 {
1456 iSockConfig->iState.iSendOperation = EPVSocketPortSendOperation_Send;
1457
1458 TPVSocketEvent retVal = iSockConfig->iTCPSocket->Send((uint8*)refCtrMemFragOut.getMemFragPtr(),
1459 refCtrMemFragOut.getMemFragSize(),
1460 TIMEOUT_SEND);
1461
1462 if (retVal == EPVSocketPending)
1463 status = PVMFPending;//wait on HandleSocketEvent callback
1464 else
1465 status = PVMFFailure;
1466
1467 if (PVMFPending != status)
1468 {
1469 PVMF_SOCKETNODE_LOGERROR((0, "PVMFClientServerSocketNode::StartSendOperation: TCP - Error. status=%d", status));
1470 }
1471 }
1472
1473 //Handle synchronous completion or failures
1474 if (status != PVMFPending)
1475 status = SendOperationComplete(status, NULL);
1476
1477 return status;
1478 }
1479
1480
SendOperationComplete(PVMFStatus aStatus,PVMFSocketActivity * aSocketActivity)1481 PVMFStatus PVMFClientServerSocketNode::SendOperationComplete(PVMFStatus aStatus, PVMFSocketActivity* aSocketActivity)
1482 {
1483 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFClientServerSocketNode::SendOperationComplete()"));
1484
1485 OSCL_ASSERT(aStatus != PVMFPending);
1486
1487 PVMFStatus status = aStatus;
1488
1489 //Update the send state
1490 TPVSocketPortSendOperation curOp = iSockConfig->iState.iSendOperation;
1491 iSockConfig->iState.iSendOperation = EPVSocketPortSendOperation_None;
1492 iSockConfig->iState.iSendOperationStatus = aStatus;
1493 iSockConfig->iState.iSendOperationCanceled = false;
1494
1495 //Release the media buffer after each send operation, regardless of success/fail.
1496 if (iSockConfig->iPendingSendMediaData.GetRep() != NULL)
1497 iSockConfig->iPendingSendMediaData.Unbind();
1498
1499 if (aSocketActivity)
1500 {
1501 //Datapath logging
1502 switch (aSocketActivity->iEvent)
1503 {
1504 case EPVSocketSuccess:
1505 //PVMF_SOCKETNODE_LOGDATATRAFFIC_I((0,"PVMFClientServerSocketNode::SendOperationComplete - Success - SockId=%d, Mime=%s", iSockConfig->iSockId, iSockConfig->iMime.get_str()));
1506 break;
1507 case EPVSocketTimeout:
1508 //PVMF_SOCKETNODE_LOGDATATRAFFIC_E((0,"PVMFClientServerSocketNode::SendOperationComplete - TimeOut - SockId=%d, Mime=%s", iSockConfig->iSockId, iSockConfig->iMime.get_str()));
1509 break;
1510 case EPVSocketFailure:
1511 //PVMF_SOCKETNODE_LOGDATATRAFFIC_E((0,"PVMFClientServerSocketNode::SendOperationComplete - Failed - SockId=%d, Mime=%s", iSockConfig->iSockId, iSockConfig->iMime.get_str()));
1512 break;
1513 case EPVSocketCancel:
1514 //PVMF_SOCKETNODE_LOGDATATRAFFIC_E((0,"PVMFClientServerSocketNode::SendOperationComplete - Cancelled - SockId=%d, Mime=%s", iSockConfig->iSockId, iSockConfig->iMime.get_str()));
1515 break;
1516 default:
1517 OSCL_ASSERT(0);
1518 break;
1519 }
1520 }
1521
1522 //report TCP errors.
1523 if (aStatus != PVMFSuccess
1524 && curOp == EPVSocketPortSendOperation_Send)
1525 {
1526 ReportSocketNodeError(PVMFErrResource, PVMFSocketNodeErrorTCPSocketSendError);
1527 }
1528
1529 //This completes an input data message sequence
1530 if (iSockConfig->iState.iSequence == EPVSocketPortSequence_InputDataMsg)
1531 SequenceComplete(aStatus);
1532 return status;
1533 }
1534
1535
CanReceive()1536 bool PVMFClientServerSocketNode::CanReceive()
1537 {
1538 return
1539 //node is started
1540 iInterfaceState == EPVMFNodeStarted
1541 //port is connected
1542 && iSockConfig->iPVMFPort && iSockConfig->iPVMFPort->IsConnected()
1543 //socket exists (gets created during request port or connect sequence)
1544 && (iSockConfig->iTCPSocket)
1545 //port is not busy with any sequence other than sending data
1546 && (iSockConfig->iState.iSequence == EPVSocketPortSequence_None
1547 || iSockConfig->iState.iSequence == EPVSocketPortSequence_InputDataMsg)
1548 //port is not busy with any receive operation.
1549 && iSockConfig->iState.iRecvOperation == EPVSocketPortRecvOperation_None
1550 //there's no node stop going on.
1551 && iNumStopPortActivityPending < 0;
1552 }
1553
1554 //Enter the "wait on memory" state
StartRecvWaitOnMemory(int32 aSize)1555 void PVMFClientServerSocketNode::StartRecvWaitOnMemory(int32 aSize)
1556 {
1557 PVMF_SOCKETNODE_LOGSTACKTRACE((0, "PVMFClientServerSocketNode::StartRecvWaitOnMemory() In"));
1558
1559 iSockConfig->iState.iRecvOperation = EPVSocketPortRecvOperation_WaitOnMemory;
1560
1561 if (aSize)
1562 {//wait on data buffer
1563 iSockConfig->iMemPool->notifyfreechunkavailable(*iSockConfig, aSize, NULL);
1564 }
1565 else
1566 {//wait on media data wrapper
1567 iSockConfig->iMemPool->iMediaDataMemPool->notifyfreechunkavailable(*iSockConfig, NULL);
1568 }
1569 }
1570
1571 //Enter the "wait on connected port" state
StartRecvWaitOnConnectedPort(PVMFSocketActivity & aSocketActivity)1572 void PVMFClientServerSocketNode::StartRecvWaitOnConnectedPort(PVMFSocketActivity& aSocketActivity)
1573 {
1574 PVMF_SOCKETNODE_LOGSTACKTRACE((0, "PVMFClientServerSocketNode::StartRecvWaitOnConnectedPort() In"));
1575
1576 //outgoing queue is busy-- must queue this event for later processing
1577 switch (aSocketActivity.iFxn)
1578 {
1579 case EPVSocketRecv:
1580 case EPVSocketRecvFrom:
1581 iSockConfig->iSocketRecvActivity.Set(aSocketActivity.iStatus
1582 , aSocketActivity.iId
1583 , aSocketActivity.iFxn
1584 , aSocketActivity.iEvent
1585 , aSocketActivity.iError);
1586 break;
1587 default:
1588 OSCL_ASSERT(false);//invalid input arg.
1589 break;
1590 }
1591
1592 //current state shoudl be idle
1593 OSCL_ASSERT(iSockConfig->iState.iRecvOperation == EPVSocketPortRecvOperation_None);
1594
1595 iSockConfig->iState.iRecvOperation = EPVSocketPortRecvOperation_WaitOnConnectedPort;
1596 }
1597
1598
StartRecvOperation()1599 PVMFStatus PVMFClientServerSocketNode::StartRecvOperation()
1600 {
1601 PVMF_SOCKETNODE_LOGSTACKTRACE((0, "PVMFClientServerSocketNode::StartRecvOperation() In"));
1602
1603 //caller should have verified we can receive data right now.
1604 OSCL_ASSERT(iSockConfig->iState.iRecvOperation == EPVSocketPortRecvOperation_None);
1605
1606 //there should be either a UDP or TCP socket on this port and a memory pool.
1607 if (!iSockConfig->iTCPSocket)
1608 {
1609 return PVMFFailure;
1610 }
1611 if (!iSockConfig->iMemPool)
1612 {
1613 return PVMFFailure;
1614 }
1615
1616 PVMFStatus status = PVMFFailure;
1617
1618 if (iSockConfig->iTCPSocket)
1619 {
1620 iSockConfig->iState.iRecvOperation = EPVSocketPortRecvOperation_Recv;
1621
1622 //Allocate memory
1623 int32 err;
1624 OsclSharedPtr<PVMFMediaDataImpl> mediaDataImpl;
1625 OSCL_TRY(err,
1626 mediaDataImpl = iSockConfig->iMemPool->getMediaDataImpl(iMaxTcpRecvBufferSize););
1627 if (err != OsclErrNone)
1628 {
1629 StartRecvWaitOnMemory(iMaxTcpRecvBufferSize);
1630 status = PVMFPending;
1631 //wait on memory pool callback "notifyfreechunkavailable"
1632 }
1633
1634 else
1635 {
1636 OSCL_TRY(err, iSockConfig->iPendingRecvMediaData = PVMFMediaData::createMediaData(
1637 mediaDataImpl, iSockConfig->iMemPool->iMediaDataMemPool););
1638 if (err != OsclErrNone)
1639 {
1640 StartRecvWaitOnMemory();
1641 status = PVMFPending;
1642 //wait on memory pool callback "notifyfreechunkavailable"
1643 }
1644
1645 else
1646 {
1647 // Retrieve memory fragment to write to
1648 OsclRefCounterMemFrag refCtrMemFragOut;
1649 iSockConfig->iPendingRecvMediaData->getMediaFragment(0, refCtrMemFragOut);
1650
1651 //Issue the Oscl socket request
1652 TPVSocketEvent retVal = iSockConfig->iTCPSocket->Recv((uint8*)refCtrMemFragOut.getMemFragPtr()
1653 , refCtrMemFragOut.getCapacity()
1654 , TIMEOUT_RECV);
1655 if (EPVSocketPending != retVal)
1656 {
1657 status = PVMFFailure;
1658 }
1659 else
1660 {
1661 status = PVMFPending;
1662 //wait on HandleSocketEvent callback.
1663 }
1664 }
1665 }
1666 }
1667 else //for (iTCPSocket==NULL)
1668 {
1669 PVMF_SOCKETNODE_LOGERROR((0, "PVMFClientServerSocketNode::StartRecvOperation() Unexpected error, no socket"));
1670 }
1671
1672 //Handle synchronous completion or failure.
1673 if (status != PVMFPending
1674 && status != PVMFFailure)
1675 {
1676 PVMF_SOCKETNODE_LOGERROR((0, "PVMFClientServerSocketNode::StartRecvOperation: Error. status=%d", status));
1677 }
1678
1679 if (status != PVMFPending)
1680 status = RecvOperationComplete(status, NULL);
1681
1682 return status;
1683 }
1684
RecvOperationComplete(PVMFStatus aStatus,PVMFSocketActivity * aSocketActivity)1685 PVMFStatus PVMFClientServerSocketNode::RecvOperationComplete(PVMFStatus aStatus, PVMFSocketActivity* aSocketActivity)
1686 {
1687 PVMF_SOCKETNODE_LOGSTACKTRACE((0, "PVMFClientServerSocketNode::RecvOperationComplete() In"));
1688
1689 //status should never be pending here
1690 OSCL_ASSERT(aStatus != PVMFPending);
1691
1692 PVMFStatus status = aStatus;
1693 bool recvOperationCanceled = iSockConfig->iState.iRecvOperationCanceled;
1694
1695 //check the condition of reset here
1696 if (iSockConfig->iState.iSequence == EPVSocketPortSequence_SocketCleanup
1697 || recvOperationCanceled)
1698 {
1699 return PVMFSuccess;
1700 }
1701
1702 //Update the state
1703 TPVSocketPortRecvOperation curOp = iSockConfig->iState.iRecvOperation;
1704 iSockConfig->iState.iRecvOperation = EPVSocketPortRecvOperation_None;
1705 iSockConfig->iState.iRecvOperationStatus = aStatus;
1706 iSockConfig->iState.iRecvOperationCanceled = false;
1707
1708 switch (curOp)
1709 {
1710 case EPVSocketPortRecvOperation_WaitOnMemory:
1711 //a memory wait is complete.
1712 //PVMF_SOCKETNODE_LOGDATATRAFFIC_I((0, "PVMFClientServerSocketNode::RecvOperationComplete WaitOnMemory - SockId=%d, Mime=%s ", iSockConfig->iSockId, iSockConfig->iMime.get_str()));
1713 break;
1714
1715 case EPVSocketPortRecvOperation_WaitOnConnectedPort:
1716 //a port wait is complete
1717 if (iSockConfig->iSocketRecvActivity.iValid)
1718 {
1719 iSockConfig->iSocketRecvActivity.iValid = false;
1720
1721 switch (iSockConfig->iSocketRecvActivity.iFxn)
1722 {
1723 case EPVSocketRecv:
1724 HandleRecvComplete(iSockConfig->iSocketRecvActivity.iStatus
1725 , &iSockConfig->iSocketRecvActivity, recvOperationCanceled);
1726 break;
1727 default:
1728 OSCL_ASSERT(0);//invalid arg
1729 break;
1730 }
1731 }
1732 break;
1733
1734 case EPVSocketPortRecvOperation_Recv:
1735 HandleRecvComplete(aStatus, aSocketActivity, recvOperationCanceled);
1736 break;
1737
1738 default:
1739 OSCL_ASSERT(0);//add code for this case
1740 break;
1741 }
1742
1743 if (CanReceive())
1744 status = StartRecvOperation();
1745
1746 return status;
1747 }
1748
1749
HandleRecvComplete(PVMFStatus aStatus,PVMFSocketActivity * aSocketActivity,bool aRecvOperationCanceled)1750 void PVMFClientServerSocketNode::HandleRecvComplete(PVMFStatus aStatus, PVMFSocketActivity* aSocketActivity, bool aRecvOperationCanceled)
1751 {
1752 OSCL_UNUSED_ARG(aRecvOperationCanceled);
1753 PVMF_SOCKETNODE_LOGSTACKTRACE((0, "PVMFClientServerSocketNode::HandleRecvComplete() In"));
1754
1755 //operation should be complete when this is called.
1756 OSCL_ASSERT(aStatus != PVMFPending);
1757
1758 //If there's no socket activity input, then this must be a failure in initiating
1759 //a Recv operation.
1760 if (!aSocketActivity || !iSockConfig->iPVMFPort
1761 || !iSockConfig->iPVMFPort->IsConnected())
1762 {
1763 OSCL_ASSERT(aStatus != PVMFSuccess);
1764 ReportSocketNodeError(PVMFErrResource, PVMFSocketNodeErrorSocketFailure);
1765 //release media data
1766 if (iSockConfig->iPendingRecvMediaData.GetRep())
1767 iSockConfig->iPendingRecvMediaData.Unbind();
1768 return;
1769 }
1770
1771 if (aSocketActivity->iEvent == EPVSocketSuccess)
1772 {
1773 if (iSockConfig->iPVMFPort->IsOutgoingQueueBusy())
1774 {
1775 //wait on port so we can send recv data.
1776 StartRecvWaitOnConnectedPort(*aSocketActivity);
1777 return;
1778 }
1779 }
1780
1781 //If we get here then it's time to process the recv result.
1782
1783 //Release media data on failure
1784 if (aStatus != PVMFSuccess)
1785 {
1786 if (iSockConfig->iPendingRecvMediaData.GetRep())
1787 iSockConfig->iPendingRecvMediaData.Unbind();
1788 }
1789
1790 switch (aSocketActivity->iEvent)
1791 {
1792 case EPVSocketSuccess:
1793 {
1794 //Get data length and set media buffer size
1795 int32 len;
1796 iSockConfig->iTCPSocket->GetRecvData(&len);
1797 if (len <= 0)
1798 {
1799 PVMF_SOCKETNODE_LOGERROR((0, "PVMFClientServerSocketNode::HandleRecvComplete - Sucessful Recv With Zero Length"));
1800 OSCL_ASSERT(false);
1801 }
1802 iSockConfig->iPendingRecvMediaData->setMediaFragFilledLen(0, len);
1803
1804 // Resize the buffer
1805 if (iSockConfig->iMemPool)
1806 {
1807 OsclSharedPtr<PVMFMediaDataImpl> mediaMsgImpl;
1808 iSockConfig->iPendingRecvMediaData->getMediaDataImpl(mediaMsgImpl);
1809 iSockConfig->iMemPool->resizeSocketDataBuffer(mediaMsgImpl);
1810 }
1811 else
1812 {
1813 PVMF_SOCKETNODE_LOGERROR((0, "PVMFClientServerSocketNode::HandleRecvComplete() ERROR:mempool not found"));
1814 OSCL_ASSERT(0);
1815 return ;
1816 }
1817
1818 //queue to next port
1819 PVMFSharedMediaMsgPtr aMediaMsgPtr;
1820 convertToPVMFMediaMsg(aMediaMsgPtr, iSockConfig->iPendingRecvMediaData);
1821
1822 PVMFStatus status = iSockConfig->iPVMFPort->QueueOutgoingMsg(aMediaMsgPtr);
1823 if (status != PVMFSuccess)
1824 {
1825 ReportErrorEvent(PVMFErrPortProcessing);
1826 return ;
1827 }
1828 }
1829 break;
1830
1831 case EPVSocketTimeout:
1832 {
1833 ReportSocketNodeError(PVMFErrTimeout, PVMFSocketNodeErrorSocketTimeOut);
1834 }
1835 break;
1836
1837 case EPVSocketCancel:
1838 break;
1839
1840 case EPVSocketFailure:
1841 {
1842 //After a receive failure, we may need to do a TCP shutdown.
1843 //Check what else is currently happening on the port.
1844 switch (iSockConfig->iState.iSequence)
1845 {
1846 case EPVSocketPortSequence_RequestPort:
1847 case EPVSocketPortSequence_InputDisconnectMsg:
1848 case EPVSocketPortSequence_SocketCleanup:
1849 break;
1850
1851 case EPVSocketPortSequence_None:
1852 case EPVSocketPortSequence_InputDataMsg:
1853 //for these cases, start a shutdown sequence
1854 //start the sequence
1855 iSockConfig->iState.iSequence = EPVSocketPortSequence_SocketCleanup;
1856 StartSequence(EPVSocketPortSequence_SocketCleanup);
1857 break;
1858
1859 default:
1860 //need code to handle this case.
1861 OSCL_ASSERT(0);
1862 break;
1863 }
1864 }
1865 break;
1866
1867 default:
1868 OSCL_ASSERT(0);
1869 break;
1870 }
1871 }
1872
1873
1874
SetMaxTCPRecvBufferSize(uint32 aBufferSize)1875 OSCL_EXPORT_REF PVMFStatus PVMFClientServerSocketNode::SetMaxTCPRecvBufferSize(uint32 aBufferSize)
1876 {
1877 if ((aBufferSize > 0) && (aBufferSize < SNODE_DEFAULT_MAX_TCP_RECV_BUFFER_SIZE))
1878 {
1879 iMaxTcpRecvBufferSize = aBufferSize;
1880 return PVMFSuccess;
1881 }
1882 return PVMFErrArgument;
1883 }
1884
GetMaxTCPRecvBufferSize(uint32 & aSize)1885 OSCL_EXPORT_REF PVMFStatus PVMFClientServerSocketNode::GetMaxTCPRecvBufferSize(uint32& aSize)
1886 {
1887 aSize = iMaxTcpRecvBufferSize;
1888 return PVMFSuccess;
1889 }
1890
SetMaxTCPRecvBufferCount(uint32 aBufferSize)1891 OSCL_EXPORT_REF PVMFStatus PVMFClientServerSocketNode::SetMaxTCPRecvBufferCount(uint32 aBufferSize)
1892 {
1893 iMaxTcpRecvBufferCount = aBufferSize;
1894 return PVMFSuccess;
1895 }
1896
GetMaxTCPRecvBufferCount(uint32 & aSize)1897 OSCL_EXPORT_REF PVMFStatus PVMFClientServerSocketNode::GetMaxTCPRecvBufferCount(uint32& aSize)
1898 {
1899 aSize = iMaxTcpRecvBufferCount;
1900 return PVMFSuccess;
1901 }
1902
StartSequence(TPVSocketPortSequence aSequence,OsclAny * aParam)1903 PVMFStatus PVMFClientServerSocketNode::StartSequence(TPVSocketPortSequence aSequence, OsclAny* aParam)
1904 {
1905 PVMFStatus status = PVMFFailure;
1906 //Set the sequence.
1907 iSockConfig->iState.iSequence = aSequence;
1908
1909 switch (aSequence)
1910 {
1911 case EPVSocketPortSequence_InputDataMsg:
1912 {
1913 OSCL_ASSERT(aParam);
1914 return StartSendOperation(*((PVMFSharedMediaMsgPtr*)aParam));
1915 }
1916
1917 case EPVSocketPortSequence_InputDisconnectMsg:
1918 {
1919 status = CloseSocketConnection();
1920 }
1921 break;
1922
1923 case EPVSocketPortSequence_SocketCleanup:
1924 if (iSockConfig->iTCPSocket)
1925 {
1926 //CancelRecvOperation();
1927 //CancelSendOperation();
1928 status = CloseSocketConnection();
1929 }
1930 break;
1931
1932 default:
1933 {
1934 OSCL_ASSERT(0);
1935 return PVMFFailure;
1936 }
1937 }
1938
1939 if (status != PVMFPending)
1940 {
1941 //nothing needed.
1942 SequenceComplete(PVMFSuccess);
1943 return PVMFSuccess;
1944 }
1945 return status;
1946 }
1947
1948
1949
CloseSocketConnection()1950 PVMFStatus PVMFClientServerSocketNode::CloseSocketConnection()
1951 {
1952 PVMFStatus status;
1953 iSockConfig->iState.iSequence = EPVSocketPortSequence_SocketCleanup;
1954 if (!iSockConfig->iTCPSocket)
1955 {
1956 status = PVMFFailure;//unexpected
1957 return status;
1958 }
1959 //Initiate a socket shutdown.
1960 TPVSocketEvent ret = iSockConfig->iTCPSocket->Shutdown(EPVSocketBothShutdown, TIMEOUT_SHUTDOWN);
1961 if (ret == EPVSocketPending)
1962 {
1963 status = PVMFPending;
1964 //wait on the socket shutdown to complete in HandleSocketEvent callback
1965 }
1966 else
1967 {
1968 status = PVMFFailure;
1969 }
1970 return status;
1971 }
1972
1973
SequenceComplete(PVMFStatus aStatus)1974 void PVMFClientServerSocketNode::SequenceComplete(PVMFStatus aStatus)
1975 {
1976 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFClientServerSocketNode::SequenceComplete() Sequence %d Status %d ", iSockConfig->iState.iSequence, aStatus));
1977
1978 TPVSocketPortSequence curSequence = iSockConfig->iState.iSequence;
1979 iSockConfig->iState.iSequence = EPVSocketPortSequence_None;
1980 iSockConfig->iState.iSequenceStatus = aStatus;
1981
1982 switch (curSequence)
1983 {
1984 case EPVSocketPortSequence_RequestPort:
1985 //may need to complete the node command
1986 if (iCurrentCmdQueue.size()
1987 && iCurrentCmdQueue.front().iCmd == PVMF_GENERIC_NODE_REQUESTPORT)
1988 {
1989 CommandComplete(iCurrentCmdQueue, iCurrentCmdQueue.front(), aStatus, iPVMFPort);
1990 }
1991 break;
1992
1993 case EPVSocketPortSequence_InputDisconnectMsg:
1994 case EPVSocketPortSequence_InputDataMsg:
1995 //If we've just completed an input port message, this may complete a node Flush command
1996 if (!iCurrentCmdQueue.empty()
1997 && iCurrentCmdQueue.front().iCmd == PVMF_GENERIC_NODE_FLUSH)
1998 {
1999 //Flush is done when all input ports are empty.
2000 if (iPVMFPort->IncomingMsgQueueSize() > 0)
2001 return;//keep waiting
2002 CommandComplete(iCurrentCmdQueue, iCurrentCmdQueue.front(), PVMFSuccess);
2003 }
2004 break;
2005
2006
2007 case EPVSocketPortSequence_SocketCleanup:
2008 {
2009 iPVMFPort->SuspendInput();
2010 iPVMFPort->ClearMsgQueues();
2011
2012 CleanupPorts();
2013 //This port is done-- decrement the counter
2014 iNumStopPortActivityPending--;
2015
2016 //When counter reaches zero, all ports are done and the sequence is complete.
2017 if (iNumStopPortActivityPending == 0)
2018 {
2019 //Reset the counter to the "idle" value.
2020 iNumStopPortActivityPending = (-1);
2021
2022 //There may be a Reset or CancelAll command waiting on
2023 //this to complete.
2024 if (!iCurrentCmdQueue.empty()
2025 && iCurrentCmdQueue.front().iCmd == PVMF_GENERIC_NODE_RESET)
2026 {
2027 CommandComplete(iCurrentCmdQueue, iCurrentCmdQueue.front(), PVMFSuccess);
2028 }
2029 else if (!iCancelCmdQueue.empty()
2030 && iCancelCmdQueue.front().iCmd == PVMF_GENERIC_NODE_CANCELALLCOMMANDS)
2031 {
2032 CommandComplete(iCancelCmdQueue, iCancelCmdQueue.front(), PVMFSuccess);
2033 }
2034 return;
2035 }
2036 }
2037 break;
2038
2039 default:
2040 break;
2041 }
2042
2043 if (curSequence != EPVSocketPortSequence_InputDataMsg
2044 && CanReceive())
2045 {
2046 StartRecvOperation();
2047 }
2048
2049 if (CanProcessIncomingMsg())
2050 ProcessIncomingMsg();
2051 }
2052