222 lines · 6.6 KB · Java
RawDownload
/* * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.  Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code 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 * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ /* * *  (C) Copyright IBM Corp. 1999 All Rights Reserved. *  Copyright 1997 The Open Group Research Institute.  All rights reserved. */ package sun.security.krb5.internal; import java.io.*;import java.net.*; public abstract class NetClient {    public static NetClient getInstance(String protocol, String hostname, int port,            int timeout) throws IOException {        if (protocol.equals("TCP")) {            return new TCPClient(hostname, port, timeout);        } else {            return new UDPClient(hostname, port, timeout);        }    }     abstract public void send(byte[] data) throws IOException;     abstract public byte[] receive() throws IOException;     abstract public void close() throws IOException;} class TCPClient extends NetClient {     private Socket tcpSocket;    private BufferedOutputStream out;    private BufferedInputStream in;     TCPClient(String hostname, int port, int timeout)            throws IOException {        tcpSocket = new Socket();        tcpSocket.connect(new InetSocketAddress(hostname, port), timeout);        out = new BufferedOutputStream(tcpSocket.getOutputStream());        in = new BufferedInputStream(tcpSocket.getInputStream());        tcpSocket.setSoTimeout(timeout);    }     @Override    public void send(byte[] data) throws IOException {        byte[] lenField = new byte[4];        intToNetworkByteOrder(data.length, lenField, 0, 4);        out.write(lenField);         out.write(data);        out.flush();    }     @Override    public byte[] receive() throws IOException {        byte[] lenField = new byte[4];        int count = readFully(lenField, 4);         if (count != 4) {            if (Krb5.DEBUG) {                System.out.println(                    ">>>DEBUG: TCPClient could not read length field");            }            return null;        }         int len = networkByteOrderToInt(lenField, 0, 4);        if (Krb5.DEBUG) {            System.out.println(                ">>>DEBUG: TCPClient reading " + len + " bytes");        }        if (len <= 0) {            if (Krb5.DEBUG) {                System.out.println(                    ">>>DEBUG: TCPClient zero or negative length field: "+len);            }            return null;        }         byte data[] = new byte[len];        count = readFully(data, len);        if (count != len) {            if (Krb5.DEBUG) {                System.out.println(                    ">>>DEBUG: TCPClient could not read complete packet (" +                    len + "/" + count + ")");            }            return null;        } else {            return data;        }    }     @Override    public void close() throws IOException {        tcpSocket.close();    }     /**     * Read requested number of bytes before returning.     * @return The number of bytes actually read; -1 if none read     */    private int readFully(byte[] inBuf, int total) throws IOException {        int count, pos = 0;         while (total > 0) {            count = in.read(inBuf, pos, total);             if (count == -1) {                return (pos == 0? -1 : pos);            }            pos += count;            total -= count;        }        return pos;    }     /**     * Returns the integer represented by 4 bytes in network byte order.     */    private static int networkByteOrderToInt(byte[] buf, int start,        int count) {        if (count > 4) {            throw new IllegalArgumentException(                "Cannot handle more than 4 bytes");        }         int answer = 0;         for (int i = 0; i < count; i++) {            answer <<= 8;            answer |= ((int)buf[start+i] & 0xff);        }        return answer;    }     /**     * Encodes an integer into 4 bytes in network byte order in the buffer     * supplied.     */    private static void intToNetworkByteOrder(int num, byte[] buf,        int start, int count) {        if (count > 4) {            throw new IllegalArgumentException(                "Cannot handle more than 4 bytes");        }         for (int i = count-1; i >= 0; i--) {            buf[start+i] = (byte)(num & 0xff);            num >>>= 8;        }    }} class UDPClient extends NetClient {    InetAddress iaddr;    int iport;    int bufSize = 65507;    DatagramSocket dgSocket;    DatagramPacket dgPacketIn;     UDPClient(String hostname, int port, int timeout)        throws UnknownHostException, SocketException {        iaddr = InetAddress.getByName(hostname);        iport = port;        dgSocket = new DatagramSocket();        dgSocket.setSoTimeout(timeout);    }     @Override    public void send(byte[] data) throws IOException {        DatagramPacket dgPacketOut = new DatagramPacket(data, data.length,                                                        iaddr, iport);        dgSocket.send(dgPacketOut);    }     @Override    public byte[] receive() throws IOException {        byte ibuf[] = new byte[bufSize];        dgPacketIn = new DatagramPacket(ibuf, ibuf.length);        try {            dgSocket.receive(dgPacketIn);        }        catch (SocketException e) {            dgSocket.receive(dgPacketIn);        }        byte[] data = new byte[dgPacketIn.getLength()];        System.arraycopy(dgPacketIn.getData(), 0, data, 0,                         dgPacketIn.getLength());        return data;    }     @Override    public void close() {        dgSocket.close();    }}