String location = res.getHeader("Location");
String xrange = res.getHeader("X-Range");
if (!StringHelper.isEmptyString(location)
&& !StringHelper.isEmptyString(xrange))
{
HTTPRequestEvent freq = cloneRequest(req);
freq.url = location;
freq.setHeader("X-Snova-HCE", "1");
freq.setHeader("Range", xrange);
cb.writeHttpReq(freq);
return true;
}
}
switch (rangeState)
{
case STATE_WAIT_NORMAL_RES:
{
cb.onHttpResponse(res);
return true;
}
case STATE_WAIT_HEAD_RES:
{
if (res.statusCode != 206)
{
cb.onHttpResponse(res);
return true;
}
this.res = res;
String contentRangeHeader = res.getHeader("Content-Range");
int length = res.content.readableBytes();
if (!StringHelper.isEmptyString(contentRangeHeader))
{
ContentRangeHeaderValue v = new ContentRangeHeaderValue(
contentRangeHeader);
length = (int) v.getInstanceLength();
}
if (this.contentEnd == -1)
{
this.contentEnd = length - 1;
}
if (null != originRangeHader)
{
res.statusCode = 206;
res.setHeader("Content-Range", String.format(
"bytes %d-%d/%d", this.contentBegin,
this.contentEnd, length));
}
else
{
res.statusCode = 200;
res.removeHeader("Content-Range");
}
res.setHeader("Content-Length", ""
+ (this.contentEnd - this.contentBegin + 1));
int n = res.content.readableBytes();
this.expectedRangePos += n;
this.rangePos += n;
cb.onHttpResponse(res);
rangeState = STATE_WAIT_RANGE_GET_RES;
break;
}
case STATE_WAIT_RANGE_GET_RES:
{
if (res.statusCode != 206)
{
logger.error("Expected 206 response, but got "
+ res.statusCode);
if(res.getHeader("X-Range") != null)
{
fetchWorkerNum = 1;
final HTTPRequestEvent freq = cloneRequest(req);
freq.setHeader("Range", res.getHeader("X-Range"));
SharedObjectHelper.getGlobalTimer().schedule(new Runnable()
{
public void run()
{
cb.writeHttpReq(freq);
}
}, 1, TimeUnit.SECONDS);
return true;
}
return false;
}
rangeWorker.decrementAndGet();
String contentRangeHeader = res.getHeader("Content-Range");
ContentRangeHeaderValue v = new ContentRangeHeaderValue(
contentRangeHeader);
logger.info(String.format("Session[%d]Recv range chunk:%s",
this.sessionID, contentRangeHeader));
chunks.put((int) v.getFirstBytePos(), res.content);
while (chunks.containsKey(expectedRangePos))
{
Buffer chunk = chunks.remove(expectedRangePos);
expectedRangePos += chunk.readableBytes();
cb.onRangeChunk(chunk);
}
if (expectedRangePos < this.contentEnd)
{
logger.info(String.format(
"Session[%d]Expect range chunk:%d", this.sessionID,
this.expectedRangePos));
}
else
{
logger.info(String.format(
"Session[%d]Range task finished.", this.sessionID));
}
break;
}
default:
{
return false;
}
}
while (!this.closed
&& this.res.statusCode < 300
&& rangeWorker.get() < fetchWorkerNum
&& rangePos < contentEnd
&& (rangePos - expectedRangePos) < fetchLimit * fetchWorkerNum
* 2)
{
synchronized (this)
{
int begin = this.rangePos;
int end = this.rangePos + fetchLimit - 1;
if (end > this.contentEnd)
{
end = this.contentEnd;
}
this.rangePos = end + 1;
rangeWorker.incrementAndGet();
String rangeHeader = "bytes=" + begin + "-" + end;
logger.info(String.format("Session[%d]Fetch range:%s",
this.sessionID, rangeHeader));
HTTPRequestEvent freq = cloneRequest(req);
freq.setHeader("Range", rangeHeader);
freq.setHeader("X-Snova-HCE", "1");
cb.writeHttpReq(freq);
}
}
return true;
}