001/*
002 * jPOS Project [http://jpos.org]
003 * Copyright (C) 2000-2026 jPOS Software SRL
004 *
005 * This program is free software: you can redistribute it and/or modify
006 * it under the terms of the GNU Affero General Public License as
007 * published by the Free Software Foundation, either version 3 of the
008 * License, or (at your option) any later version.
009 *
010 * This program is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
013 * GNU Affero General Public License for more details.
014 *
015 * You should have received a copy of the GNU Affero General Public License
016 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
017 */
018
019package org.jpos.iso.channel;
020
021import org.jpos.core.Configuration;
022import org.jpos.core.ConfigurationException;
023import org.jpos.iso.*;
024
025import java.io.IOException;
026import java.net.ServerSocket;
027
028/**
029 * ISOChannel implementation - CS standard Channel<br>
030 * We at <a href="http://www.cs.com.uy">CS</a>, have used
031 * the so called ISOChannels for a long time. This class
032 * talks with our legacy C++ based systems.<br>
033 *
034 * @author apr@cs.com.uy
035 * @version $Id$
036 * @see ISOMsg
037 * @see ISOException
038 * @see ISOChannel
039 */
040public class CSChannel extends BaseChannel {
041    private boolean replyKeepAlive = true;
042    /**
043     * Public constructor (used by Class.forName("...").newInstance())
044     */
045    public CSChannel () {
046        super();
047    }
048    /**
049     * Construct client ISOChannel
050     * @param host  server TCP Address
051     * @param port  server port number
052     * @param p     an ISOPackager
053     * @see ISOPackager
054     */
055    public CSChannel (String host, int port, ISOPackager p) {
056        super(host, port, p);
057    }
058    /**
059     * Construct server ISOChannel
060     * @param p     an ISOPackager
061     * @exception IOException on I/O failure
062     * @see ISOPackager
063     */
064    public CSChannel (ISOPackager p) throws IOException {
065        super(p);
066    }
067    /**
068     * constructs a server ISOChannel associated with a Server Socket
069     * @param p     an ISOPackager
070     * @param serverSocket where to accept a connection
071     * @exception IOException on I/O failure
072     * @see ISOPackager
073     */
074    public CSChannel (ISOPackager p, ServerSocket serverSocket)
075        throws IOException
076    {
077        super(p, serverSocket);
078    }
079    /**
080     * Writes a 4-byte message length header to the output stream.
081     * @param len the packed message length
082     * @exception IOException on I/O failure
083     */
084    protected void sendMessageLength(int len) throws IOException {
085        serverOut.write (len >> 8);
086        serverOut.write (len);
087        serverOut.write (0);
088        serverOut.write (0);
089    }
090    /**
091     * Reads the 4-byte message length header from the input stream.
092     * @return the message length
093     * @exception IOException on I/O failure
094     * @exception ISOException on protocol error
095     */
096    protected int getMessageLength() throws IOException, ISOException {
097        int l = 0;
098        byte[] b = new byte[4];
099        while (l == 0) {
100            serverIn.readFully(b,0,4);
101            l = ((int)b[0] &0xFF) << 8 | (int)b[1] &0xFF;
102            if (l == 0 &&
103                (replyKeepAlive || isExpectKeepAlive()))
104            {
105                serverOutLock.lock();
106                try {
107                    serverOut.write(b);
108                    serverOut.flush();
109                } finally {
110                    serverOutLock.unlock();
111                }
112            }
113        }
114        return l;
115    }
116    protected int getHeaderLength() {
117        // CS Channel does not support header
118        return 0;
119    }
120    protected void sendMessageHeader(ISOMsg m, int len) {
121        // CS Channel does not support header
122    }
123
124    @Override
125    public void setConfiguration (Configuration cfg) throws ConfigurationException {
126        super.setConfiguration(cfg);
127        replyKeepAlive = cfg.getBoolean("reply-keepalive", true);
128    }
129}