package it.yup.xmpp; import org.bouncycastle.util.encoders.Base64; //#mdebug //@ //@import it.yup.util.Logger; //@ // #enddebug import it.yup.util.Utils; import it.yup.xml.Element; import it.yup.xmlstream.BasicXmlStream; import it.yup.xmlstream.EventQuery; import it.yup.xmlstream.EventQueryRegistration; import it.yup.xmlstream.PacketListener; import it.yup.xmpp.packets.Iq; import it.yup.xmpp.packets.Stanza; public class FTReceiver implements PacketListener { /* * The xmpp client */ private XMPPClient xmppClient = XMPPClient.getInstance(); /* * A file transfer receiver event handler */ private FTREventHandler eh; public interface FTREventHandler { public void dataReceived(byte[] data, String fileName,String fileDesc, OpenListener ftrp); public void reqFT(String contactName, OpenListener ftrp); public void chunkReceived(int length, int fileSize, OpenListener openListener); } public class OpenListener implements PacketListener { public Element e_jingle; private int block_size = 4096; //private StringBuffer encodedData= new StringBuffer(block_size); private StringBuffer encodedData = new StringBuffer(); private byte[] decodedData; private EventQueryRegistration dataListenerEq; // the file size public int fileSize; // the file size public String fileName; public String fileDesc=""; public void answerFT( boolean accept) { // If accept send a correct reply and register a listener // to open the jingle stream if (accept) { this.acceptSession(); } else { Iq reply = new Iq(this.e_jingle.getAttribute(Iq.ATT_FROM),Iq.T_SET); Element jingle = reply.addElement(XMPPClient.JINGLE, FTSender.JINGLE); jingle.setAttribute(FTSender.ACTION, FTSender.SESSION_TERMINATE); jingle.addElement(null, FTSender.DECLINE); xmppClient.sendPacket(reply); } } public void packetReceived(Element e) { PacketListener dataListener = new PacketListener() { public void packetReceived(Element e) { try { String chunkData = e .getChildByName(null, FTSender.DATA).getText(); Iq replIq = new Iq(e.getAttribute(Iq.ATT_FROM), Iq.T_RESULT); replIq.setAttribute(Iq.ATT_ID, e .getAttribute(Iq.ATT_ID)); xmppClient.sendPacket(replIq); encodedData.append(chunkData); // the data is base64 encoded eh.chunkReceived ((encodedData.length()*3)/4,fileSize,OpenListener.this); } catch (Exception ex) { // #mdebug //@ ex.printStackTrace(); //@ Logger.log("In receiving an IBB packet" //@ + ex.getClass().getName() + "\n" //@ + ex.getMessage()); // #enddebug } } }; PacketListener closeListener = new PacketListener() { public void packetReceived(Element e) { try { BasicXmlStream.removeEventListener(dataListenerEq); Iq reply = Utils.easyReply(e); xmppClient.sendPacket(reply); Iq closeSession = new Iq(e.getAttribute(Iq.ATT_FROM), Iq.T_SET); Element jingleClose = closeSession.addElement( XMPPClient.JINGLE, FTSender.JINGLE); jingleClose.setAttribute(FTSender.ACTION, FTSender.SESSION_TERMINATE); jingleClose.setAttribute(FTSender.SID, e_jingle.getChildByName(null, FTSender.JINGLE) .getAttribute(FTSender.SID)); jingleClose.addElement(null, "reason").addElement(null, "success"); xmppClient.sendPacket(closeSession); String decString = encodedData.toString(); decodedData = Base64.decode(decString); // #mdebug //@ Logger.log("File received kb: " + decodedData.length); //@ // System.out.println(decString); // #enddebug eh.dataReceived(decodedData, fileName,fileDesc, OpenListener.this); } catch (Exception ex) { // #mdebug //@ ex.printStackTrace(); //@ Logger.log("In closing session" //@ + ex.getClass().getName() + "\n" //@ + ex.getMessage()); // #enddebug } } }; //this.encodedData.setLength(fileSize*2); EventQuery eq = new EventQuery(Iq.IQ, new String[] { Iq.ATT_FROM, Iq.ATT_TYPE }, new String[] { e.getAttribute(Iq.ATT_FROM), Iq.T_SET }); Element openElement = e.getChildByName(null, FTSender.OPEN); eq.child = new EventQuery(FTSender.DATA, new String[] { FTSender.SID, "xmlns" }, new String[] { openElement.getAttribute(FTSender.SID), XMPPClient.NS_IBB }); this.dataListenerEq = BasicXmlStream.addEventListener(eq, dataListener); eq = new EventQuery(Iq.IQ, new String[] { Iq.ATT_FROM, Iq.ATT_TYPE }, new String[] { e.getAttribute(Iq.ATT_FROM), Iq.T_SET }); eq.child = new EventQuery(FTSender.CLOSE, new String[] { FTSender.SID, "xmlns" }, new String[] { openElement.getAttribute(FTSender.SID), XMPPClient.NS_IBB }); BasicXmlStream.addOnetimeEventListener(eq, closeListener); block_size = Integer.parseInt(openElement .getAttribute(FTSender.BLOCK_SIZE)); Stanza reply = new Iq(e.getAttribute(Iq.ATT_FROM), Iq.T_RESULT); reply.setAttribute(Iq.ATT_ID, e.getAttribute(Iq.ATT_ID)); xmppClient.sendPacket(reply); } private void acceptSession() { Element e = this.e_jingle; Element session_accept = new Iq(e.getAttribute(Iq.ATT_FROM), Iq.T_SET); Element jingle = this.e_jingle .getChildByName(null, FTSender.JINGLE); jingle.setAttribute(FTSender.ACTION, FTSender.SESSION_ACCEPT); session_accept.addElement(jingle); xmppClient.sendPacket(session_accept); } }; public FTReceiver(FTREventHandler eh) { this.eh = eh; EventQuery eq = new EventQuery(Iq.IQ, new String[] { Iq.ATT_TYPE }, new String[] { Iq.T_SET }); eq.child = new EventQuery(FTSender.JINGLE, new String[] { "xmlns", FTSender.ACTION }, new String[] { XMPPClient.JINGLE, FTSender.SESSION_INITIATE }); BasicXmlStream.addEventListener(eq, this); } public void packetReceived(Element e) { // file transfer receive protocol OpenListener ftrp = new OpenListener(); ftrp.e_jingle = e; Element fileNode = e.getChildByName(null, FTSender.JINGLE) .getChildByName(null, FTSender.CONTENT).getChildByName(null, FTSender.DESCRIPTION).getChildByName(null, FTSender.OFFER).getChildByName(null, FTSender.FILE); ftrp.fileSize = Integer.parseInt(fileNode.getAttribute(FTSender.SIZE)); ftrp.fileName = fileNode.getAttribute(FTSender.NAME); Element desc = fileNode.getChildByName(null, FTSender.DESC); if (desc!=null) ftrp.fileDesc=desc.getText(); Stanza reply = Utils.easyReply(e); xmppClient.sendPacket(reply); EventQuery eq = new EventQuery(Iq.IQ, new String[] { Iq.ATT_FROM, Iq.ATT_TYPE }, new String[] { e.getAttribute(Iq.ATT_FROM), Iq.T_SET }); Element jingle = e.getChildByName(null, FTSender.JINGLE); Element content = jingle.getChildByName(null, FTSender.CONTENT); Element transport = content.getChildByName(null, FTSender.TRANSPORT); eq.child = new EventQuery(FTSender.OPEN, new String[] { FTSender.SID }, new String[] { transport.getAttribute(FTSender.SID) }); BasicXmlStream.addOnetimeEventListener(eq, ftrp); eh.reqFT(e.getAttribute(Iq.ATT_FROM), ftrp); } }