package com.bigdo.service;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.URLConnection;
import java.util.ArrayList;
import com.bigdo.common.BDSQLiteHelper;
import com.bigdo.common.RConfig;
import com.bigdo.common.RState;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
public class WebServer extends Thread {
int port = 0;
ServerSocket serverSocket = null;
boolean isLoop = false;
VideoPayService PayService;
String baseDir = "";
public WebServer(VideoPayService PayService) {
super();
BDSQLiteHelper sqlobj = null;
this.PayService = PayService;
}
@Override
public void run() {
super.run();
String status = Environment.getExternalStorageState();
if (status.equals(Environment.MEDIA_MOUNTED)) {
baseDir = Environment.getExternalStorageDirectory()
+ RConfig.Video_Dir;
startService();
}
}
public void startService() {
BDSQLiteHelper sqlobj = null;
while (!this.isInterrupted() && serverSocket == null) {
try {
this.port = 0;
isLoop = false;
int port = 57030;
try {
// 创建服务器套接字
serverSocket = new ServerSocket(port);
} catch (Exception e) {
try {
if (serverSocket != null) {
serverSocket.close();
}
} catch (Exception e1) {
}
serverSocket = null;
port = 0;
sendStatusMsg(RState.Video_Status_Init_Error);
continue;
}
this.port = 0;
if (serverSocket != null) {
try {
this.port = serverSocket.getLocalPort();
} catch (Exception e) {
this.port = 0;
}
}
isLoop = true;
sendStatusMsg(RState.Video_Status_Run);
while (isLoop && !this.isInterrupted()) {
// 接收客户端套接字
Socket socket = serverSocket.accept();
RecvThread t = new RecvThread(socket);
// t.setDaemon(true);// 设为守护线程
t.start();
}
} catch (Exception e) {
isLoop = false;
sendStatusMsg(RState.Video_Status_Close);
} finally {
try {
if (serverSocket != null) {
serverSocket.close();
}
} catch (IOException e) {
}
serverSocket = null;
}
}
sendStatusMsg(RState.Video_Status_Run);
}
public void sendStatusMsg() {
int port = 0;
if (serverSocket != null) {
try {
port = serverSocket.getLocalPort();
} catch (Exception e) {
}
}
Bundle data = new Bundle();
data.putInt("status", isLoop ? RState.Video_Status_Run
: RState.Video_Status_Unknown);
data.putInt("prot", port);
PayService.sendBroadcastMsg(RState.Video_Status_Info, "服务状态", data);
}
public void sendStatusMsg(int status) {
int port = 0;
if (serverSocket != null) {
try {
port = serverSocket.getLocalPort();
} catch (Exception e) {
}
}
Bundle data = new Bundle();
data.putInt("status", status);
data.putInt("prot", port);
PayService.sendBroadcastMsg(RState.Video_Status_Info, "服务状态", data);
}
public void stopService() {
isLoop = false;
try {
if (serverSocket != null) {
serverSocket.close();
}
} catch (Exception e) {
}
serverSocket = null;
interrupt();
sendStatusMsg(RState.Video_Status_Close);
}
private class RecvThread extends Thread {
Socket socket;
public RecvThread(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
super.run();
handler();
}
private void handler() {
BDSQLiteHelper sqlobj = null;
if (socket != null) {
InputStream in = null;
try {
byte[] data = new byte[1024 * 4];
int rc = 0;
StringBuffer r_sb = new StringBuffer();
in = socket.getInputStream();
while (!this.isInterrupted()
&& (socket != null
&& (!socket.isClosed() && socket
.isConnected()) && (rc = in
.read(data)) != -1)) {
if (rc > 0) {
r_sb.append(new String(data, 0, rc, "UTF-8"));
ArrayList<String> rs_item = analysisHttp(r_sb);
String con = "close";
for (int i = 0; i < rs_item.size(); i++) {
HttpEntity entity = analysisHttpEntity(rs_item
.get(i));
if (entity != null) {
con = entity.con;
outFile(entity);
}
}
if ("close".equals(con)) {
closeSocket();
data = null;
break;
}
}
}
} catch (Exception e) {
// Log.e("entity_error", e.getMessage());
} finally {
try {
if (in != null) {
in.close();
}
} catch (Exception e) {
}
closeSocket();
}
}
}
private void closeSocket() {
try {
if (socket != null) {
socket.shutdownInput();
socket.shutdownOutput();
socket.close();
}
} catch (Exception e) {
}
socket = null;
interrupt();
}
private void outFile(HttpEntity entity) {
BDSQLiteHelper sqlobj = null;
if (socket != null) {
OutputStream out = null;
try {
out = socket.getOutputStream();
} catch (IOException e4) {
}
if (out != null) {
String e = "\r\n";
if (entity != null && entity.File != null
&& !entity.File.equals("")) {
try {
// String path = "/sdcard/1.mp4";
File fd = new File(baseDir);
Log.e("out-file", baseDir + entity.File + ".r");
File f = new File(fd, entity.File + ".r");
int size = 0;
if (f.exists()) {
FileInputStream in = null;
try {
long flg = f.length();
in = new FileInputStream(f);
String http_code = "206 Partial Content";
if (entity.Range_e <= 0) {
entity.Range_e = flg;
}
long rlg = (entity.Range_e - entity.Range_s);
if (entity.Range_s == 0) {
http_code = "200 OK";
rlg = flg;
}
StringBuilder header = new StringBuilder();
header.append(("HTTP/1.1 " + http_code + e));
header.append(("Connection: close" + e));
// header.append(("Content-Type: video/mp4"
// + e));
String contentType = VideoMime.Mime(f
.getName());
header.append(("Content-Type: "
+ contentType + e));
Log.e("Content-Type" + contentType, "");
header.append(("Accept-Ranges: bytes" + e));
if (entity.Range_s > 0) {
header.append(("Content-Range: bytes "
+ entity.Range_s + "-"
+ entity.Range_e + "/" + flg + e));
}
header.append(("Content-Length: " + rlg + e + e));
in.skip(entity.Range_s + 180);
out.write(header.toString().getBytes());
header.delete(0, header.length());
int t_read_count = 0;
int blg = 1024 * 4;
if (rlg < blg) {
blg = (int) rlg;
}
byte[] buffer = new byte[blg];
while ((!socket.isClosed() && socket
.isConnected())
&& (size = in.read(buffer)) != -1) {
t_read_count += size;
out.write(buffer, 0, size);
out.flush();
if (t_read_count >= rlg) {
break;
}
}
} catch (Exception e1) {
// Log.e("outf",
// "error-rFile: " + e1.getMessage(), e1);
} finally {
try {
if (in != null) {
in.close();
}
} catch (Exception e2) {
}
in = null;
}
}
} catch (Exception e3) {
}
}
}
}
}
};
private class HttpEntity {
public String File = "";
public long Range_s = 0;
public long Range_e = 0;
public String con = "";
}
private ArrayList<String> analysisHttp(StringBuffer sb) {
BDSQLiteHelper sqlobj = null;
ArrayList<String> rs_item = new ArrayList<String>();
int lg = sb.length();
String el = "\r\n";
String http1_1 = " HTTP/1.1" + el, http1_0 = " HTTP/1.0" + el;
while (lg > 0) {
if (lg > 0) {
int s = sb.indexOf("GET ");
if (s < 0) {
sb.delete(0, lg);
return rs_item;
}
int http_s = sb.indexOf(http1_1);
if (http_s < 0) {
http_s = sb.indexOf(http1_0);
}
int es = sb.indexOf(el);
if (http_s > s && http_s + http1_1.length() == es + el.length()) {
int s_n = sb.indexOf(el + el + "GET ", es);
if (s_n < es) {
s_n = lg;
}
rs_item.add(sb.substring(s, s_n));
sb.delete(s, s_n);
} else {
return rs_item;
}
lg = sb.length();
}
}
return rs_item;
}
private HttpEntity analysisHttpEntity(final String src) {
BDSQLiteHelper sqlobj = null;
HttpEntity entity = new HttpEntity();
if (src != null && !src.equals("")) {
String el = "\r\n", get = "GET ";
String http1_1 = " HTTP/1.1" + el, http1_0 = " HTTP/1.0" + el;
int s = src.indexOf(get) + get.length(), e = src.indexOf(http1_1);
if (e < 0) {
e = src.indexOf(http1_0, s);
}
if (e > 0) {
entity.File = src.substring(s, e);
}
String Range = "Range: bytes=";
s = src.indexOf(Range, e + http1_1.length());
if (s > 0) {
s += Range.length();
e = src.indexOf(el, s);
if (e > 0) {
String Range_s_e = src.substring(s, e);
if (Range_s_e != null && !Range_s_e.equals("")) {
String[] r_s_to_e = Range_s_e.split("[\\-]");
if (r_s_to_e != null && r_s_to_e.length > 0) {
if (r_s_to_e[0] != null && !r_s_to_e[0].equals("")) {
entity.Range_s = Integer.parseInt(r_s_to_e[0]);
}
if (r_s_to_e.length > 1 && r_s_to_e[1] != null
&& !r_s_to_e[1].equals("")) {
entity.Range_e = Integer.parseInt(r_s_to_e[1]);
}
}
}
}
}
String con = "Connection: ";
s = src.indexOf(con);
if (s > 0) {
s += con.length();
e = src.indexOf(el, s);
if (e > 0) {
entity.con = src.substring(s, e);
}
}
}
// if (entity.Range_e < entity.Range_s) {
// entity.Range_e += entity.Range_s + 1024 * 1024 * 1;
// }
return entity;
}
}