httpsource.java

来自「java语言开发的P2P流媒体系统」· Java 代码 · 共 988 行 · 第 1/2 页

JAVA
988
字号
						{
							String newHeader = key + ": " + value; //$NON-NLS-1$
							
							if (additionalHTTPHeaders == null)
							{
								additionalHTTPHeaders = newHeader;
							}
							else
							{
								additionalHTTPHeaders = additionalHTTPHeaders + "\r\n" + newHeader; //$NON-NLS-1$
							}
						}
					}
				}
				
				// Zus鋞zliche HTTP-Header setzen, falls es welche gibt
				if (additionalHTTPHeaders != null)
				{
					metadata.setHttpHeaders(additionalHTTPHeaders);
				}
								
				if (isICYStream && !metaIntFound)
				{
					// Wichtige Metadaten nicht gefunden
					return false;
				}
				
				if (PlaylistParser.isPlaylistMIMEType(metadata.getContentType())) //$NON-NLS-1$
				{
					// Es ist eine Playlist!
					// Diese muss ausgelesen werden
					return false;
				}
								
				// Auch Icecast-Str鰉e als Shoutcast-Str鰉e behandeln
				isICYStream = metaIntFound;
				
				if (isICYStream)
				{
					metadata.setServerProtocol("ICY"); //$NON-NLS-1$
				}
				else
				{
					metadata.setServerProtocol("HTTP"); //$NON-NLS-1$
				}
				
				if (!stationNameFound)
				{
					// URL als Namen setzen
					metadata.setStationName(url.toString());
				}
				
				if (contentTypeFound)
				{
					// Un黚liche Content-Types ersetzen
					String contentType = metadata.getContentType().toLowerCase();
					
					if (contentType.equals("video/x-nsv")) //$NON-NLS-1$
					{
						metadata.setContentType("video/nsv"); //$NON-NLS-1$
					}
					else if (contentType.equals("application/x-ogg") || contentType.equals("audio/x-vorbis")) //$NON-NLS-1$ //$NON-NLS-2$
					{
						metadata.setContentType("application/ogg"); //$NON-NLS-1$
					}
				}
				else
				{
					// Standard: MP3-Strom
					metadata.setContentType("audio/mpeg"); //$NON-NLS-1$
				}
							
				// Die Metadaten sind komplett
				
				// System.out.println(metadata);	
				
				// Socket usw. setzen
				this.socket = socket;
				this.inputStream = inputStream;
				this.outputStream = outputStream;	
				couldConnect = true;
				
				Logger.info("HttpSource", "HttpSource.STREAM_FOUND", url); //$NON-NLS-1$ //$NON-NLS-2$
				if (metadata.getContentType().equals("application/ogg"))
					PacketFactory.STREAM_PACKET_MAX_SIZE = PacketFactory.STREAM_PACKET_MAX_SIZE_TCP_OGG;
				return true;
			}
			else
			{
				// Es hat nicht geklappt...
				return false;
			}
			
		}
		catch (Exception e)
		{
			Logger.info("HttpSource", "HttpSource.COULD_NOT_CONNECT_TO_URL", url); //$NON-NLS-1$ //$NON-NLS-2$
			return false;
		}
		finally
		{
			if (!couldConnect)
			{
				// Alle Ressourcen wieder freigeben
				if (writer != null)
				{
					try
					{
						writer.close();
					}
					catch (IOException e)
					{
					}
				}
				
				if (inputStream != null)
				{
					try
					{
						inputStream.close();
					}
					catch (IOException e)
					{
					}
				}
				
				if (outputStream != null)
				{
					try
					{
						outputStream.close();
					}
					catch (IOException e)
					{
					}
				}
				
				if (socket != null)
				{
					try
					{
						socket.close();
					}
					catch (IOException e)
					{
					}
				}
			}
		}
	}

	private void serve()
	{
		buffer.setMetadata(metadata);
		try
		{
			if (metadata.getContentType().toLowerCase().equals("application/ogg")) //$NON-NLS-1$
			{
				serveOgg();
			}
			else
			{
				serveGeneric();
			}
		}
		catch (SocketTimeoutException e)
		{
			Logger.warning("HttpSource", "HttpSource.SOCKET_TIMEOUT"); //$NON-NLS-1$ //$NON-NLS-2$
		}
		catch (EOFException e)
		{
			Logger.warning("HttpSource", "HttpSource.STREAM_ENDED"); //$NON-NLS-1$ //$NON-NLS-2$)
		}
		catch (IOException e)
		{
			Logger.warning("HttpSource", "IO_ERROR", e); //$NON-NLS-1$ //$NON-NLS-2$
		}
		finally
		{
			isConnected = false;
			
			if (inputStream != null)
			{
				try
				{
					inputStream.close();
				}
				catch (IOException e)
				{
				}
			}
			
			if (outputStream != null)
			{
				try
				{
					outputStream.close();
				}
				catch (IOException e)
				{
				}
			}
			
			if (socket != null)
			{
				try
				{
					socket.close();
				}
				catch (IOException e)
				{
				}
			}			
		}
	}

	private void serveGeneric() throws IOException
	{		
		// Puffer f黵 die gelesenen Bytes
		byte[] readBytes = new byte[READ_BUFFER_SIZE];
				
		// Puffer f黵 die Shoutcast-Metadaten
		byte[] shoutcastMetadata = new byte[4080];

		//long nextDataSendTime = System.currentTimeMillis() + DATA_COLLECTION_INTERVAL;
		/*
		long time = System.currentTimeMillis();
		int total = 0;
		*/
		
		// Soviele Datenbytes m黶sen noch gelesen werden,
		// bis Shoutcast-Metadaten kommen
		int dataBytesLeft = metadataInterval;

		// (Das Timeout auch w鋒rend der
		//  Datenlieferungsphase beibehalten)

		while(true)
		{
			if (isICYStream && (dataBytesLeft == 0))
			{
				// Jetzt m黶sen die Metadaten gelesen werden
				int metadataLengthByte = inputStream.read();
		
				if (metadataLengthByte == -1)
				{
					throw new EOFException();
				}
				
				int metadataLength = metadataLengthByte * 16;
			
				if (metadataLength != 0)
				{
					// Die Metadaten komplett lesen
					inputStream.readFully(shoutcastMetadata, 0, metadataLength);
				
					// Die Metadaten konvertieren
					ShoutcastMetadata.shoutcastToMetadata(shoutcastMetadata, metadataLength, metadata);
				
					// Die neuen Metadaten sofort verschicken
					buffer.setMetadataSong(metadata);
				}
			
				// Jetzt kommen wieder Datenbytes
				dataBytesLeft = metadataInterval;
			}
		
			// Datenbytes lesen
			int readLength;
		
			if (isICYStream)
			{
				readLength = Math.min(readBytes.length, dataBytesLeft);
			}
			else
			{
				readLength = readBytes.length;
			}
			
			int count = inputStream.read(readBytes, 0, readLength);
			// total += count;
															
			if (count == -1)
			{
				// Der Strom ist zu Ende
				throw new EOFException();
			}
		
			if (isICYStream)
			{
				// Restliche Datenbytes berechnen
				dataBytesLeft -= count;
			}
			
			// Daten weiterschicken
			buffer.sendData(readBytes, count);
			
			// System.out.println(System.currentTimeMillis());
			// System.out.println(count);
		}
	}
	
	private void serveOgg() throws IOException
	{			
		try
		{	
			OggPage oggPage;
		
			while(true)
			{
				oggPage = new OggPage(inputStream);
				if (oggPage.isBeginOfLogicalBitstream())
				{
					byte[] oggHeader = OggStream.readVorbisHeader(oggPage, inputStream, metadata);
					
					buffer.setHeader(oggHeader);
					buffer.setMetadataSong(metadata);
				}
				else
				{
					buffer.sendData(oggPage.getPageData());
				}
			}
		}
		catch (OggException e)
		{
			Logger.warning("HttpSource", "HttpSource.OGG_ERROR", e); //$NON-NLS-1$ //$NON-NLS-2$
		}
	}

	/**
	 * Tries to connect to one of the Shoutcast/Icecast servers.
	 *
	 * @return <code>true</code>, if a connection to a Shoutcast/Icecast server
	 *         could be established, or <code>false</code>otherwise.
	 */
	public boolean connect()
	{
		isConnected = false;
		
		// Versuchen, eine Verbindung zu einem Shoutcast-Server herzustellen
		if (firstTry != null)
		{
			isConnected = connect(firstTry, 0);
			
			if (isConnected)
			{
				// firstTry in ein secondTry 黚erf黨ren
				// (Jetzt weiss man, dass es ein Strom ist)
				URL[] urls = new URL[1];
				urls[0] = firstTry;
				secondTry = urls;
			}
			
			if (!isConnected && !isICYStream)
			{
				secondTry = PlaylistParser.parse(firstTry);
			}
			
			// Das n鋍hste mal mit secondTry versuchen
			firstTry = null;
		}
		
		if (!isConnected && (secondTry != null))
		{
			for (int i=0; i < secondTry.length; i++)
			{
				isConnected = connect(secondTry[i], 0);
				if (isConnected)
				{
					break;
				}	
			}
		}
		
		return isConnected;
	}
	
	public void run()
	{
		Logger.finer("HttpSource", "HttpSource.THREAD_RUNNING"); //$NON-NLS-1$ //$NON-NLS-2$
		
		try
		{
			boolean wasConnected = false;
			long lastServeTime = 0;
				
			do
			{
				if (!isConnected)
				{
					connect();
				}
				
				if (isConnected)
				{
					wasConnected = true;
				}
				
				if (isConnected)
				{
					lastServeTime = System.currentTimeMillis();
					serve();
					
					if (System.currentTimeMillis() - lastServeTime < MINIMAL_SERVE_TIME)
					{
						// Der Server hat nicht lang genug durchgehalten
						// Jetzt ein bisschen warten
						
						Logger.info("HttpSource", "HttpSource.RECONNECT_IN_ONE_MINUTE"); //$NON-NLS-1$ //$NON-NLS-2$

						// Eine Minute warten und nochmals probieren
						Thread.sleep(RECONNECT_WAIT_TIME); 
					}
				}
				else
				{
					if (!wasConnected)
					{
						// Thread beenden
						Logger.info("HttpSource", "HttpSource.COULD_NOT_CONNECT_TO_SERVER"); //$NON-NLS-1$ //$NON-NLS-2$
						return;
					}
					
					Logger.info("HttpSource", "HttpSource.COULD_NOT_CONNECT_TO_SERVER"); //$NON-NLS-1$ //$NON-NLS-2$
					Logger.info("HttpSource", "HttpSource.RECONNECT_IN_ONE_MINUTE"); //$NON-NLS-1$ //$NON-NLS-2$
					
					// Eine Minute warten und nochmals probieren
					Thread.sleep(RECONNECT_WAIT_TIME);
				}
			} while (true);
		}
		catch (Exception e)
		{
			Logger.severe("HttpSource", "INTERNAL_ERROR", e); //$NON-NLS-1$ //$NON-NLS-2$
		}
	}
	
	
	// Beispiele f黵 die erste Zeile einer Antwort:
	// "HTTP/1.0 302 Found"
	// "ICY 200 OK"		
	private String getProtocol(String line)
	{
		int spacePos = line.indexOf(" "); //$NON-NLS-1$
		if (spacePos == -1)
		{
			return ""; //$NON-NLS-1$
		}
		
		int slashPos = line.indexOf("/"); //$NON-NLS-1$
		if (slashPos != -1)
		{
			return line.substring(0, slashPos);
		}
		else
		{
			return line.substring(0, spacePos);
		}		
	}

	private int getStatusCode(String line)
	{
		int spacePos = line.indexOf(" "); //$NON-NLS-1$
		
		if (spacePos == -1)
		{
			return -1;
		}
		
		int secondSpacePos = line.indexOf(" ", spacePos+1); //$NON-NLS-1$
		
		if (secondSpacePos == -1)
		{
			secondSpacePos = line.length();
		}
		
		try
		{
			String number = line.substring(spacePos+1, secondSpacePos);
			number = number.trim();
			return Integer.parseInt(number);
		}
		catch (NumberFormatException e)
		{
			return -1;
		}
	}
	public void setBroadcastBuffer(BroadcastBuffer buffer)
	{
		this.buffer = buffer;
	}
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?