Hi,
I have ported your code on a standalone class to test it :
import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.apache.mina.common.ByteBuffer;
import org.apache.mina.common.IoSession;
import org.apache.mina.filter.codec.demux.MessageDecoderResult;
public class FSResponseDecoder {
private static final byte[] CONTENT_LENGTH = new
String("Content-Length:").getBytes();
private CharsetDecoder decoder = Charset.defaultCharset().newDecoder();
public FSResponseDecoder() {
}
synchronized public MessageDecoderResult decodable(IoSession
session, ByteBuffer in) {
try {
return messageComplete(in) ? MessageDecoderResult.OK
: MessageDecoderResult.NEED_DATA;
} catch (Exception ex) {
ex.printStackTrace();
}
return MessageDecoderResult.NOT_OK;
}
public MessageDecoderResult decode(IoSession session, ByteBuffer in)
throws Exception {
// Try to decode body
System.out.println("[[[[[ Decode function on session "+session);
decodeBody(in);
System.out.println("]]]]] Finish decode function on session
"+session);
return MessageDecoderResult.OK;
}
private String getBufferString(ByteBuffer in) {
int size = in.remaining();
if (size == 0) {
return "empty";
}
StringBuffer out = new StringBuffer(size);
while(in.hasRemaining()) {
out.append((char) in.get());
}
in.flip();
return out.toString();
}
private int getEndOfHeader(ByteBuffer in,int last) {
int eoh = -1;
for (int i = 0; i < last; i++) {
if (in.get(i) == (byte) 0x0A && in.get(i + 1) == (byte) 0x0A) {
eoh = i + 1;
break;
}
}
return eoh;
}
private boolean messageComplete(ByteBuffer in) throws Exception {
int sizeToRead = 0;
int last = in.remaining() - 1;
System.out.println("***** New Buffer to analyze *****");
String str = getBufferString(in); // in.getHexDump();
System.out.println("Buffer Dump\n"+str);
int eoh = getEndOfHeader(in, last);
if (eoh == -1)
return false;
if (in.get(0) == (byte) 'C' && in.get(1) == (byte) 'o' &&
in.get(2) == (byte) 'n' &&
in.get(3) == (byte) 't' && in.get(4) == (byte) 'e' &&
in.get(5) == (byte) 'n' &&
in.get(6) == (byte) 't' && in.get(7) == (byte) '-' &&
in.get(8) == (byte) 'L' &&
in.get(9) == (byte) 'e' && in.get(10) == (byte) 'n' &&
in.get(11) == (byte) 'g' &&
in.get(12) == (byte) 't' && in.get(13) == (byte) 'h')
{
int contentLength = getContentLength(in, last);
boolean result;
if (contentLength>0) {
result = contentLength + eoh <= in.remaining();
sizeToRead = contentLength + (eoh+1);
System.out.println("content_length["+contentLength+"]
eoh["+eoh+"] == in.remaining["+in.remaining()+"] ==> "+result);
if (result)
System.out.println("sizeToRead is >>>> "+sizeToRead);
}
else
result = false;
return (result);
}
sizeToRead = eoh+1;
System.out.println("sizeToRead is >>>> "+sizeToRead);
return true;
}
private int getContentLength(ByteBuffer in, int last) {
String str = getBufferString(in); // in.getHexDump();
System.out.println("last = "+last);
System.out.println("***** Buffer in getContentLength 1
*****\n"+str);
for (int i = 0; i < last; i++) {
boolean found = false;
for (int j = 0; j < CONTENT_LENGTH.length; j++) {
if (in.get(i + j) != CONTENT_LENGTH[j]) {
found = false;
break;
}
found = true;
}
if (found) {
// retrieve value from this position till next 0x0D 0x0A
System.out.println("Found content-length index at "+i);
StringBuilder contentLength = new StringBuilder();
for (int j = i + CONTENT_LENGTH.length; j < last; j++) {
if (in.get(j) == 0x0A)
break;
contentLength.append(new String( new byte[] { in.get(j)
}));
System.out.println("["+new String( new byte[]
{in.get(j)})+"]");
}
// if content-length worth of data has been received
then the message is complete
str = getBufferString(in); // in.getHexDump();
System.out.println("***** Buffer in getContentLength
2*****\n"+str);
System.out.println("ContentLength = "+contentLength);
System.out.println("total buffer length = "+in.remaining());
return Integer.parseInt(contentLength.toString().trim());
}
}
return -1;
}
private void decodeBody(ByteBuffer in) {
try {
int sizeToRead = 0;
int last = in.remaining() - 1;
int eoh = getEndOfHeader(in, last);
if (in.get(0) == (byte) 'C' && in.get(1) == (byte) 'o' &&
in.get(2) == (byte) 'n' &&
in.get(3) == (byte) 't' && in.get(4) == (byte) 'e'
&& in.get(5) == (byte) 'n' &&
in.get(6) == (byte) 't' && in.get(7) == (byte) '-'
&& in.get(8) == (byte) 'L' &&
in.get(9) == (byte) 'e' && in.get(10) == (byte) 'n'
&& in.get(11) == (byte) 'g' &&
in.get(12) == (byte) 't' && in.get(13) == (byte)
'h')
{
int contentLength = getContentLength(in, last);
sizeToRead = contentLength + (eoh+1);
}
else
sizeToRead = eoh+1;
System.out.println("Parsing request with sizeToRead =
"+sizeToRead);
parseRequest(new StringReader(in.getString(sizeToRead,
decoder)));
} catch (CharacterCodingException ex) {
ex.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void parseRequest(Reader is) {
BufferedReader rdr = new BufferedReader(is);
Map<String, String> response = new HashMap<String,String>();
try {
// Get request URL.
String line;
// Read header
System.out.println("Reading parameters:");
while ((line = rdr.readLine()) != null && line.length() > 0) {
String[] tokens = line.split(": ");
response.put(tokens[0], tokens[1] );
System.out.println(tokens[0]+": "+tokens[1]);
}
// determine content-type of this response
String contentType = response.get("Content-Type");
// If method 'POST' then read Content-Length worth of data
if (contentType.equalsIgnoreCase("text/event-xml") ||
contentType.equalsIgnoreCase("text/event-plain")) {
int len = Integer.parseInt(response.get("Content-Length"));
char[] buf = new char[len];
if (rdr.read(buf) == len) {
line = String.copyValueOf(buf);
}
String str = line;
response.put("Event-Data", str);
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
public static void main(String[] args) throws Exception
{
FSResponseDecoder decoder = new FSResponseDecoder();
String str =
"Content-Length: 1619\n"+
"Content-Type: text/event-plain\n"+
"\n"+
"Channel-State: CS_NEW\n"+
"Channel-State-Number: 0\n"+
"Channel-Name: sofia/external/nobody%40192.168.3.12\n"+
"Unique-ID: fd2229c0-2d6c-11dd-9acd-0b28d09a52aa\n"+
"Call-Direction: inbound\n"+
"Answer-State: ringing\n"+
"variable_sip_from_user: nobody\n"+
"variable_sip_from_uri: nobody%40192.168.3.12\n"+
"variable_sip_from_host: 192.168.3.12\n"+
"variable_sip_from_tag: 02H917ryecvgp\n"+
"variable_sofia_profile_name: external\n"+
"variable_sofia_profile_domain_name: external\n"+
"variable_sip_req_user: 6001\n"+
"variable_sip_req_port: 5080\n"+
"variable_sip_req_uri: 6001%40192.168.3.11%3A5080\n"+
"variable_sip_req_host: 192.168.3.11\n"+
"variable_sip_to_user: 6001\n"+
"variable_sip_to_port: 5080\n"+
"variable_sip_to_uri: 6001%40192.168.3.11%3A5080\n"+
"variable_sip_to_host: 192.168.3.11\n"+
"variable_sip_contact_user: mod_sofia\n"+
"variable_sip_contact_port: 5060\n"+
"variable_sip_contact_uri: mod_sofia%40192.168.3.12%3A5060\n"+
"variable_sip_contact_host: 192.168.3.12\n"+
"variable_channel_name: sofia/external/nobody%40192.168.3.12\n"+
"variable_endpoint_disposition: INBOUND%20CALL\n"+
"variable_sip_call_id: 824f7531-a82e-122b-8485-000f1f644b48\n"+
"variable_sip_user_agent: FreeSWITCH-mod_sofia/1.0.pre4-8539\n"+
"variable_sip_via_host: 192.168.3.12\n"+
"variable_sip_via_rport: 5060\n"+
"variable_max_forwards: 70\n"+
"Event-Name: CHANNEL_CREATE\n"+
"Core-UUID: ed9888ba-2c94-11dd-";
int capacity = str.getBytes().length;
ByteBuffer bb = ByteBuffer.allocate( capacity );
bb.put( str.getBytes() );
decoder.decode( null, bb );
}
}
Here are the logs :
[[[[[ Decode function on session null
last = 752
***** Buffer in getContentLength 1 *****
seems correct. Can you test it ?
--
--
cordialement, regards,
Emmanuel Lécharny
www.iktek.com
directory.apache.org