// line CRLF
if (message == null) {
return null;
}
if (cnt < limit && !message.isHeadersComplete()) {
Header header = null;
int quoteCnt = 0;
boolean startToken = true;
int position = bb.position();
boolean incrCnt; // Whether the cnt should be incremented when continuing for loop
for (; cnt < limit;) {
incrCnt = true; // Default is increment, reset every time.
if (bs[cnt] == ':' && header == null) {
if (cnt - position < 1) {
// Line starts with colon. Do not accept
theirLog.severe("Line starts with colon, unacceptable");
if (errorHandler != null) {
errorHandler.handleError(((SipServletRequestImpl) (message)), 400, "Malformed header");
}
return null;
}
header = Header.create(bs, position, (cnt - position), message);
position = cnt + 1;
startToken = true;
} else if (startToken && (bs[cnt] == ' ' || bs[cnt] == '\t')) {
position = cnt + 1;
} else if (bs[cnt] == '"') {
quoteCnt++;
} else if (bs[cnt] == ',' && quoteCnt % 2 == 0 && header != null) { // multi header on one line
// header.setInLineValues(true);
// Must check if Date header
if (!Header.isSingleLineHeader(header) && !((cnt - position) == 3 && cnt + 1 < limit && bs[cnt + 1] == ' ')) {
// TODO - Should we throw a parse exception if in single
// line
// header map?
// This will have an impact on performance so it has to
// be
// measured.
// Eg trap Unsupported op ex and generate parse ex.
try {
header.setValue(
new String(bs, position, (cnt - position), SipFactoryImpl.SIP_CHARSET),
false);
} catch (UnsupportedEncodingException e) {
throw new ParserException("Failed setting header value", e);
}
header.setIsNextValueOnSameLine(true, false);
position = ++cnt;
// Trim WS
while (cnt < limit && bs[cnt] == ' ') {
position = ++cnt;
}
if (Header.isSingleLineHeader(header) && theirLog.isLoggable(Level.FINER)) {
theirLog.log(Level.FINER, "SingleLineHeader " + header.getName() + " is parsed as multiline header with a separator \',\' ");
if (theirLog.isLoggable(Level.FINEST)) {
theirLog.log(Level.FINEST, "The SingleLineHeader value : " + header.getValue() + " will be overwritten!");
}
}
}
} else if ((cnt + 1) < limit && bs[cnt] == '\r' && bs[cnt + 1] == '\n') {
if (header == null) {
message.setHeadersComplete(true);
cnt += 2;
// MARK
bb.position((cnt > limit) ? limit : cnt);
break;
} else if (cnt + 3 < limit && bs[cnt + 2] == '\r' && bs[cnt + 3] == '\n') {
// The rest is body
try {
header.setValue(
new String(bs, position, (cnt - position), SipFactoryImpl.SIP_CHARSET),
false);
} catch (UnsupportedEncodingException e) {
throw new ParserException("Failed setting header value", e);
}
header.setIsNextValueOnSameLine(false, false);
message.addHeader(header);
message.setHeadersComplete(true);
cnt += 4;
// MARK
bb.position((cnt > limit) ? limit : cnt);
if (theirLog.isLoggable(Level.FINE)) {
if (Header.isSingleLineHeader(header)) {
theirLog.log(Level.FINE, "Adding Header " + header.getName() + " = " + header.getValue() + " (" + bb.position() + ')');
} else {
ListIterator<String> li = header.getValues();
int x = 0;
while (li.hasNext()) {
theirLog.log(Level.FINE, "Adding Header " + header.getName() + " = " + li.next() + " (" + bb.position() + ')' + '<' + (++x) + '>');
}
}
}
break;
} else if (cnt + 2 < limit && (bs[cnt + 2] == ' ' || bs[cnt + 2] == '\t')) {
// Append String - multi line header
bs[cnt] = ' ';
bs[cnt + 1] = ' ';
bs[cnt + 2] = ' ';
cnt += 3;
} else {
try {
header.setValue(
new String(bs, position, (cnt - position), SipFactoryImpl.SIP_CHARSET),
false);
} catch (UnsupportedEncodingException e) {
throw new ParserException("Failed setting header value", e);
}
header.setIsNextValueOnSameLine(false, false);
message.addHeader(header);
cnt += 2;
// MARK
bb.position((cnt > limit) ? limit : cnt);
if (theirLog.isLoggable(Level.FINE)) {
if (Header.isSingleLineHeader(header)) {
theirLog.log(Level.FINE, "Adding Header " + header.getName() + " = " + header.getValue() + " (" + bb.position() + ')');
} else {
ListIterator<String> li = header.getValues();
int x = 0;
while (li.hasNext()) {
theirLog.log(Level.FINE, "Adding Header " + header.getName() + " = " + li.next() + " (" + bb.position() + ')' + '<' + (++x) + '>');
}
}
}
header = null;
quoteCnt = 0;
startToken = true;
// Don't increment as we have already stepped forward.
incrCnt = false;
}
position = cnt;
} else if (startToken) {
startToken = false;
}
// Do the increment if we should.
if (incrCnt) {
cnt++;
}
}
}
if (message.isHeadersComplete() && !message.isMessageComplete()) {
String errorStr = null;
Header header = message.getRawHeader(Header.CALL_ID);
if (header == null || header.getValue() == null || header.getValue().length() == 0) {
errorStr = "Failed to validate mandatory header CallId";
}
header = message.getRawHeader(Header.TO);
if (header == null || header.getValue() == null || header.getValue().length() == 0) {
errorStr = "Failed to validate mandatory header To";
}
header = message.getRawHeader(Header.FROM);
if (header == null || header.getValue() == null || header.getValue().length() == 0) {
errorStr = "Failed to validate mandatory header From";
}
header = message.getRawHeader(Header.CSEQ);
if (header == null || header.getValue() == null || header.getValue().length() == 0) {
errorStr = "Failed to validate mandatory header Cseq";
}
header = message.getRawHeader(Header.VIA);
if (header == null || header.getValue() == null || header.getValue().length() == 0) {
errorStr = "Failed to validate mandatory header Via";
}
header = message.getRawHeader(Header.MAX_FORWARDS);
if ((header == null || header.getValue() == null) && message instanceof SipServletRequestImpl) {
Header mf = Header.createFormated(Header.MAX_FORWARDS, message);
mf.setValue("70", false);
message.setHeader(mf);
if (theirLog.isLoggable(Level.FINER)) {
theirLog.log(Level.FINER, "Added Max-Forwards = " + 70);
}
}