static int deliverSWP(SwpState state, Msg *frame) { SwpHdr hdr; char *hbuf; hbuf = msgStripHdr(frame, HLEN); load_swp_hdr(&hdr, hbuf); if (hdr->Flags & FLAG_ACK_VALID) { if (swpInWindow(hdr.AckNum, state->LAR + 1, state->LFS)) { do { struct sendQ_slot *slot; slot = &state->sendQ[++state->LAR % SWS]; evCancel(slot->timeout); msgDestroy(&slot->msg); semSignal(&state->sendWindowNotFull); } while (state->LAR != hdr.Acknum); } } if (hdr.Flags & FLAG_HAS_DATA) { struct recvQ_slot, *slot; //received data packet---do RECEIVER side slot = &state->recvQ[hdr.SeqNum % RWS]; if (!swpInWindow(hdr.SeqNum, state->NFE, state->NFE + RWS - 1)) { //drop the message return SUCCESS; } msgSaveCopy(&slot->msg, frame); slot->received = TRUE; if (hdr.SeqNum == state->NFE) { Msg m; while (slot->received) { deliver(HLP, &slot->msg); msgDestroy(&slot->msg); slot->received = FALSE; slot = &state->recvQ[++state->NFE % RWS]; } //send ACK prepare_ack(&m, state->NFE - 1); send(LINK, &m); msgDestroy(&m); } } return SUCCESS; }
OsStatus MpStreamPlayer::destroy() { OsStatus status = OS_SUCCESS ; // Assume since this is non-blocking. Only // a failure to send will cause error // Make sure we disable looping before sending stop, otherwise it is // possible for the stop request to be lost (because of auto-replay) miLoopCount = 0 ; if ((mpMsgQ != NULL) && (mHandle != NULL)) { int iState = getState() ; if ( mbRealized && (iState != PlayerStopped) && (iState != PlayerAborted) && (iState != PlayerDestroyed) ) { MpStreamMsg msgStop(MpStreamMsg::STREAM_STOP, mTarget, mHandle); status = mpMsgQ->send(msgStop) ; } if ( mbRealized && (iState != PlayerDestroyed) && (status == OS_SUCCESS)) { MpStreamMsg msgDestroy(MpStreamMsg::STREAM_DESTROY, mTarget, mHandle); status = mpMsgQ->send(msgDestroy) ; } } return status ; }
int tryPush( XObj self, XObj sessn, int times, int length ) { xkern_return_t xkr; int i; Msg_s savedMsg, request; int c = 0; PState *ps = (PState *)self->state; #if MACH_KERNEL tvalspec_t time_val_before, time_val_after; #endif /* MACH_KERNEL */ xkr = msgConstructContig(&savedMsg, self->path, (u_int)length, TEST_STACK_SIZE); if (xkr == XK_FAILURE) { sprintf(errBuf, "Could not construct a msg of length %d\n", length + TEST_STACK_SIZE); Kabort(errBuf); } msgConstructContig(&request, self->path, 0, 0); semInit(&ps->sema, 0); ps->flushing = FALSE; ps->partialcount = times - 1; #if MACH_KERNEL rtc_gettime(&ps->starttime); rtc_gettime(&ps->partialtime); #else xGetTime(&ps->starttime); #endif /* MACH_KERNEL */ for (i = 0; i < ps->groupsize; i++) { msgAssign(&request, &savedMsg); xkr = xPush(sessn, &request); if( xkr == XK_FAILURE ) { printf( "Dgram Push error %d\n" , xkr ); goto abort; } } evSchedule(ps->evdgram, dgram_abort, self, 30000000); semWait(&ps->sema); evCancel(ps->evdgram); abort: msgDestroy(&savedMsg); msgDestroy(&request); return (times - ps->partialcount); }
xkern_return_t serverDemux( XObj self, XObj lls, Msg dg ) { Msg_s reply; msgConstructCopy(&reply, dg); (void)xPush(lls, &reply); msgDestroy(&reply); return XK_SUCCESS; }
xkern_return_t clientDemux( XObj self, XObj lls, Msg dg ) { PState *ps = (PState *)self->state; Msg_s reply; #if MACH_KERNEL tvalspec_t singletime; #else XTime endtime; #endif /* MACH_KERNEL */ if (ps->flushing == TRUE) return XK_SUCCESS; if (--ps->partialcount == 0) { semSignal(&ps->sema); ps->flushing = TRUE; #if MACH_KERNEL #if 0 rtc_gettime(&ps->nettime); SUB_TVALSPEC(&ps->nettime, &ps->starttime); dgramtest_record((void *)&ps->nettime); #endif /* 0 */ #else xGetTime(&endtime); xSubTime(&ps->nettime, endtime, ps->starttime); #endif /* MACH_KERNEL */ return XK_SUCCESS; } #if MACH_KERNEL rtc_gettime(&singletime); SUB_TVALSPEC(&singletime, &ps->partialtime); dgramtest_record((void *)&singletime); rtc_gettime(&ps->partialtime); #endif /* MACH_KERNEL */ msgConstructCopy(&reply, dg); (void)xPush(lls, &reply); msgDestroy(&reply); return XK_SUCCESS; }
// Realizes the player by initiating a connection to the target, allocates // buffers, etc. OsStatus MpStreamPlayer::realize(UtlBoolean bBlock /* = TRUE */) { OsStatus status = OS_FAILED ; OsEvent eventHandle ; intptr_t eventData ; // Only proceed if we have a flow graph and the player is unrealized. if (getState() == PlayerUnrealized) { // Create an mpQueueEvent object to signal state changes in from // the MpStreamFeeder mpQueueEvent = new OsQueuedEvent(*getMessageQueue(), 0); // Realize the stream if (mSourceType == SourceUrl) { if (mpMsgQ != NULL) { MpStreamMsg msg(MpStreamMsg::STREAM_REALIZE_URL, mTarget, NULL, &eventHandle, mpQueueEvent, mFlags, (intptr_t) new Url(mUrl)) ; status = mpMsgQ->send(msg) ; } } else if (mSourceType == SourceBuffer) { if (mpMsgQ != NULL) { MpStreamMsg msg(MpStreamMsg::STREAM_REALIZE_BUFFER, mTarget, NULL, &eventHandle, mpQueueEvent, mFlags, (intptr_t) mpBuffer) ; status = mpMsgQ->send(msg) ; } } if (status == OS_SUCCESS) { // Wait for a response status = eventHandle.wait(OsTime(MAX_REALIZE_WAIT, 0)) ; if (status == OS_SUCCESS) { if (eventHandle.getEventData(eventData) == OS_SUCCESS) { mHandle = (StreamHandle) eventData ; if (mHandle != 0) mbRealized = TRUE ; } else { mHandle = NULL ; } } else { mHandle = NULL ; } } } if (mHandle == 0) { mState = PlayerDestroyed ; status = OS_FAILED ; mSemStateChange.release() ; } if (status == OS_SUCCESS) { // Start Server task if successfull if (start() == TRUE) { // Block while waiting for prefetch (if requested) if (bBlock) { while (getState() == PlayerUnrealized) { mSemStateChange.acquire(); } } else { // Wait for task to startup while (!isStarted()) { OsTask::yield() ; } } } else { syslog(FAC_STREAMING, PRI_CRIT, "Failed to create thread for MpStreamPlayer") ; // Unable to create thread; attempt to clean up status = OS_FAILED ; MpStreamMsg msgStop(MpStreamMsg::STREAM_STOP, mTarget, mHandle); mpMsgQ->send(msgStop) ; MpStreamMsg msgDestroy(MpStreamMsg::STREAM_DESTROY, mTarget, mHandle); mpMsgQ->send(msgDestroy) ; // YIKES: This is hard to recover from, we don't have a message queue // to wait for a response from the lower layers. If someone deletes // this immediately after this call, the lower layers could choke // on a now-deleted mpQueueEvent. There are two options that I can // think of: 1) garbage collect the player after some long period of // time, 2) block the thread context for some reasonable amount of // time. I'm going with #2 for now... OsTask::delay(1000) ; mbRealized = FALSE ; mState = PlayerDestroyed ; mSemStateChange.release() ; } } return status ; }
// Pauses a specific entry OsStatus MpStreamPlaylistPlayer::destroyEntry(PlayListEntry* e, UtlBoolean bBlockAndClean /*= TRUE*/) { OsStatus status = OS_INVALID_ARGUMENT; // OsSysLog::add(FAC_MP, PRI_DEBUG, "MpStreamPlaylistPlayer::destroyEntry %p[%d]", e, e? e->index:-1); if (e != NULL) { status = OS_SUCCESS; // Only proceed if we have a flow graph and the player is prefetched or // playing. if (e->state != PlayerUnrealized) { int iState = e->state; if ( (iState != PlayerStopped) && (iState != PlayerAborted) && (iState != PlayerDestroyed) ) { MpStreamMsg msgStop(MpStreamMsg::STREAM_STOP, mTarget, e->handle); status = mpMsgQ->send(msgStop); if (status != OS_SUCCESS) { setEntryState(e, PlayerFailed); OsSysLog::add(FAC_MP, PRI_ERR, "MpStreamPlaylistPlayer::destroyEntry failed on send of MpStreamMsg::STREAM_STOP message"); } } if ((iState != PlayerDestroyed) && (status == OS_SUCCESS)) { MpStreamMsg msgDestroy(MpStreamMsg::STREAM_DESTROY, mTarget, e->handle); status = mpMsgQ->send(msgDestroy); if (status != OS_SUCCESS) { setEntryState(e, PlayerFailed); OsSysLog::add(FAC_MP, PRI_ERR, "MpStreamPlaylistPlayer::destroyEntry failed on send of MpStreamMsg::STREAM_DESTROY message"); } } if (bBlockAndClean) { while (e->state != PlayerDestroyed) { status = mSemStateChange.acquire(mDestroyTimeout); if (status == OS_WAIT_TIMEOUT) { OsSysLog::add(FAC_MP, PRI_ERR, "MpStreamPlaylistPlayer::destroyEntry timed out waiting for Delete to complete"); break; } } if (e->pQueuedEvent != NULL) { delete e->pQueuedEvent; } // Delete the PlayListEntry delete e ; } } } return status; }