Path: blob/master/src/java.security.jgss/share/classes/sun/security/krb5/internal/NetClient.java
41161 views
/*1* Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425/*26*27* (C) Copyright IBM Corp. 1999 All Rights Reserved.28* Copyright 1997 The Open Group Research Institute. All rights reserved.29*/3031package sun.security.krb5.internal;3233import java.io.*;34import java.net.*;35import sun.security.util.IOUtils;3637public abstract class NetClient implements AutoCloseable {38public static NetClient getInstance(String protocol, String hostname, int port,39int timeout) throws IOException {40if (protocol.equals("TCP")) {41return new TCPClient(hostname, port, timeout);42} else {43return new UDPClient(hostname, port, timeout);44}45}4647public abstract void send(byte[] data) throws IOException;48public abstract byte[] receive() throws IOException;49public abstract void close() throws IOException;50}5152class TCPClient extends NetClient {5354private Socket tcpSocket;55private BufferedOutputStream out;56private BufferedInputStream in;5758TCPClient(String hostname, int port, int timeout)59throws IOException {60tcpSocket = new Socket();61tcpSocket.connect(new InetSocketAddress(hostname, port), timeout);62out = new BufferedOutputStream(tcpSocket.getOutputStream());63in = new BufferedInputStream(tcpSocket.getInputStream());64tcpSocket.setSoTimeout(timeout);65}6667@Override68public void send(byte[] data) throws IOException {69byte[] lenField = new byte[4];70intToNetworkByteOrder(data.length, lenField, 0, 4);71out.write(lenField);7273out.write(data);74out.flush();75}7677@Override78public byte[] receive() throws IOException {79byte[] lenField = new byte[4];80int count = readFully(lenField, 4);8182if (count != 4) {83if (Krb5.DEBUG) {84System.out.println(85">>>DEBUG: TCPClient could not read length field");86}87return null;88}8990int len = networkByteOrderToInt(lenField, 0, 4);91if (Krb5.DEBUG) {92System.out.println(93">>>DEBUG: TCPClient reading " + len + " bytes");94}95if (len <= 0) {96if (Krb5.DEBUG) {97System.out.println(98">>>DEBUG: TCPClient zero or negative length field: "+len);99}100return null;101}102103try {104return IOUtils.readExactlyNBytes(in, len);105} catch (IOException ioe) {106if (Krb5.DEBUG) {107System.out.println(108">>>DEBUG: TCPClient could not read complete packet (" +109len + "/" + count + ")");110}111return null;112}113}114115@Override116public void close() throws IOException {117tcpSocket.close();118}119120/**121* Read requested number of bytes before returning.122* @return The number of bytes actually read; -1 if none read123*/124private int readFully(byte[] inBuf, int total) throws IOException {125int count, pos = 0;126127while (total > 0) {128count = in.read(inBuf, pos, total);129130if (count == -1) {131return (pos == 0? -1 : pos);132}133pos += count;134total -= count;135}136return pos;137}138139/**140* Returns the integer represented by 4 bytes in network byte order.141*/142private static int networkByteOrderToInt(byte[] buf, int start,143int count) {144if (count > 4) {145throw new IllegalArgumentException(146"Cannot handle more than 4 bytes");147}148149int answer = 0;150151for (int i = 0; i < count; i++) {152answer <<= 8;153answer |= ((int)buf[start+i] & 0xff);154}155return answer;156}157158/**159* Encodes an integer into 4 bytes in network byte order in the buffer160* supplied.161*/162private static void intToNetworkByteOrder(int num, byte[] buf,163int start, int count) {164if (count > 4) {165throw new IllegalArgumentException(166"Cannot handle more than 4 bytes");167}168169for (int i = count-1; i >= 0; i--) {170buf[start+i] = (byte)(num & 0xff);171num >>>= 8;172}173}174}175176class UDPClient extends NetClient {177InetAddress iaddr;178int iport;179int bufSize = 65507;180DatagramSocket dgSocket;181DatagramPacket dgPacketIn;182183UDPClient(String hostname, int port, int timeout)184throws UnknownHostException, SocketException {185iaddr = InetAddress.getByName(hostname);186iport = port;187dgSocket = new DatagramSocket();188dgSocket.setSoTimeout(timeout);189dgSocket.connect(iaddr, iport);190}191192@Override193public void send(byte[] data) throws IOException {194DatagramPacket dgPacketOut = new DatagramPacket(data, data.length,195iaddr, iport);196dgSocket.send(dgPacketOut);197}198199@Override200public byte[] receive() throws IOException {201byte[] ibuf = new byte[bufSize];202dgPacketIn = new DatagramPacket(ibuf, ibuf.length);203try {204dgSocket.receive(dgPacketIn);205}206catch (SocketException e) {207if (e instanceof PortUnreachableException) {208throw e;209}210dgSocket.receive(dgPacketIn);211}212byte[] data = new byte[dgPacketIn.getLength()];213System.arraycopy(dgPacketIn.getData(), 0, data, 0,214dgPacketIn.getLength());215return data;216}217218@Override219public void close() {220dgSocket.close();221}222}223224225