com.jcraft.weirdx.XDMCP.java Source code

Java tutorial

Introduction

Here is the source code for com.jcraft.weirdx.XDMCP.java

Source

/* -*-mode:java; c-basic-offset:2; -*- */
/* WeirdX - XDMCP support
 *
 * Copyright (C) 1999-2004 JCraft, Inc.
 *
 * This program 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 2 of the License, or
 * (at your option) any later version.
 *
 * This program 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 this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

package com.jcraft.weirdx;

import java.io.*;
import java.net.*;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

@SuppressWarnings("unused")
public final class XDMCP extends Thread implements ClientListener {
    private static Log LOG = LogFactory.getLog(XDMCP.class);

    private final static int start = 1;
    private final static int query = 2;
    private final static int collect_query = 3;
    private final static int broadcast = 4;
    private final static int collect_broadcast_query = 5;
    private final static int update_broadcast_willing = 6;
    private final static int indirect = 7;
    private final static int collect_indirect_query = 8;
    private final static int update_indirect_willing = 9;
    private final static int start_connection = 10;
    private final static int await_request_response = 11;
    private final static int manage = 12;
    private final static int await_manage_response = 13;
    private final static int stop_connection = 14;
    private final static int run_session = 15;
    private final static int keep_alive = 16;
    private final static int await_alive = 17;
    private final static int reset_display = 18;

    public final static int BroadcastQuery = 1;
    final static int Query = 2;
    public final static int IndirectQuery = 3;
    private final static int ForwardQuery = 4;
    private final static int Willing = 5;
    private final static int Unwilling = 6;
    private final static int Request = 7;
    private final static int Accept = 8;
    private final static int Decline = 9;
    private final static int Manage = 10;
    private final static int Refuse = 11;
    private final static int Failed = 12;
    private final static int KeepAlive = 13;
    private final static int Alive = 14;

    private int state = 0;

    private final static byte[] manu_display_id = "JCraft-WeirdX-1".getBytes();
    private final static byte[] display_class = "JCraft-WeirdX".getBytes();

    private final static byte[] authname = "MIT-MAGIC-COOKIE-1".getBytes();
    static byte[] mitcookie = null;

    private final static int XDMCPcp_port = 177;
    private static byte[] myaddress = null;

    static int timeout = 5000;

    int displayNum = 0;
    UDPIOByte io;
    byte[] buf = new byte[1024];
    int sessionID;
    String XDMCP;
    int fstclient = -1;

    String host;
    int mode = query;

    void close() {
        try {
            if (io != null)
                io.close();
        } catch (Exception e) {
        }
    }

    void getLocalHost(String name) {
        myaddress = new byte[4];
        try {
            InetAddress local;
            if (name != null && name.length() > 0) {
                local = InetAddress.getByName(name);
            } else {
                local = InetAddress.getLocalHost();
            }
            byte[] b = local.getHostAddress().getBytes();
            int bi = 0;
            for (int i = 0; i < 4; i++) {
                myaddress[i] = 0;
                while (bi < b.length && b[bi] != '.') {
                    myaddress[i] = (byte) (myaddress[i] * 10 + (b[bi] - '0'));
                    bi++;
                }
                if (b.length <= bi)
                    break;
                bi++;
            }
        } catch (Exception e) {
            LOG.error(e);
        }
    }

    XDMCP(String host) {
        this(Query, host, null, 0);
    }

    public XDMCP(String query, String localhost, int num) {
        this(Query, query, localhost, num);
    }

    public XDMCP(int op, String host, String localhost, int num) {
        super();

        this.host = host;
        this.displayNum = num;

        if (myaddress == null) {
            getLocalHost(localhost);
        }

        if (myaddress[0] == 127 && myaddress[1] == 0 && myaddress[2] == 0 && myaddress[3] == 1) {
            LOG.warn("XDMCP warning: InetAddress.getLocalHost() return loopback address");
        }

        if (op == Query)
            mode = query;
        else if (op == BroadcastQuery)
            mode = broadcast;
        else if (op == IndirectQuery)
            mode = indirect;

        if (op == Query) {
            io = new UDPIOByte(host, XDMCPcp_port);
            io.setTimeout(timeout);
        }
    }

    public void connected(int index) {
        if (fstclient == -1) {
            fstclient = index;
        }
    }

    public void disconnected(int index) {
        if (fstclient == index) {
            fstclient = -1;
            WeirdX.resetScreen(0);
            state = reset_display;
        }
    }

    public void run() {
        try {
            stateMachine();
        } catch (Exception e) {
            LOG.error(e);
        }
    }

    void stateMachine() throws IOException {
        int foo, len, opcode, sessionId;

        state = start;

        while (true) {
            switch (state) {
            case start:
                state = mode;
                if (mode == broadcast) {
                    if (io != null)
                        io.close();
                    io = new UDPIOByte(host, XDMCPcp_port);
                    io.setTimeout(timeout);
                } else if (mode == indirect) {
                    if (io != null)
                        io.close();
                    io = new UDPIOByte(host, XDMCPcp_port);
                    io.setTimeout(timeout);
                }
                break;
            case query:
                io.putShort(1);
                io.putShort(Query); // Query
                io.putShort(1);
                io.putShort(0);
                io.flush();
                state = collect_query;
                break;

            case collect_query:
                try {
                    foo = io.getShort();
                    opcode = io.getShort();
                    len = io.getShort();
                    if (opcode == Willing) {
                        foo = io.getShort();
                        io.getByte(buf, 0, foo);
                        foo = io.getShort();
                        io.getByte(buf, 0, foo);
                        foo = io.getShort();
                        io.getByte(buf, 0, foo);
                        state = start_connection;
                    } else if (opcode == Unwilling) {
                        foo = io.getShort();
                        io.getByte(buf, 0, foo);
                        foo = io.getShort();
                        io.getByte(buf, 0, foo);
                        state = stop_connection;
                    } else {
                        LOG.error("unknow opcode(" + opcode + ") at " + state);
                        return;
                    }
                } catch (InterruptedIOException ie) { // timeout
                    state = query;
                    return;
                }
                break;

            case broadcast:
                io.putShort(1);
                io.putShort(BroadcastQuery); // BroadcastQuery
                io.putShort(1);
                io.putShort(0);
                io.flush();
                state = collect_broadcast_query;
                break;

            case collect_broadcast_query:
                try {
                    foo = io.getShort();
                    opcode = foo = io.getShort();
                    len = io.getShort();
                    if (opcode == Willing) {
                        foo = io.getShort();
                        io.getByte(buf, 0, foo);
                        foo = io.getShort();
                        io.getByte(buf, 0, foo);
                        String target = new String(buf, 0, foo);
                        foo = io.getShort();
                        io.getByte(buf, 0, foo);

                        if (target.length() == 0) {
                            target = new String(buf, 0, foo);
                            target = target.substring(target.indexOf(' ') + 1);
                        }

                        io.close();
                        io = new UDPIOByte(target, XDMCPcp_port);
                        io.setTimeout(timeout);

                        state = update_broadcast_willing;
                    } else {
                        io.getByte(buf, 0, len);
                        state = start;
                    }
                    //state=start_connection;
                } catch (InterruptedIOException ie) { // timeout
                    state = start;
                }
                break;

            case update_broadcast_willing:
                state = start_connection;
                //state=collect_broadcast_query;
                break;

            case indirect:
                io.putShort(1);
                io.putShort(IndirectQuery); // IndirectQuery
                io.putShort(1);
                io.putShort(0);
                io.flush();
                state = collect_indirect_query;
                break;

            case collect_indirect_query:
                try {
                    foo = io.getShort();
                    opcode = foo = io.getShort();
                    len = foo = io.getShort();
                    if (opcode == Willing) {
                        foo = io.getShort();
                        io.getByte(buf, 0, foo);
                        foo = io.getShort();
                        io.getByte(buf, 0, foo);
                        String wilinghost = new String(buf, 0, foo);
                        foo = io.getShort();
                        io.getByte(buf, 0, foo);

                        if (io != null)
                            io.close();
                        io = new UDPIOByte(wilinghost, XDMCPcp_port);
                        io.setTimeout(timeout);
                        Acl.parse("+" + wilinghost);

                        //       state=update_indirect_willing;
                        state = start_connection;
                    } else {
                        io.getByte(buf, 0, len);
                        state = indirect;
                    }
                    //state=start_connection;
                } catch (InterruptedIOException ie) { // timeout
                    state = indirect;
                }
                break;

            case update_indirect_willing:
                state = collect_indirect_query;
                break;

            case start_connection:
                io.putShort(1);
                io.putShort(Request);
                io.putShort(15 + myaddress.length + manu_display_id.length + 2 + authname.length);
                io.putShort(displayNum);
                io.putByte((byte) 1);
                io.putShort(0); // connection Type, inet
                io.putByte((byte) 1);
                io.putShort(myaddress.length);
                io.putByte(myaddress, 0, myaddress.length);
                io.putShort(0); // len of authentification name
                io.putShort(0); // len of authentification data
                io.putByte((byte) 1); // count of authorization names
                io.putShort(authname.length);
                io.putByte(authname, 0, authname.length);
                io.putShort(manu_display_id.length); // len of manifucture id
                io.putByte(manu_display_id, 0, manu_display_id.length);
                io.flush();
                state = await_request_response;
                break;

            case await_request_response:
                try {
                    foo = io.getShort();
                    opcode = io.getShort();
                    len = io.getShort();
                    if (opcode == Accept) {
                        sessionID = foo = io.getInt();
                        foo = io.getShort();
                        io.getByte(buf, 0, foo);
                        foo = io.getShort();
                        io.getByte(buf, 0, foo);
                        foo = io.getShort();
                        io.getByte(buf, 0, foo);

                        String bar = null;
                        if (foo > 0)
                            bar = new String(buf, 0, foo);

                        foo = io.getShort();
                        io.getByte(buf, 0, foo);
                        if (bar != null && bar.equals("MIT-MAGIC-COOKIE-1") && foo > 0) {
                            mitcookie = new byte[foo];
                            System.arraycopy(buf, 0, mitcookie, 0, foo);
                        } else {
                            mitcookie = null;
                        }
                        state = manage;
                    } else if (opcode == Decline) {
                        foo = io.getShort();
                        io.getByte(buf, 0, foo);
                        foo = io.getShort();
                        io.getByte(buf, 0, foo);
                        foo = io.getShort();
                        io.getByte(buf, 0, foo);
                        state = stop_connection;
                    } else {
                        LOG.error("unknow opcode(" + opcode + ") at " + state);
                        return;
                    }
                } catch (InterruptedIOException ie) { // timeout
                    state = start_connection;
                    return;
                }
                break;

            case manage:
                io.putShort(1);
                io.putShort(Manage);
                io.putShort(8 + display_class.length);
                io.putInt(sessionID);
                io.putShort(displayNum);
                io.putShort(display_class.length);
                io.putByte(display_class, 0, display_class.length);
                io.flush();
                state = await_manage_response;
                break;

            case await_manage_response:
                try {
                    foo = io.getShort();
                    opcode = foo = io.getShort();
                    len = foo = io.getShort();
                    if (opcode == Refuse) {
                        int id = io.getInt();
                        if (sessionID == id) {
                            state = start_connection;
                        } else {
                            return;
                        }
                    } else if (opcode == Failed) {
                        int id = io.getInt();
                        foo = io.getShort();
                        io.getByte(buf, 0, foo);
                        if (sessionID == id) {
                            state = stop_connection;
                        } else {
                            LOG.error("await_manage_response: invalid failed " + id);
                            return;
                        }
                    } else {
                        LOG.error("unknow opcode(" + opcode + ") at " + state);
                        return;
                    }
                } catch (InterruptedIOException ie) { // timeout
                    try {
                        Thread.sleep(1000);
                    } catch (Exception e) {
                    }
                    if (fstclient == -1) {
                        state = manage;
                    } else {
                        state = run_session;
                    }
                }
                break;

            case stop_connection:
                state = start;
                break;

            case run_session:
                while (true) {
                    try {
                        Thread.sleep(10000);
                    } catch (Exception e) {
                    }
                    if (state == reset_display)
                        break;
                }
                //state=keep_alive;
                state = reset_display;
                break;

            case keep_alive:
                io.putShort(1);
                io.putShort(KeepAlive);
                io.putShort(6);
                io.putShort(displayNum);
                io.putInt(sessionID);
                io.flush();
                state = await_alive;
                break;

            case await_alive:
                foo = io.getShort();
                opcode = io.getShort();
                len = io.getShort();
                int running = foo = io.getByte();
                int id = io.getInt();
                if (running != 0 && id == sessionID) { // running
                    state = run_session;
                } else {
                    state = reset_display;
                }
                break;

            case reset_display:
                state = start;
                break;

            default:
                LOG.warn("??");
            }
        }
    }

    class UDPIOByte {
        InetAddress address;
        DatagramSocket socket = null;
        DatagramPacket sndpacket;
        DatagramPacket recpacket;
        byte[] buf = new byte[1024];
        String host;
        int port;
        byte[] inbuffer = new byte[1024];
        byte[] outbuffer = new byte[1024];
        int instart = 0, inend = 0, outindex = 0;
        /*private*/ byte[] ba;
        /*private*/ byte[] sa;
        /*private*/ byte[] ia;

        UDPIOByte(String host, int port) {
            this.host = host;
            this.port = port;
            try {
                address = InetAddress.getByName(host);
                //   socket = new DatagramSocket();
                socket = new DatagramSocket(6001); // dummy...
            } catch (Exception e) {
                LOG.error(e);
            }
            ba = new byte[1];
            sa = new byte[2];
            ia = new byte[8];
            recpacket = new DatagramPacket(buf, 1024);
            sndpacket = new DatagramPacket(outbuffer, 0, address, port);
        }

        void setTimeout(int i) {
            try {
                socket.setSoTimeout(i);
            } catch (Exception e) {
                LOG.error(e);
            }
        }

        int getByte() throws java.io.IOException {
            if ((inend - instart) < 1) {
                read(1);
            }
            return inbuffer[instart++] & 0xff;
        }

        void getByte(byte[] array) throws java.io.IOException {
            getByte(array, 0, array.length);
        }

        void getByte(byte[] array, int begin, int length) throws java.io.IOException {
            int i = 0;
            while (true) {
                if ((i = (inend - instart)) < length) {
                    if (i != 0) {
                        System.arraycopy(inbuffer, instart, array, begin, i);
                        begin += i;
                        length -= i;
                        instart += i;
                    }
                    read(length);
                    continue;
                }
                System.arraycopy(inbuffer, instart, array, begin, length);
                instart += length;
                break;
            }
        }

        int getShort() throws java.io.IOException {
            if ((inend - instart) < 2) {
                read(2);
            }
            int s = 0;
            s = inbuffer[instart++] & 0xff;
            s = ((s << 8) & 0xffff) | (inbuffer[instart++] & 0xff);
            return s;
        }

        int getInt() throws java.io.IOException {
            if ((inend - instart) < 4) {
                read(4);
            }
            int i = 0;
            i = inbuffer[instart++] & 0xff;
            i = ((i << 8) & 0xffff) | (inbuffer[instart++] & 0xff);
            i = ((i << 8) & 0xffffff) | (inbuffer[instart++] & 0xff);
            i = (i << 8) | (inbuffer[instart++] & 0xff);
            return i;
        }

        void getPad(int n) throws java.io.IOException {
            int i;
            while (n > 0) {
                if ((i = inend - instart) < n) {
                    n -= i;
                    instart += i;
                    read(n);
                    continue;
                }
                instart += n;
                break;
            }
        }

        void read(int n) throws java.io.IOException {
            if (n > inbuffer.length) {
                n = inbuffer.length;
            }
            instart = inend = 0;
            int i;
            while (true) {
                recpacket = new DatagramPacket(buf, 1024);
                socket.receive(recpacket);
                i = recpacket.getLength();
                System.arraycopy(recpacket.getData(), 0, inbuffer, inend, i);
                // i=in.read(inbuffer, inend, inbuffer.length-inend);
                if (i == -1) {
                    throw new IOException();
                }
                inend += i;
                if (n <= inend)
                    break;
            }
        }

        void putByte(byte val) throws java.io.IOException {
            if ((outbuffer.length - outindex) < 1) {
                flush();
            }
            outbuffer[outindex++] = val;
        }

        void putByte(int val) throws java.io.IOException {
            putByte((byte) val);
        }

        void putByte(byte[] array) throws java.io.IOException {
            putByte(array, 0, array.length);
        }

        void putByte(byte[] array, int begin, int length) throws java.io.IOException {
            if (length <= 0)
                return;
            int i = 0;
            while (true) {
                if ((i = (outbuffer.length - outindex)) < length) {
                    if (i != 0) {
                        System.arraycopy(array, begin, outbuffer, outindex, i);
                        begin += i;
                        length -= i;
                        outindex += i;
                    }
                    flush();
                    continue;
                }
                System.arraycopy(array, begin, outbuffer, outindex, length);
                outindex += length;
                break;
            }
        }

        void putShort(int val) throws java.io.IOException {
            if ((outbuffer.length - outindex) < 2) {
                flush();
            }
            outbuffer[outindex++] = (byte) ((val >> 8) & 0xff);
            outbuffer[outindex++] = (byte) (val & 0xff);
        }

        void putInt(int val) throws java.io.IOException {
            if ((outbuffer.length - outindex) < 4) {
                flush();
            }
            outbuffer[outindex++] = (byte) ((val >> 24) & 0xff);
            outbuffer[outindex++] = (byte) ((val >> 16) & 0xff);
            outbuffer[outindex++] = (byte) ((val >> 8) & 0xff);
            outbuffer[outindex++] = (byte) ((val) & 0xff);
        }

        void putPad(int n) throws java.io.IOException {
            int i;
            while (true) {
                if ((i = (outbuffer.length - outindex)) < n) {
                    if (i != 0) {
                        outindex += i;
                        n -= i;
                    }
                    flush();
                    continue;
                }
                outindex += n;
                break;
            }
        }

        synchronized void flush() throws java.io.IOException {
            if (outindex == 0)
                return;
            sndpacket.setLength(outindex);
            socket.send(sndpacket);
            outindex = 0;
        }

        void close() throws java.io.IOException {
            socket.close();
        }
    }

    public static void main(String[] args) {

        String usage = "usage: [-query|-broadcast] address -display displayname";

        int op = -1;
        String address = null;
        String displayaddress = null;
        int displaynum = 0;

        if (args.length == 0) {
            System.err.println(usage);
            System.exit(-1);
        }

        for (int i = 0; i < args.length; i++) {
            if (args[i].equals("-query")) {
                op = Query;
                i++;
                address = args[i];
                continue;
            }
            if (args[i].equals("-broadcast")) {
                op = BroadcastQuery;
                i++;
                address = args[i];
                continue;
            }
            if (args[i].equals("-display")) {
                i++;
                displayaddress = args[i].substring(0, args[i].indexOf(":"));
                try {
                    String foo = args[i].substring(args[i].indexOf(":") + 1, args[i].length());
                    foo = foo.substring(0, (foo.indexOf(".") == -1 ? foo.length() : foo.indexOf(".")));
                    displaynum = Integer.parseInt(foo);
                } catch (Exception e) {
                }
            }
        }

        if (op == -1 || address == null || displayaddress == null) {
            System.err.println(usage);
            System.exit(-1);
        }

        XDMCP foo = new XDMCP(op, address, displayaddress, displaynum);
        foo.start();
    }
}