/****************************************************************** * * CyberHTTP for Java * * Copyright (C) Satoshi Konno 2002-2004 * * File: HTTPSocket.java * * Revision; * * 12/12/02 - first revision. 03/11/04 - Added the following methods about chunk * size. setChunkSize(), getChunkSize(). 08/26/04 - Added a isOnlyHeader to * post(). 03/02/05 - Changed post() to suppot chunked stream. 06/10/05 - * Changed post() to add a Date headedr to the HTTPResponse before the posting. * 07/07/05 - Lee Peik Feng <pflee@users.sourceforge.net> - Fixed post() to * output the chunk size as a hex string. * ******************************************************************/ package com.guo.duoduo.airplayreceiver.http; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; import java.util.Calendar; public class HTTPSocket { //////////////////////////////////////////////// // Constructor //////////////////////////////////////////////// private Socket socket = null; private InputStream sockIn = null; private OutputStream sockOut = null; //////////////////////////////////////////////// // Socket //////////////////////////////////////////////// public HTTPSocket(Socket socket) { setSocket(socket); open(); } public HTTPSocket(HTTPSocket socket) { setSocket(socket.getSocket()); setInputStream(socket.getInputStream()); setOutputStream(socket.getOutputStream()); } public void finalize() { close(); } //////////////////////////////////////////////// // local address/port //////////////////////////////////////////////// public Socket getSocket() { return socket; } private void setSocket(Socket socket) { this.socket = socket; } //////////////////////////////////////////////// // in/out //////////////////////////////////////////////// public String getLocalAddress() { return getSocket().getLocalAddress().getHostAddress(); } public int getLocalPort() { return getSocket().getLocalPort(); } public InputStream getInputStream() { return sockIn; } private void setInputStream(InputStream in) { sockIn = in; } private OutputStream getOutputStream() { return sockOut; } private void setOutputStream(OutputStream out) { sockOut = out; } //////////////////////////////////////////////// // open/close //////////////////////////////////////////////// public boolean open() { Socket sock = getSocket(); try { sockIn = sock.getInputStream(); sockOut = sock.getOutputStream(); } catch (Exception e) { //TODO Add blacklistening of the UPnP Device return false; } return true; } public boolean close() { try { if (sockIn != null) sockIn.close(); if (sockOut != null) sockOut.close(); getSocket().close(); } catch (Exception e) { //Debug.warning(e); return false; } return true; } //////////////////////////////////////////////// // post //////////////////////////////////////////////// private boolean post(HTTPResponse httpRes, byte content[], long contentOffset, long contentLength, boolean isOnlyHeader) { //TODO Check for bad HTTP agents, this method may be list for IOInteruptedException and for blacklistening httpRes.setDate(Calendar.getInstance()); OutputStream out = getOutputStream(); try { httpRes.setContentLength(contentLength); out.write(httpRes.getHeader().getBytes()); out.write(HTTP.CRLF.getBytes()); if (isOnlyHeader == true) { out.flush(); return true; } boolean isChunkedResponse = httpRes.isChunked(); if (isChunkedResponse == true) { // Thanks for Lee Peik Feng <pflee@users.sourceforge.net> (07/07/05) String chunSizeBuf = Long.toHexString(contentLength); out.write(chunSizeBuf.getBytes()); out.write(HTTP.CRLF.getBytes()); } out.write(content, (int) contentOffset, (int) contentLength); if (isChunkedResponse == true) { out.write(HTTP.CRLF.getBytes()); out.write("0".getBytes()); out.write(HTTP.CRLF.getBytes()); } out.flush(); } catch (Exception e) { //Debug.warning(e); return false; } return true; } private boolean post(HTTPResponse httpRes, InputStream in, long contentOffset, long contentLength, boolean isOnlyHeader) { //TODO Check for bad HTTP agents, this method may be list for IOInteruptedException and for blacklistening httpRes.setDate(Calendar.getInstance()); OutputStream out = getOutputStream(); try { httpRes.setContentLength(contentLength); out.write(httpRes.getHeader().getBytes()); out.write(HTTP.CRLF.getBytes()); if (isOnlyHeader == true) { out.flush(); return true; } boolean isChunkedResponse = httpRes.isChunked(); if (0 < contentOffset) in.skip(contentOffset); int chunkSize = HTTP.getChunkSize(); byte readBuf[] = new byte[chunkSize]; long readCnt = 0; long readSize = (chunkSize < contentLength) ? chunkSize : contentLength; int readLen = in.read(readBuf, 0, (int) readSize); while (0 < readLen && readCnt < contentLength) { if (isChunkedResponse == true) { // Thanks for Lee Peik Feng <pflee@users.sourceforge.net> (07/07/05) String chunSizeBuf = Long.toHexString(readLen); out.write(chunSizeBuf.getBytes()); out.write(HTTP.CRLF.getBytes()); } out.write(readBuf, 0, readLen); if (isChunkedResponse == true) out.write(HTTP.CRLF.getBytes()); readCnt += readLen; readSize = (chunkSize < (contentLength - readCnt)) ? chunkSize : (contentLength - readCnt); readLen = in.read(readBuf, 0, (int) readSize); } if (isChunkedResponse == true) { out.write("0".getBytes()); out.write(HTTP.CRLF.getBytes()); } out.flush(); } catch (Exception e) { //Debug.warning(e); return false; } return true; } public boolean post(HTTPResponse httpRes, long contentOffset, long contentLength, boolean isOnlyHeader) { //TODO Close if Connection != keep-alive if (httpRes.hasContentInputStream() == true) return post(httpRes, httpRes.getContentInputStream(), contentOffset, contentLength, isOnlyHeader); return post(httpRes, httpRes.getContent(), contentOffset, contentLength, isOnlyHeader); } }