コード例 #1
0
ファイル: parse.c プロジェクト: insertion/SEED_LAB
void *Parse_parse (int fd, int reqOnly)
{
  http400 = generate400();
  //getToken(fd, 1);    modify
  
  ReqLine_t reqline;
  Http_t http = 0;
  if(reqOnly){
    reqline = Parse_reqLine (fd);
    return reqline;
  }
  
  parseHeaders(fd);
  if (token.kind!=TOKEN_CRLF)
    parseError(fd);
  
  int num = parseBody(fd);  
  
  reqline = gReqline;
  
  http = Http_new (HTTP_KIND_REQUEST
		   , reqline
		   , 0
		   , 0
		   , 0);
  
  if (DEBUG)
    Http_print (1, http);
  return http;
}
コード例 #2
0
ファイル: http.cpp プロジェクト: Joker-vD/sntlm
HttpResponse::HttpResponse(TcpClientSocket& socket)
	: buffer(socket)
	, ischunked(false)
	, contentlength(nlen)
{
	raw_statusline = buffer.getline();
	if (raw_statusline.empty()) { throw http_exception("Empty response"); }

	parseResponseLine(raw_statusline);

	std::vector<std::string> raw_headers;
	for (std::string line = buffer.getline(); !line.empty(); line = buffer.getline()) {
		if (('\x20' == line[0]) || ('\t' == line[0])) {
			auto last = raw_headers.rbegin();
			if (raw_headers.rend() == last) { throw http_exception("HTTP request can't start with a whitespace"); }
			if (last->find(':') == std::string::npos) { throw http_exception("Header name can't reside on multiple lines"); }
			*last += line;
		}
		else {
			raw_headers.push_back(line);
		}
	}

	parseHeaders(raw_headers);
}
コード例 #3
0
ファイル: HTTPRequest.cpp プロジェクト: bensonX/EasyDarwin
//Parses the request
QTSS_Error HTTPRequest::Parse()
{
	Assert(fRequestHeader.Ptr != NULL);
	StringParser parser(&fRequestHeader);

	// Store the request line (used for logging) 
	// (ex: GET /index.html HTTP/1.0)
	StringParser requestLineParser(&fRequestHeader);
	requestLineParser.ConsumeUntil(&fRequestLine, StringParser::sEOLMask);

	// Parse request line returns an error if there is an error in the
	// request URI or the formatting of the request line. 
	// If the method or version are not found, they are set
	// to httpIllegalMethod or httpIllegalVersion respectively, 
	// and QTSS_NoErr is returned.
	QTSS_Error err = QTSS_NoErr;
	do {
		err = parseRequestLine(&parser);
		if (err != QTSS_NoErr)
			return err;
	} while (fHTTPType == httpIllegalType);

	// Parse headers and set values of headers into fFieldValues array
	err = parseHeaders(&parser);
	if (err != QTSS_NoErr)
		return err;

	return QTSS_NoErr;
}
コード例 #4
0
ファイル: HTTPRequest.cpp プロジェクト: RamseyK/ByteBufferCpp
/**
 * Parse
 * Populate internal HTTPRequest variables by parsing the HTTP data
 *
 * @param True if successful. If false, sets parseErrorStr for reason of failure
 */
bool HTTPRequest::parse() {
	std::string initial = "", methodName = "";

	// Get elements from the initial line: <method> <path> <version>\r\n
	methodName = getStrElement();
	requestUri = getStrElement();
	version = getLine(); // End of the line, pull till \r\n

	// Convert the name to the internal enumeration number
	method = methodStrToInt(methodName);
	if(method == -1) {
		parseErrorStr = "Invalid Method: " + methodName;
		return false;
	}

	// Validate the HTTP version. If there is a mismatch, discontinue parsing
	if(strcmp(version.c_str(), HTTP_VERSION) != 0) {
		parseErrorStr = "Supported HTTP version does not match";
		return false;
	}

	// Parse and populate the headers map using the parseHeaders helper
	parseHeaders();

	// Only POST and PUT can have Content (data after headers)
	if((method != POST) && (method != PUT))
		return true;
	
	// Parse the body of the message
	if(!parseBody())
		return false;
	
	return true;
}
コード例 #5
0
void RequestParser::parsePart(const Item& aItem, Part& aPart)
{
  Item lHeaders;
  Item lBody;

  bool lHaveHeaders = getObject(aItem, "headers", false, lHeaders);
  if (lHaveHeaders)
    parseHeaders(lHeaders, aPart.theHeaders);

  getObject(aItem, "body", true, lBody);
  parseBody(lBody, aPart.theBody);
}
コード例 #6
0
ファイル: request.c プロジェクト: gamman/appweb-3
/*
 *  Parse a new request. Return true to keep going with this or subsequent request, zero means insufficient data to proceed.
 */
static bool parseRequest(MaConn *conn, MaPacket *packet) 
{
    MaRequest   *req;
    char        *start, *end;
    int         len;

    /*
     *  Must wait until we have the complete set of headers.
     */
    if ((len = mprGetBufLength(packet->content)) == 0) {
        return 0;
    }
    start = mprGetBufStart(packet->content);
    if ((end = mprStrnstr(start, "\r\n\r\n", len)) == 0) {
        return 0;
    }
    len = (int) (end - start);
    if (len >= conn->host->limits->maxHeader) {
        maFailConnection(conn, MPR_HTTP_CODE_REQUEST_TOO_LARGE, "Header too big");
        return 0;
    }
    if (parseFirstLine(conn, packet)) {
        parseHeaders(conn, packet);
    } else {
        return 0;
    }
    maMatchHandler(conn);
    
    /*
     *  Have read the headers. Create the request pipeline. This calls the open() stage entry routines.
     */
    maCreatePipeline(conn);

    req = conn->request;
    if (conn->connectionFailed) {
        /* Discard input data */
        mprAssert(conn->keepAliveCount <= 0);
        conn->state = MPR_HTTP_STATE_PROCESSING;
        maRunPipeline(conn);
    } else if (req->remainingContent > 0) {
        conn->state = MPR_HTTP_STATE_CONTENT;
    } else if (req->length == -1 && (req->method == MA_REQ_POST || req->method == MA_REQ_PUT)) {
        conn->state = MPR_HTTP_STATE_CONTENT;
    } else {
        /*
         *  Can run the request now if there is no incoming data.
         */
        conn->state = MPR_HTTP_STATE_PROCESSING;
        maRunPipeline(conn);
    }
    return !conn->disconnected;
}
コード例 #7
0
/** 
 * 
 * 
 * @param err 
 * @param len 
 */
void connection::handle_server_read_headers(const bs::error_code& err, size_t len) {
	if(!err) {
		std::string::size_type idx;
		if(fHeaders.empty())
			fHeaders=std::string(sbuffer.data(),len);
		else
			fHeaders+=std::string(sbuffer.data(),len);
		idx=fHeaders.find("\r\n\r\n");
		if(idx == std::string::npos) { // going to read rest of headers
			async_read(ssocket_, ba::buffer(sbuffer), ba::transfer_at_least(1),
					   boost::bind(&connection::handle_browser_read_headers,
								   shared_from_this(),
								   ba::placeholders::error,
								   ba::placeholders::bytes_transferred));
		} else { // analyze headers
			RespReaded=len-idx-4;
			idx=fHeaders.find("\r\n");
 			std::string respString=fHeaders.substr(0,idx);
			RespLen = -1;
			parseHeaders(fHeaders.substr(idx+2),respHeaders);
			std::string reqConnString="",respConnString="";

			std::string respVersion=respString.substr(respString.find("HTTP/")+5,3);
			
			headersMap::iterator it=respHeaders.find("Content-Length");
			if(it != respHeaders.end())
				RespLen=boost::lexical_cast<int>(it->second);
			it=respHeaders.find("Connection");
			if(it != respHeaders.end())
				respConnString=it->second;
			it=reqHeaders.find("Connection");
			if(it != reqHeaders.end())
				reqConnString=it->second;
			
			isPersistent=(
				((fReqVersion == "1.1" && reqConnString != "close") ||
				 (fReqVersion == "1.0" && reqConnString == "keep-alive")) &&
				((respVersion == "1.1" && respConnString != "close") ||
				 (respVersion == "1.0" && respConnString == "keep-alive")) &&
				RespLen != -1);
			// send data
			ba::async_write(bsocket_, ba::buffer(fHeaders),
							boost::bind(&connection::handle_browser_write,
										shared_from_this(),
										ba::placeholders::error,
										ba::placeholders::bytes_transferred));
		}
	} else {
		shutdown();
	}
}
コード例 #8
0
void RequestParser::parseRequest(const Item& aItem, Request& aRequest)
{
  if (!getString(aItem, "method", false, aRequest.theMethod))
    aRequest.theMethod = "GET";
  else
    aRequest.theMethod = fn::upper_case(aRequest.theMethod);

  getString(aItem, "href", true, aRequest.theHref);

  Item lAuthentication;
  if ((aRequest.theAuthentication.theSendAuthentication = getObject(aItem, "authentication", false, lAuthentication)))
    parseAuthentication(lAuthentication, aRequest.theAuthentication);

  Item lOptions;
  if (getObject(aItem, "options", false, lOptions))
    parseOptions(lOptions, aRequest.theOptions);

  // follow-redirect: take care of the default (if the user didn't provide one)
  if (aRequest.theMethod == "GET" || aRequest.theMethod == "HEAD" || aRequest.theMethod == "OPTIONS")
  {
    if (!aRequest.theOptions.theUserDefinedFollowRedirect)
      aRequest.theOptions.theFollowRedirect = true;
  }
  else
  {
    if (aRequest.theOptions.theFollowRedirect)
    {
      std::ostringstream lMsg;
      lMsg << "cannot follow redirect, request method: " << aRequest.theMethod;
      theThrower->raiseException("FOLLOW", lMsg.str());
    }
  }

  Item lHeaders;
  bool lHaveHeaders = getObject(aItem, "headers", false, lHeaders);
  if (lHaveHeaders)
    parseHeaders(lHeaders, aRequest.theHeaders);

  Item lBody;
  Item lMultipart;
  aRequest.theHaveBody = getObject(aItem, "body", false, lBody);
  aRequest.theHaveMultiPart = getObject(aItem, "multipart", false, lMultipart);
  if (aRequest.theHaveBody && aRequest.theHaveMultiPart)
    theThrower->raiseException("REQUEST","The specified request is not valid. HTTP request cannot contain both body and multipart");

  if (aRequest.theHaveBody)
    parseBody(lBody, aRequest.theBody);

  if (aRequest.theHaveMultiPart)
    parseMultipart(lMultipart, aRequest.theMultiPart);
}
コード例 #9
0
ファイル: HttpResponse.cpp プロジェクト: gaobaoru/socket
bool HttpResponse::parse(){
    std::string statusstr;

    version = getStrElement();
    statusstr = getStrElement();
    determineStatusCode();
    reason = getLine();

    parseHeaders();

    if(!parseBody())
   	return false;

    return true;
}
コード例 #10
0
/** 
 * 
 * 
 * @param err 
 * @param len 
 */
void connection::handle_browser_read_headers(const bs::error_code& err, size_t len) {
	if(!err) {
		if(fHeaders.empty())
			fHeaders=std::string(bbuffer.data(),len);
		else
			fHeaders+=std::string(bbuffer.data(),len);
		if(fHeaders.find("\r\n\r\n") == std::string::npos) { // going to read rest of headers
			async_read(bsocket_, ba::buffer(bbuffer), ba::transfer_at_least(1),
					   boost::bind(&connection::handle_browser_read_headers,
								   shared_from_this(),
								   ba::placeholders::error,
								   ba::placeholders::bytes_transferred));
		} else { // analyze headers
			std::string::size_type idx=fHeaders.find("\r\n");
			std::string reqString=fHeaders.substr(0,idx);
			fHeaders.erase(0,idx+2);

			idx=reqString.find(" ");
			if(idx == std::string::npos) {
				std::cout << "Bad first line: " << reqString << std::endl;
				return;
			}
			
			fMethod=reqString.substr(0,idx);
			reqString=reqString.substr(idx+1);
			idx=reqString.find(" ");
			if(idx == std::string::npos) {
				std::cout << "Bad first line of request: " << reqString << std::endl;
				return;
			}
			fURL=reqString.substr(0,idx);
			fReqVersion=reqString.substr(idx+1);
			idx=fReqVersion.find("/");
			if(idx == std::string::npos) {
				std::cout << "Bad first line of request: " << reqString << std::endl;
				return;
			}
			fReqVersion=fReqVersion.substr(idx+1);
			
			// analyze headers, etc
			parseHeaders(fHeaders,reqHeaders);
			// pass control
			start_connect();
		}
	} else {
		shutdown();
	}
}
コード例 #11
0
    void HttpResponseParser::parseMultipartBody(Item& aItem, const std::string& aBoundary)
    {
      std::istream& lStream = aItem.getStream();

      std::string lLine;
      std::stringstream lBody;

      parseStartBoundary(lStream, aBoundary);

      while (lStream.good())
      {
        parseHeaders(lStream);
        if (parseBody(lStream, aBoundary))
          return;
      }
  }
コード例 #12
0
ファイル: MailMessage.cpp プロジェクト: ruphy/kfunambol
int MailMessage::parse(const char *rfc2822, size_t len) {
    StringBuffer s(rfc2822, len);
    int rc;

    LOG.debug("MailMessage::parse START");

    size_t hdrlen = getHeadersLen(s, newline);

    StringBuffer headers = s.substr(0, hdrlen);    
    StringBuffer rfcbody;

    rc = parseHeaders(headers);
    if(rc)
        return rc;

    if(contentType.ifind(MULTIPART) != StringBuffer::npos) {
        // Multipart message
        rfcbody = s.substr(hdrlen);
        rc= parseBodyParts(rfcbody);
    }
    else {
        // go to the beginning of the body
        hdrlen = hdrlen + strlen(newline) + strlen(newline);
        rfcbody = s.substr(hdrlen);
        body.setMimeType(contentType);
        // FIXME: handle all encodings, not only quoted-printable
        if( strcmp(body.getEncoding(), "quoted-printable") == 0 ) {
            char *decoded = qp_decode( rfcbody );
            body.setContent ( decoded );
            delete [] decoded;
        }
        else if ( strcmp(body.getEncoding(), "base64") == 0 ) {
            char *decoded = NULL;
            size_t len = 0;
            rc = uudecode( rfcbody, &decoded, &len ) ;
            if( !rc ) {
                body.setContent ( decoded );
                delete [] decoded;
            }
        }
        else body.setContent(rfcbody);
    }

    LOG.debug("MailMessage::parse END");
    return rc;
}
コード例 #13
0
ファイル: HttpClient.cpp プロジェクト: ESAlexhi/Sming
err_t HttpClient::onReceive(pbuf *buf)
{
	if (buf == NULL)
	{
		// Disconnected, close it
		TcpClient::onReceive(buf);
	}
	else
	{
		int startPos = 0;
		if (waitParse)
		{
			String http = NetUtils::pbufStrCopy(buf, 0, 4);
			http.toUpperCase();
			if (http == "HTTP" && code == 0)
			{
				int codeStart = NetUtils::pbufFindChar(buf, ' ', 4);
				int codeEnd = NetUtils::pbufFindChar(buf, ' ', codeStart + 1);
				if (codeStart != -1 && codeEnd != -1 && codeEnd - codeStart < 5)
				{
					String strCode = NetUtils::pbufStrCopy(buf, codeStart, codeEnd);
					code = strCode.toInt();
				}
				else
					code = 0;
			}
			int headerEnd = NetUtils::pbufFindStr(buf, "\r\n\r\n");
			if (headerEnd != -1)
			{
				debugf("Header pos: %d", headerEnd);
				startPos = headerEnd + 4;
				waitParse = false;
				if (headerEnd < NETWORK_MAX_HTTP_PARSING_LEN)
					parseHeaders(buf, headerEnd);
			}
		}

		writeRawData(buf, startPos);

		// Fire ReadyToSend callback
		TcpClient::onReceive(buf);
	}

	return ERR_OK;
}
コード例 #14
0
ファイル: HTTPProxy.cpp プロジェクト: MDrollette/i2pd
	void HTTPProxyConnection::RunRequest()
	{
		request r;
		ExtractRequest(r);
		parseHeaders(m_Buffer, r.headers);
		size_t addressHelperPos = r.uri.find ("i2paddresshelper");
		if (addressHelperPos != std::string::npos)
		{
			// jump service
			size_t addressPos = r.uri.find ("=", addressHelperPos);
			if (addressPos != std::string::npos)
			{
				LogPrint ("Jump service for ", r.host, " found. Inserting to address book");
				auto base64 = r.uri.substr (addressPos + 1);
				i2p::client::context.GetAddressBook ().InsertAddress (r.host, base64);
			}
		}			
	
		LogPrint("Requesting ", r.host, ":", r.port, " with path ", r.uri, " and method ", r.method);
		SendToAddress (r.host, r.port,  m_Buffer, m_BufferLen);
	}
コード例 #15
0
ファイル: llmime.cpp プロジェクト: Nora28/imprudence
bool LLMimeParser::Impl::parseIndex(
	std::istream& istr,
	S32 limit,
	const std::string& separator,
	bool is_subpart,
	LLMimeIndex& index)
{
	LLSD headers;
	bool parsed_something = false;
	if(parseHeaders(istr, limit, headers))
	{
		parsed_something = true;
		LLMimeIndex mime(headers, mScanCount);
		index = mime;
		if(index.isMultipart())
		{
			// Figure out the separator, scan past it, and recurse.
			std::string ct = headers[CONTENT_TYPE].asString();
			std::string sep = findSeparator(ct);
			scanPastSeparator(istr, limit, sep);
			while(continueParse() && parseIndex(istr, limit, sep, true, mime))
			{
				index.attachSubPart(mime);
			}
		}
		else
		{
			// Scan to the end of content.
			scanPastContent(istr, limit, headers, separator);
			if(is_subpart)
			{
				scanPastSeparator(istr, limit, separator);
			}
		}
	}
	if(mError) return false;
	return parsed_something;
}
コード例 #16
0
ファイル: parse.c プロジェクト: BitVoyage/InfoSecuratyLab
Http_t Parse_parse (int fd)
{
  http400 = generate400();
  getToken(fd, 1);

  ReqLine_t reqline;
  Http_t http = 0;

  reqline = parseRequestLine (fd);
  parseHeaders(fd);
  if (token.kind!=TOKEN_CRLF)
    parseError(fd);
  parseBody(fd);
  http = Http_new (HTTP_KIND_REQUEST
		   , reqline
		   , 0
		   , 0
		   , 0);

  if (DEBUG)
    Http_print (1, http);
  return http;
}
コード例 #17
0
const char*
HttpResponse::parseResponse(const char* buffer, size_t size)
{
  const char* curPos = buffer;

  const char* endline = (const char*)memmem(curPos, size - (curPos - buffer), "\r\n", 2);
  if (endline == 0)
    throw ParseError("HTTP response doesn't end with \\r\\n");

  string responseLine(curPos, endline - curPos);
  size_t posFirstSpace = responseLine.find(" ");
  size_t posSecondSpace = responseLine.find(" ", posFirstSpace + 1);

  if (posFirstSpace == string::npos || posSecondSpace == string::npos)
    throw ParseError("Incorrectly formatted response");

  // 1. HTTP version
  if (responseLine.compare(0, 5, "HTTP/") != 0)
    throw ParseError("Incorrectly formatted HTTP response");

  string version = responseLine.substr(5, posFirstSpace - 5);
  // TRACE(version);
  setVersion(version);

  // 2. Response code
  string code = responseLine.substr(posFirstSpace + 1, posSecondSpace - posFirstSpace - 1);
  // TRACE(code);
  setStatusCode(code);

  string msg = responseLine.substr(posSecondSpace + 1, responseLine.size() - posSecondSpace - 1);
  // TRACE(msg);
  setStatusMsg(msg);

  curPos = endline + 2;
  return parseHeaders(curPos, size - (curPos - buffer));
}
コード例 #18
0
ファイル: TheoraPlayer.cpp プロジェクト: binji/drod-nacl
bool CTheoraPlayer::playVideo(
//Plays specified OGG Theora file to screen surface.
//If screen == NULL, then this method will test that the file is playable
//by decoding it as fast as possible but not displaying anything.
//
//Returns: whether playback was successful
	CStretchyBuffer& buffer, SDL_Surface *screen,
	const int x, const int y) //[default=(0,0)]
{
	//init
	theora_p = vorbis_p = 0;
	startticks = 0;
	bool bSkippedLastFrame = false;

	// start up Ogg stream synchronization layer
	ogg_sync_init(&oy);

	// init supporting Vorbis structures needed in header parsing
	vorbis_info_init(&vi);
	vorbis_comment_init(&vc);

	// init supporting Theora structures needed in header parsing
	theora_comment_init(&tc);
	theora_info_init(&ti);
	if (!screen)
		ti.quick_p = 1;
	ti.quality = 63;

	if (!parseHeaders(buffer))
		return false;

	// force audio off
	vorbis_p = 0;

	// initialize decoders
	if (theora_p) {
		theora_decode_init(&td,&ti);
#if 0
		printf("Ogg logical stream %x is Theora %dx%d %.02f fps video\n"
			  "  Frame content is %dx%d with offset (%d,%d).\n",
			to.serialno,ti.width,ti.height, (double)ti.fps_numerator/ti.fps_denominator,
			ti.frame_width, ti.frame_height, ti.offset_x, ti.offset_y);
		//report_colorspace(&ti); //we're not using this info for anything
		dump_comments(&tc);
#endif
	} else {
		// tear down the partial theora setup
		theora_info_clear(&ti);
		theora_comment_clear(&tc);
	}
	if(vorbis_p) {
		vorbis_synthesis_init(&vd,&vi);
		vorbis_block_init(&vd,&vb);  
		printf("Ogg logical stream %lx is Vorbis %d channel %ld Hz audio.\n",
			vo.serialno,vi.channels,vi.rate);
	} else {
		// tear down the partial vorbis setup
		vorbis_info_clear(&vi);
		vorbis_comment_clear(&vc);
	}

	// open audio
	if (vorbis_p)
		open_audio();

	// open video
	SDL_Overlay *yuv_overlay = NULL;
	if (theora_p && screen)
		yuv_overlay = open_video(screen);
  
	// single frame video buffering
	ogg_packet op;
	ogg_int64_t  videobuf_granulepos=-1;
	double       videobuf_time=0;
	double last_frame_time = 0;
	bool hasdatatobuffer = true;

	// Main loop
	bool audiobuf_ready=false;
	bool videobuf_ready=false;
	bool playbackdone = (yuv_overlay == NULL);
	bool isPlaying = false;
	bool bBreakout = false;
	while (!playbackdone)
	{
		// break out on SDL quit event
		SDL_Event event;
		if (SDL_PollEvent(&event))
		{
			switch (event.type)
			{
				case SDL_QUIT: playbackdone = bBreakout = true; break;
				case SDL_KEYDOWN:
					if (event.key.keysym.sym == SDLK_ESCAPE)
						playbackdone = bBreakout = true;
				break;
				default: break;
			}
		}

		while (theora_p && !videobuf_ready) {
			// get one video packet...
			if (ogg_stream_packetout(&to,&op)>0)
			{
				theora_decode_packetin(&td,&op);

				videobuf_granulepos=td.granulepos;
				videobuf_time=theora_granule_time(&td,videobuf_granulepos);

#if 0
				//Without sound channels to synch to, don't need to worry about skipping frames when slow.
				// update the frame counter
				//++frameNum;

				// check if this frame time has not passed yet.
				//	If the frame is late we need to decode additional
				//	ones and keep looping, since theora at this stage
				//	needs to decode all frames.
				const double now=get_time();
				const double delay=videobuf_time-now;
				if(delay>=0.0){
					/// got a good frame, not late, ready to break out
					videobuf_ready=true;
				} else if(now-last_frame_time>=1.0) {
					// display at least one frame per second, regardless
					videobuf_ready=true;
				} else {
					//Need to catch up -- no time to display frame.
					if (bSkippedLastFrame) //only allow skipping one frame in a row
						videobuf_ready = true; //show anyway
					else
						bSkippedLastFrame = true;
					//printf("dropping frame %d (%.3fs behind)\n", frameNum, -delay);
				}
#else
				videobuf_ready = true; //show every frame
#endif
			} else {
				// need more data
				break;
			}
		}

		if (!hasdatatobuffer && !videobuf_ready && !audiobuf_ready) {
			isPlaying = false;
			playbackdone = true;
		}

		//If we're set for the next frame, sleep.
		//In other words, don't show frames too rapidly. 
		if((!theora_p || videobuf_ready) && 
			(!vorbis_p || audiobuf_ready))
		{
			const int ticks = (int)(1000*(videobuf_time-get_time()));
			if(ticks>0 && screen) //don't need to sleep if only testing file
				SDL_Delay(ticks);
		}
 
		if (videobuf_ready)
		{
			// time to write our cached frame
			if (screen)
			{
				const bool bRes = video_write(screen, yuv_overlay, x, y);
				if (!bRes) //couldn't display image
					playbackdone = bBreakout = true;
			}
			videobuf_ready=false;
			last_frame_time=get_time();
			bSkippedLastFrame = false;

			// if audio has not started (first frame) then start it
			if ((!isPlaying)&&(vorbis_p)) {
				start_audio();
				isPlaying = true;
			}
		}

		// HACK: always look for more audio data
		audiobuf_ready=false;

		// buffer compressed data every loop
		if (hasdatatobuffer) {
			hasdatatobuffer = buffer_data(&oy, buffer) > 0;
			if (!hasdatatobuffer) {
				//printf("Ogg buffering stopped, end of file reached.\n");
			}
		}
    
		if (ogg_sync_pageout(&oy,&og)>0)
			queue_page(&og);

	} // playbackdone

	// show number of video frames decoded
	//printf("\nFrames decoded: %d\n", frameNum);

	// deinit
	if (vorbis_p) {
		audio_close();

		ogg_stream_clear(&vo);
		vorbis_block_clear(&vb);
		vorbis_dsp_clear(&vd);
		vorbis_comment_clear(&vc);
		vorbis_info_clear(&vi); 
	}
	if (theora_p) {
		if (yuv_overlay)
			SDL_FreeYUVOverlay(yuv_overlay);

		ogg_stream_clear(&to);
		theora_clear(&td);
		theora_comment_clear(&tc);
		theora_info_clear(&ti);
	}
	ogg_sync_clear(&oy);

	//If broken out of testing, return false since entire file was not verified.
	return !bBreakout || screen != NULL;
}
コード例 #19
0
ファイル: Websocket.c プロジェクト: GangXu/Websocket-1
void *handleClient(void *args) {
	pthread_detach(pthread_self());
	pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
	pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
	pthread_cleanup_push(&cleanup_client, args);

	int buffer_length = 0, string_length = 1, reads = 1;

	ws_client *n = args;
	n->thread_id = pthread_self();

	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
	pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);

	char buffer[BUFFERSIZE];
	n->string = (char *) malloc(sizeof(char));

	if (n->string == NULL) {
		pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
		handshake_error("Couldn't allocate memory.", ERROR_INTERNAL, n);
		pthread_exit((void *) EXIT_FAILURE);
	}

	printf("Client connected with the following information:\n"
		   "\tSocket: %d\n"
		   "\tAddress: %s\n\n", n->socket_id, (char *) n->client_ip);
	printf("Checking whether client is valid ...\n\n");
	fflush(stdout);

	/**
	 * Getting headers and doing reallocation if headers is bigger than our
	 * allocated memory.
	 */
	do {
		memset(buffer, '\0', BUFFERSIZE);
		if ((buffer_length = recv(n->socket_id, buffer, BUFFERSIZE, 0)) <= 0){
			pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
			handshake_error("Didn't receive any headers from the client.", 
					ERROR_BAD, n);
			pthread_exit((void *) EXIT_FAILURE);
		}

		if (reads == 1 && strlen(buffer) < 14) {
			handshake_error("SSL request is not supported yet.", 
					ERROR_NOT_IMPL, n);
			pthread_exit((void *) EXIT_FAILURE);
		}

		string_length += buffer_length;

		char *tmp = realloc(n->string, string_length);
		if (tmp == NULL) {
			pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
			handshake_error("Couldn't reallocate memory.", ERROR_INTERNAL, n);
			pthread_exit((void *) EXIT_FAILURE);
		}
		n->string = tmp;
		tmp = NULL;

		memset(n->string + (string_length-buffer_length-1), '\0', 
				buffer_length+1);
		memcpy(n->string + (string_length-buffer_length-1), buffer, 
				buffer_length);
		reads++;
	} while( strncmp("\r\n\r\n", n->string + (string_length-5), 4) != 0 
			&& strncmp("\n\n", n->string + (string_length-3), 2) != 0
			&& strncmp("\r\n\r\n", n->string + (string_length-8-5), 4) != 0
			&& strncmp("\n\n", n->string + (string_length-8-3), 2) != 0 );
	
	printf("User connected with the following headers:\n%s\n\n", n->string);
	fflush(stdout);

	ws_header *h = header_new();

	if (h == NULL) {
		pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
		handshake_error("Couldn't allocate memory.", ERROR_INTERNAL, n);
		pthread_exit((void *) EXIT_FAILURE);
	}

	n->headers = h;

	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
	if ( parseHeaders(n->string, n, port) < 0 ) {
		pthread_exit((void *) EXIT_FAILURE);
	}

	if ( sendHandshake(n) < 0 && n->headers->type != UNKNOWN ) {
		pthread_exit((void *) EXIT_FAILURE);	
	}	

	list_add(l, n);
	pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);

	printf("Client has been validated and is now connected\n\n");
	printf("> ");
	fflush(stdout);

	uint64_t next_len = 0;
	char next[BUFFERSIZE];
	memset(next, '\0', BUFFERSIZE);

	while (1) {
		if ( communicate(n, next, next_len) != CONTINUE) {
			break;
		}

		pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
		if (n->headers->protocol == CHAT) {
			list_multicast(l, n);
		} else if (n->headers->protocol == ECHO) {
			list_multicast_one(l, n, n->message);
		} else {
			list_multicast_one(l, n, n->message);
		}
		pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);

		if (n->message != NULL) {
			memset(next, '\0', BUFFERSIZE);
			memcpy(next, n->message->next, n->message->next_len);
			next_len = n->message->next_len;
			message_free(n->message);
			free(n->message);
			n->message = NULL;	
		}
	}
	
	printf("Shutting client down..\n\n");
	printf("> ");
	fflush(stdout);

	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
	list_remove(l, n);
	pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);

	pthread_cleanup_pop(0);
	pthread_exit((void *) EXIT_SUCCESS);
}
コード例 #20
0
ファイル: KDSoapServerSocket.cpp プロジェクト: nbeudez/KDSoap
void KDSoapServerSocket::slotReadyRead()
{
    if (!m_socketEnabled)
        return;

    //qDebug() << this << QThread::currentThread() << "slotReadyRead!";
    QByteArray buf(2048, ' ');
    qint64 nread = -1;
    while (nread != 0) {
        nread = read(buf.data(), buf.size());
        if (nread < 0) {
            qDebug() << "Error reading from server socket:" << errorString();
            return;
        }
        m_requestBuffer += buf.left(nread);
    }

    //qDebug() << "KDSoapServerSocket: request:" << m_requestBuffer;

    QByteArray receivedHttpHeaders, receivedData;
    const bool splitOK = splitHeadersAndData(m_requestBuffer, receivedHttpHeaders, receivedData);

    if (!splitOK) {
        //qDebug() << "Incomplete SOAP request, wait for more data";
        //incomplete request, wait for more data
        return;
    }

    QMap<QByteArray, QByteArray> httpHeaders;
    httpHeaders = parseHeaders(receivedHttpHeaders);

    if (m_doDebug) {
        qDebug() << "headers received:" << receivedHttpHeaders;
        qDebug() << httpHeaders;
        qDebug() << "data received:" << receivedData;
    }

    const QByteArray contentLength = httpHeaders.value("content-length");
    if (receivedData.size() < contentLength.toInt())
        return; // incomplete request, wait for more data
    m_requestBuffer.clear();

    const QByteArray requestType = httpHeaders.value("_requestType");
    if (requestType != "GET" && requestType != "POST") {
        qWarning() << "Unknown HTTP request:" << requestType;
        //handleError(replyMsg, "Client.Data", QString::fromLatin1("Invalid request type '%1', should be GET or POST").arg(QString::fromLatin1(requestType.constData())));
        //sendReply(0, replyMsg);
        const QByteArray methodNotAllowed = "HTTP/1.1 405 Method Not Allowed\r\nAllow: GET POST\r\nContent-Length: 0\r\n\r\n";
        write(methodNotAllowed);
        return;
    }

    const QString path = QString::fromLatin1(httpHeaders.value("_path").constData());

    KDSoapServerAuthInterface* serverAuthInterface = qobject_cast<KDSoapServerAuthInterface *>(m_serverObject);
    if (serverAuthInterface) {
        QByteArray authValue = httpHeaders.value("Authorization");
        if (authValue.isEmpty())
            authValue = httpHeaders.value("authorization"); // as sent by Qt-4.5
        if (!serverAuthInterface->handleHttpAuth(authValue, path)) {
            // send auth request (Qt supports basic, ntlm and digest)
            const QByteArray unauthorized = "HTTP/1.1 401 Authorization Required\r\nWWW-Authenticate: Basic realm=\"example\"\r\nContent-Length: 0\r\n\r\n";
            write(unauthorized);
            return;
        }
    }

    KDSoapServer* server = m_owner->server();
    KDSoapMessage replyMsg;
    replyMsg.setUse(server->use());

    KDSoapServerObjectInterface* serverObjectInterface = qobject_cast<KDSoapServerObjectInterface *>(m_serverObject);
    if (!serverObjectInterface) {
        const QString error = QString::fromLatin1("Server object %1 does not implement KDSoapServerObjectInterface!").arg(QString::fromLatin1(m_serverObject->metaObject()->className()));
        handleError(replyMsg, "Server.ImplementationError", error);
        sendReply(0, replyMsg);
        return;
    } else {
        serverObjectInterface->setServerSocket(this);
    }

    if (requestType == "GET") {
        if (path == server->wsdlPathInUrl() && handleWsdlDownload()) {
            return;
        } else if (handleFileDownload(serverObjectInterface, path)) {
            return;
        }

        // See http://www.ibm.com/developerworks/xml/library/x-tipgetr/
        // We could implement it, but there's no SOAP request, just a query in the URL,
        // which we'd have to pass to a different virtual than processRequest.
        handleError(replyMsg, "Client.Data", QString::fromLatin1("Support for GET requests not implemented yet."));
        sendReply(0, replyMsg);
        return;
    }

    //parse message
    KDSoapMessage requestMsg;
    KDSoapHeaders requestHeaders;
    KDSoapMessageReader reader;
    KDSoapMessageReader::XmlError err = reader.xmlToMessage(receivedData, &requestMsg, &m_messageNamespace, &requestHeaders);
    if (err == KDSoapMessageReader::PrematureEndOfDocumentError) {
        //qDebug() << "Incomplete SOAP message, wait for more data";
        // This should never happen, since we check for content-size above.
        return;
    } //TODO handle parse errors?

    // check soap version and extract soapAction header
    QByteArray soapAction;
    const QByteArray contentType = httpHeaders.value("content-type");
    if (contentType.startsWith("text/xml")) {
        // SOAP 1.1
        soapAction = httpHeaders.value("soapaction");
        // The SOAP standard allows quotation marks around the SoapAction, so we have to get rid of these.
        if (soapAction.startsWith('\"'))
            soapAction = soapAction.mid(1, soapAction.length() - 2);

    } else if (contentType.startsWith("application/soap+xml")) {
        // SOAP 1.2
        // Example: application/soap+xml;charset=utf-8;action=ActionHex
        const QList<QByteArray> parts = contentType.split(';');
        Q_FOREACH(const QByteArray& part, parts) {
            if (part.startsWith("action=")) {
                soapAction = part.mid(strlen("action="));
            }
        }
    }

    m_method = requestMsg.name();

    if (!replyMsg.isFault()) {
        makeCall(serverObjectInterface, requestMsg, replyMsg, requestHeaders, soapAction, path);
    }

    if (serverObjectInterface && m_delayedResponse) {
        // Delayed response. Disable the socket to make sure we don't handle another call at the same time.
        setSocketEnabled(false);
    } else {
        sendReply(serverObjectInterface, replyMsg);
    }
}
コード例 #21
0
ファイル: request.c プロジェクト: Bogdanp/facebooc
Request *requestNew(char *buff) {
    Request *request = malloc(sizeof(Request));

    char *segment, *bs;

    request->method      = UNKNOWN_METHOD;
    request->path        = NULL;
    request->uri         = NULL;
    request->queryString = NULL;
    request->postBody    = NULL;
    request->headers     = NULL;
    request->cookies     = NULL;
    request->account     = NULL;

    // METHOD
    TOK(buff, " \t");

    if      (strcmp(segment, "OPTIONS") == 0) request->method = OPTIONS;
    else if (strcmp(segment, "GET")     == 0) request->method = GET;
    else if (strcmp(segment, "HEAD")    == 0) request->method = HEAD;
    else if (strcmp(segment, "POST")    == 0) request->method = POST;
    else if (strcmp(segment, "PUT")     == 0) request->method = PUT;
    else if (strcmp(segment, "DELETE")  == 0) request->method = DELETE;
    else if (strcmp(segment, "TRACE")   == 0) request->method = TRACE;
    else if (strcmp(segment, "CONNECT") == 0) request->method = CONNECT;
    else goto fail;

    // PATH
    TOK(NULL, " \t");

    request->path = bsNew(segment);
    request->uri  = bsNew(segment);

    if (strchr(request->path, '#') != NULL)
        goto fail;

    // VERSION
    TOK(NULL, "\n");

    if (strncmp(segment, "HTTP/1.0", 8) != 0 &&
        strncmp(segment, "HTTP/1.1", 8) != 0)
        goto fail;

    // HEADERS
    request->headers = parseHeaders(segment);

    // BODY
    bs = kvFindList(request->headers, "Content-Type");

    if (bs != NULL && strncmp(bs, "application/x-www-form-urlencoded", 33) == 0) {
        segment = strtok(NULL, "\0");

        if (segment == NULL)
            goto fail;

        request->postBody = parseQS(segment);
    }

    // QUERYSTRING
    segment = strchr(request->path, '?');

    if (segment != NULL) {
        request->uri = bsNewLen(request->path, segment - request->path);
        request->queryString = parseQS(segment + 1);

        if (request->queryString == NULL)
            goto fail;
    }

    // COOKIES
    segment = kvFindList(request->headers, "Cookie");

    if (segment != NULL) {
        request->cookies = parseCookies(segment);

        if (request->cookies == NULL)
            goto fail;
    }

    return request;

fail:
    requestDel(request);

    return NULL;
}
コード例 #22
0
ファイル: httpserver_p.cpp プロジェクト: nbeudez/KDSoap
void HttpServerThread::run()
{
    m_server = new BlockingHttpServer(m_features & Ssl);
    m_server->listen();
    QMutexLocker lock(&m_mutex);
    m_port = m_server->serverPort();
    lock.unlock();
    m_ready.release();

    const bool doDebug = qgetenv("KDSOAP_DEBUG").toInt();

    if (doDebug)
        qDebug() << "HttpServerThread listening on port" << m_port;

    // Wait for first connection (we'll wait for further ones inside the loop)
    QTcpSocket *clientSocket = m_server->waitForNextConnectionSocket();
    Q_ASSERT(clientSocket);

    Q_FOREVER {
        // get the "request" packet
        if (doDebug) {
            qDebug() << "HttpServerThread: waiting for read";
        }
        if (clientSocket->state() == QAbstractSocket::UnconnectedState ||
            !clientSocket->waitForReadyRead(2000)) {
            if (clientSocket->state() == QAbstractSocket::UnconnectedState) {
                delete clientSocket;
                if (doDebug) {
                    qDebug() << "Waiting for next connection...";
                }
                clientSocket = m_server->waitForNextConnectionSocket();
                Q_ASSERT(clientSocket);
                continue; // go to "waitForReadyRead"
            } else {
                qDebug() << "HttpServerThread:" << clientSocket->error() << "waiting for \"request\" packet";
                break;
            }
        }
        const QByteArray request = m_partialRequest + clientSocket->readAll();
        if (doDebug) {
            qDebug() << "HttpServerThread: request:" << request;
        }

        // Split headers and request xml
        lock.relock();
        const bool splitOK = splitHeadersAndData(request, m_receivedHeaders, m_receivedData);
        if (!splitOK) {
            //if (doDebug)
            //    qDebug() << "Storing partial request" << request;
            m_partialRequest = request;
            continue;
        }

        m_headers = parseHeaders(m_receivedHeaders);

        if (m_headers.value("Content-Length").toInt() > m_receivedData.size()) {
            //if (doDebug)
            //    qDebug() << "Storing partial request" << request;
            m_partialRequest = request;
            continue;
        }

        m_partialRequest.clear();

        if (m_headers.value("_path").endsWith("terminateThread")) // we're asked to exit
            break; // normal exit

        // TODO compared with expected SoapAction
        QList<QByteArray> contentTypes = m_headers.value("Content-Type").split(';');
        if (contentTypes[0] == "text/xml" && m_headers.value("SoapAction").isEmpty()) {
            qDebug() << "ERROR: no SoapAction set for Soap 1.1";
            break;
        }else if( contentTypes[0] == "application/soap+xml" && !contentTypes[2].startsWith("action")){
            qDebug() << "ERROR: no SoapAction set for Soap 1.2";
            break;
        }
        lock.unlock();

        //qDebug() << "headers received:" << m_receivedHeaders;
        //qDebug() << headers;
        //qDebug() << "data received:" << m_receivedData;


        if (m_features & BasicAuth) {
            QByteArray authValue = m_headers.value("Authorization");
            if (authValue.isEmpty())
                authValue = m_headers.value("authorization"); // as sent by Qt-4.5
            bool authOk = false;
            if (!authValue.isEmpty()) {
                //qDebug() << "got authValue=" << authValue; // looks like "Basic <base64 of user:pass>"
                Method method;
                QString headerVal;
                parseAuthLine(QString::fromLatin1(authValue.data(),authValue.size()), &method, &headerVal);
                //qDebug() << "method=" << method << "headerVal=" << headerVal;
                switch (method) {
                case None: // we want auth, so reject "None"
                    break;
                case Basic:
                    {
                        const QByteArray userPass = QByteArray::fromBase64(headerVal.toLatin1());
                        //qDebug() << userPass;
                        // TODO if (validateAuth(userPass)) {
                        if (userPass == ("kdab:testpass")) {
                            authOk = true;
                        }
                        break;
                    }
                default:
                    qWarning("Unsupported authentication mechanism %s", authValue.constData());
                }
            }

            if (!authOk) {
                // send auth request (Qt supports basic, ntlm and digest)
                const QByteArray unauthorized = "HTTP/1.1 401 Authorization Required\r\nWWW-Authenticate: Basic realm=\"example\"\r\nContent-Length: 0\r\n\r\n";
                clientSocket->write( unauthorized );
                if (!clientSocket->waitForBytesWritten(2000)) {
                    qDebug() << "HttpServerThread:" << clientSocket->error() << "writing auth request";
                    break;
                }
                continue;
            }
        }

        // send response
        QByteArray response = makeHttpResponse(m_dataToSend);
        if (doDebug) {
            qDebug() << "HttpServerThread: writing" << response;
        }
        clientSocket->write(response);

        clientSocket->flush();
    }
    // all done...
    delete clientSocket;
    delete m_server;
    if (doDebug) {
        qDebug() << "HttpServerThread terminated";
    }
}
コード例 #23
0
PassRefPtr<ApplicationCache> ApplicationCacheStorage::loadCache(unsigned storageID)
{
    SQLiteStatement cacheStatement(m_database, 
                                   "SELECT url, type, mimeType, textEncodingName, headers, CacheResourceData.data FROM CacheEntries INNER JOIN CacheResources ON CacheEntries.resource=CacheResources.id "
                                   "INNER JOIN CacheResourceData ON CacheResourceData.id=CacheResources.data WHERE CacheEntries.cache=?");
    if (cacheStatement.prepare() != SQLResultOk) {
        LOG_ERROR("Could not prepare cache statement, error \"%s\"", m_database.lastErrorMsg());
        return 0;
    }
    
    cacheStatement.bindInt64(1, storageID);

    RefPtr<ApplicationCache> cache = ApplicationCache::create();
    
    int result;
    while ((result = cacheStatement.step()) == SQLResultRow) {
        KURL url(cacheStatement.getColumnText(0));
        
        unsigned type = (unsigned)cacheStatement.getColumnInt64(1);

        Vector<char> blob;
        cacheStatement.getColumnBlobAsVector(5, blob);
        
        RefPtr<SharedBuffer> data = SharedBuffer::adoptVector(blob);
        
        String mimeType = cacheStatement.getColumnText(2);
        String textEncodingName = cacheStatement.getColumnText(3);
        
        ResourceResponse response(url, mimeType, data->size(), textEncodingName, "");

        String headers = cacheStatement.getColumnText(4);
        parseHeaders(headers, response);
        
        RefPtr<ApplicationCacheResource> resource = ApplicationCacheResource::create(url, response, type, data.release());

        if (type & ApplicationCacheResource::Manifest)
            cache->setManifestResource(resource.release());
        else
            cache->addResource(resource.release());
    }

    if (result != SQLResultDone)
        LOG_ERROR("Could not load cache resources, error \"%s\"", m_database.lastErrorMsg());
    
    // Load the online whitelist
    SQLiteStatement whitelistStatement(m_database, "SELECT url FROM CacheWhitelistURLs WHERE cache=?");
    if (whitelistStatement.prepare() != SQLResultOk)
        return 0;
    whitelistStatement.bindInt64(1, storageID);
    
    HashSet<String> whitelist;
    while ((result = whitelistStatement.step()) == SQLResultRow) 
        whitelist.add(whitelistStatement.getColumnText(0));

    if (result != SQLResultDone)
        LOG_ERROR("Could not load cache online whitelist, error \"%s\"", m_database.lastErrorMsg());

    cache->setOnlineWhitelist(whitelist);
    
    cache->setStorageID(storageID);

    return cache.release();
}    
コード例 #24
0
ファイル: splayer.c プロジェクト: kazutomi/xiphqt
int main( int argc, char* argv[] ){

  int i,j;
  ogg_packet op;
  SDL_Event event;
  int hasdatatobuffer = 1;
  int playbackdone = 0;
  double now, delay, last_frame_time = 0;

  int frameNum=0;
  int skipNum=0;

  /* takes first argument as file to play */
  /* this works better on Windows and is more convenient
     for drag and drop ogg files over the .exe */

  if( argc != 2 )
  {
    usage();
    exit(0);
  }

  infile  = fopen( argv[1], "rb" );

  /* start up Ogg stream synchronization layer */
  ogg_sync_init(&oy);

  /* init supporting Vorbis structures needed in header parsing */
  vorbis_info_init(&vi);
  vorbis_comment_init(&vc);

  /* init supporting Theora structures needed in header parsing */
  theora_comment_init(&tc);
  theora_info_init(&ti);

  parseHeaders();

  /* force audio off */
  /* vorbis_p = 0; */

  /* initialize decoders */
  if(theora_p){
    theora_decode_init(&td,&ti);
    printf("Ogg logical stream %x is Theora %dx%d %.02f fps video\n"
           "  Frame content is %dx%d with offset (%d,%d).\n",
	   to.serialno,ti.width,ti.height, (double)ti.fps_numerator/ti.fps_denominator,
	   ti.frame_width, ti.frame_height, ti.offset_x, ti.offset_y);
    report_colorspace(&ti);
    dump_comments(&tc);
  }else{
    /* tear down the partial theora setup */
    theora_info_clear(&ti);
    theora_comment_clear(&tc);
  }
  if(vorbis_p){
    vorbis_synthesis_init(&vd,&vi);
    vorbis_block_init(&vd,&vb);  
    printf("Ogg logical stream %x is Vorbis %d channel %d Hz audio.\n",
	   vo.serialno,vi.channels,vi.rate);
  }else{
    /* tear down the partial vorbis setup */
    vorbis_info_clear(&vi);
    vorbis_comment_clear(&vc);
  }
  /* open audio */
  if(vorbis_p)open_audio();
  /* open video */
  if(theora_p)open_video();
  
  /* our main loop */
  while(!playbackdone){

    /* break out on SDL quit event */
    if ( SDL_PollEvent ( &event ) )
    {
      if ( event.type == SDL_QUIT ) break ;
    }

    /* get some audio data */
    while(vorbis_p && !audiobuf_ready){
      int ret;
      float **pcm;
      int count = 0;
      int maxBytesToWrite;

      /* is there pending audio? does it fit our circular buffer without blocking? */
      ret=vorbis_synthesis_pcmout(&vd,&pcm);
      maxBytesToWrite = GetAudioStreamWriteable(aOutStream);

      if (maxBytesToWrite<=FRAMES_PER_BUFFER){
        /* break out until there is a significant amount of
           data to avoid a series of small write operations. */
        break;
      }
      /* if there's pending, decoded audio, grab it */
      if((ret>0)&&(maxBytesToWrite>0)){

	for(i=0;i<ret && i<(maxBytesToWrite/vi.channels);i++)
	  for(j=0;j<vi.channels;j++){
	    int val=(int)(pcm[j][i]*32767.f);
	    if(val>32767)val=32767;
	    if(val<-32768)val=-32768;
	    samples[count]=val;
	    count++;
	  }
	if(WriteAudioStream( aOutStream, samples, i )) {
	  if(count==maxBytesToWrite){
	    audiobuf_ready=1;
	  }
	}
        vorbis_synthesis_read(&vd,i);

	if(vd.granulepos>=0)
	  audiobuf_granulepos=vd.granulepos-ret+i;
	else
	  audiobuf_granulepos+=i;

      }else{
	
	/* no pending audio; is there a pending packet to decode? */
	if(ogg_stream_packetout(&vo,&op)>0){
	  if(vorbis_synthesis(&vb,&op)==0) /* test for success! */
	   vorbis_synthesis_blockin(&vd,&vb);
	}else	/* we need more data; break out to suck in another page */
	  break;
      }
    } /* end audio cycle */

    while(theora_p && !videobuf_ready){
      /* get one video packet... */
      if(ogg_stream_packetout(&to,&op)>0){
      
        theora_decode_packetin(&td,&op);

	  videobuf_granulepos=td.granulepos;
	  videobuf_time=theora_granule_time(&td,videobuf_granulepos);
	  /* update the frame counter */
	  frameNum++;

	  /* check if this frame time has not passed yet.
	     If the frame is late we need to decode additonal
	     ones and keep looping, since theora at this stage
	     needs to decode all frames */
	  now=get_time();
	  delay=videobuf_time-now;
	  if(delay>=0.0){
		/* got a good frame, not late, ready to break out */
		videobuf_ready=1;
	  }else if(now-last_frame_time>=1.0){
		/* display at least one frame per second, regardless */
		videobuf_ready=1;
	  }else{
		fprintf(stderr, "dropping frame %d (%.3fs behind)\n",
			frameNum, -delay);
	   }
      }else{
	/* need more data */
	break;
      }
    }

    if(!hasdatatobuffer && !videobuf_ready && !audiobuf_ready){
      isPlaying = 0;
      playbackdone = 1;
    }

    /* if we're set for the next frame, sleep */
    if((!theora_p || videobuf_ready) && 
       (!vorbis_p || audiobuf_ready)){
        int ticks = 1.0e3*(videobuf_time-get_time());
	if(ticks>0)
          SDL_Delay(ticks);
    }
 
    if(videobuf_ready){
      /* time to write our cached frame */
      video_write();
      videobuf_ready=0;
      last_frame_time=get_time();

      /* if audio has not started (first frame) then start it */
      if ((!isPlaying)&&(vorbis_p)){
        start_audio();
        isPlaying = 1;
      }
    }

    /* HACK: always look for more audio data */
    audiobuf_ready=0;

    /* buffer compressed data every loop */
    if(hasdatatobuffer){
      hasdatatobuffer=buffer_data(&oy);
      if(hasdatatobuffer==0){
        printf("Ogg buffering stopped, end of file reached.\n");
      }
    }
    
    if (ogg_sync_pageout(&oy,&og)>0){
      queue_page(&og);
    }

  } /* playbackdone */

  /* show number of video frames decoded */
  printf( "\n");
  printf( "Frames decoded: %d", frameNum );
  if(skipNum)
    printf( " (only %d shown)", frameNum-skipNum);
  printf( "\n" );

  /* tear it all down */
  fclose( infile );

  if(vorbis_p){
    audio_close();

    ogg_stream_clear(&vo);
    vorbis_block_clear(&vb);
    vorbis_dsp_clear(&vd);
    vorbis_comment_clear(&vc);
    vorbis_info_clear(&vi); 
  }
  if(theora_p){
    ogg_stream_clear(&to);
    theora_clear(&td);
    theora_comment_clear(&tc);
    theora_info_clear(&ti);
  }
  ogg_sync_clear(&oy);

  printf("\r                                                              "
	 "\nDone.\n");
	 
  SDL_Quit();

  return(0);

}