/** * Global Sensor Networks (GSN) Source Code * Copyright (c) 2006-2016, Ecole Polytechnique Federale de Lausanne (EPFL) * * This file is part of GSN. * * GSN is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GSN is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GSN. If not, see <http://www.gnu.org/licenses/>. * * File: src/ch/epfl/gsn/networking/zeromq/ZeroMQWrapperPush.java * * @author Julien Eberle * */ package ch.epfl.gsn.networking.zeromq; import java.io.ByteArrayInputStream; import org.zeromq.ZContext; import org.slf4j.LoggerFactory; import org.slf4j.Logger; import org.zeromq.ZMQ; import com.esotericsoftware.kryo.Kryo; import com.esotericsoftware.kryo.io.Input; import ch.epfl.gsn.Main; import ch.epfl.gsn.beans.AddressBean; import ch.epfl.gsn.beans.DataField; import ch.epfl.gsn.beans.StreamElement; import ch.epfl.gsn.delivery.StreamElement4Rest; import ch.epfl.gsn.wrappers.AbstractWrapper; public class ZeroMQWrapperPush extends AbstractWrapper { private transient Logger logger = LoggerFactory.getLogger( this.getClass() ); private DataField[] structure; private Kryo kryo = new Kryo(); private ZMQ.Socket receiver = null; private int lport = 0; private String laddress; @Override public boolean initialize() { kryo.register(StreamElement4Rest.class); kryo.register(DataField[].class); AddressBean addressBean = getActiveAddressBean(); structure = getActiveAddressBean().getOutputStructure(); String _lport = addressBean.getPredicateValue("local_port"); laddress = addressBean.getPredicateValue("local_address"); if ( laddress == null || laddress.trim().length() == 0 ) throw new RuntimeException( "The >local_address< parameter is missing from the ZeroMQ wrapper." ); if (_lport != null){ lport = Integer.parseInt(_lport); if ( lport <= 0 || lport > 65535 ) throw new RuntimeException( "The >local_port< parameter must be a valid port number." ); } else { throw new RuntimeException( "The >local_port< parameter is missing from the ZeroMQ wrapper." ); } ZContext ctx = Main.getZmqContext(); receiver = ctx.createSocket(ZMQ.REP); receiver.bind("tcp://*:"+lport); receiver.setReceiveTimeOut(10000); return true; } @Override public void dispose() { } @Override public String getWrapperName() { return "ZeroMQ wrapper Push"; } @Override public void run(){ while (isActive()) { try { byte[] rec = receiver.recv(); if (rec != null) { ByteArrayInputStream bais = new ByteArrayInputStream(rec); StreamElement se = kryo.readObjectOrNull(new Input(bais),StreamElement.class); boolean success = postStreamElement(se); receiver.send(success ? new byte[]{(byte)0} : new byte[]{(byte)1}); } } catch (IllegalStateException z) { logger.error("ZMQ wrapper error in zmq protocol (re-init socket): ",z); try { receiver.send(new byte[]{(byte)1}); } catch (Exception e) { logger.error("ZMQ wrapper error in send: ",e); } finally { receiver.close(); ZContext ctx = Main.getZmqContext(); receiver = ctx.createSocket(ZMQ.REP); receiver.bind("tcp://*:"+lport); receiver.setReceiveTimeOut(10000); } } catch (Exception e) { logger.error("ZMQ wrapper error: ",e); } } receiver.close(); } /** * if the structure is not defined in the xml file, throws an exception. */ @Override public DataField[] getOutputFormat() throws RuntimeException{ if (structure == null){throw new RuntimeException("ZMQ Push wrapper has an undefined output structure.");} return structure; } @Override public boolean isTimeStampUnique(){ return false; } }