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.iso.*;
022
023import java.io.BufferedReader;
024import java.io.EOFException;
025import java.io.IOException;
026import java.io.InputStreamReader;
027import java.net.ServerSocket;
028import java.net.Socket;
029import java.util.Vector;
030
031/**
032 * Implements an ISOChannel suitable to be used to connect to an X.25 PAD. 
033 * It waits a limited amount of time to decide when a packet is ready
034 * to be unpacked.
035 *
036 * This channel is based on PADChannel version 1.4. The new version
037 * seems to have some problems dealing with ETXs (we're working on it).
038 * Use this version _only_ if you have problems with current PADChannel
039 * as it will be deprecated some time in the future.
040 *
041 * @author  <a href="mailto:apr@cs.com.uy">Alejandro P. Revilla</a>
042 * @version $Id$
043 *
044 * @see ISOMsg
045 * @see ISOException
046 * @see ISOChannel
047 */
048@SuppressWarnings("unchecked")
049public class X25Channel extends BaseChannel {
050    BufferedReader reader = null;
051    protected byte[] header;
052    /**
053     * No-args constructor
054     */
055    public X25Channel () {
056        super();
057    }
058    /**
059     * Constructs client ISOChannel
060     * @param host  server TCP Address
061     * @param port  server port number
062     * @param p     an ISOPackager
063     * @see ISOPackager
064     */
065    public X25Channel (String host, int port, ISOPackager p) {
066        super(host, port, p);
067    }
068    /**
069     * Construct server ISOChannel
070     * @param p     an ISOPackager
071     * @see ISOPackager
072     * @exception IOException
073     */
074    public X25Channel (ISOPackager p) throws IOException {
075        super(p);
076    }
077    /**
078     * constructs a server ISOChannel associated with a Server Socket
079     * @param p     an ISOPackager
080     * @param serverSocket where to accept a connection
081     * @exception IOException
082     * @see ISOPackager
083     */
084    public X25Channel (ISOPackager p, ServerSocket serverSocket) 
085        throws IOException
086    {
087        super(p, serverSocket);
088    }
089    /**
090     * @return a byte array with the received message
091     * @exception IOException
092     */
093    protected byte[] streamReceive() throws IOException {
094        int c, k=0, len = 1;
095        Vector v = new Vector();
096
097        c = serverIn.read();
098        if (c == -1)
099            throw new EOFException ("connection closed");
100        byte[] b = new byte[1];
101        b[0] = (byte) c;
102        v.addElement (b);
103
104        // Wait for packets until timeout
105        while ((c = serverIn.available()) > 0) {
106            b = new byte[c];
107            if (serverIn.read (b) != c)
108                throw new EOFException ("connection closed");
109            v.addElement (b);
110            len += c;
111            try {
112                Thread.sleep (50);
113            } catch (InterruptedException e) { }
114        }
115
116        byte[] d = new byte[len];
117        for (int i=0; i<v.size(); i++) {
118            b = (byte[]) v.elementAt(i);
119            System.arraycopy (b, 0, d, k, b.length);
120            k += b.length;
121        }
122        return d;
123    }
124    protected void connect (Socket socket) throws IOException {
125        super.connect (socket);
126        reader = new BufferedReader (new InputStreamReader (serverIn));
127    }
128    public void disconnect () throws IOException {
129        super.disconnect ();
130        reader = null;
131    }
132    protected int getHeaderLength() { 
133        return header != null ? header.length : 0;
134    }
135    public void setHeader (byte[] header) {
136        this.header = header;
137    }
138    /**
139     * @param header Hex representation of header
140     */
141    public void setHeader (String header) {
142        setHeader (
143            ISOUtil.hex2byte (header.getBytes(), 0, header.getBytes().length / 2)
144        );
145    }
146    public byte[] getHeader () {
147        return header;
148    }
149    protected void sendMessageHeader(ISOMsg m, int len) throws IOException { 
150        if (m.getHeader() != null)
151            serverOut.write(m.getHeader());
152        else if (header != null) 
153            serverOut.write(header);
154    }
155}