/* * Copyright (c) 2004, 2007, 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. */ package sun.security.ssl; import javax.net.ssl.*;import java.nio.*; /* * A multi-purpose class which handles all of the SSLEngine arguments. * It validates arguments, checks for RO conditions, does space * calculations, performs scatter/gather, etc. * * @author Brad R. Wetmore */class EngineArgs { /* * Keep track of the input parameters. */ ByteBuffer netData; ByteBuffer [] appData; private int offset; // offset/len for the appData array. private int len; /* * The initial pos/limit conditions. This is useful because we can * quickly calculate the amount consumed/produced in successful * operations, or easily return the buffers to their pre-error * conditions. */ private int netPos; private int netLim; private int [] appPoss; private int [] appLims; /* * Sum total of the space remaining in all of the appData buffers */ private int appRemaining = 0; private boolean wrapMethod; /* * Called by the SSLEngine.wrap() method. */ EngineArgs(ByteBuffer [] appData, int offset, int len, ByteBuffer netData) { this.wrapMethod = true; init(netData, appData, offset, len); } /* * Called by the SSLEngine.unwrap() method. */ EngineArgs(ByteBuffer netData, ByteBuffer [] appData, int offset, int len) { this.wrapMethod = false; init(netData, appData, offset, len); } /* * The main initialization method for the arguments. Most * of them are pretty obvious as to what they do. * * Since we're already iterating over appData array for validity * checking, we also keep track of how much remainging space is * available. Info is used in both unwrap (to see if there is * enough space available in the destination), and in wrap (to * determine how much more we can copy into the outgoing data * buffer. */ private void init(ByteBuffer netData, ByteBuffer [] appData, int offset, int len) { if ((netData == null) || (appData == null)) { throw new IllegalArgumentException("src/dst is null"); } if ((offset < 0) || (len < 0) || (offset > appData.length - len)) { throw new IndexOutOfBoundsException(); } if (wrapMethod && netData.isReadOnly()) { throw new ReadOnlyBufferException(); } netPos = netData.position(); netLim = netData.limit(); appPoss = new int [appData.length]; appLims = new int [appData.length]; for (int i = offset; i < offset + len; i++) { if (appData[i] == null) { throw new IllegalArgumentException( "appData[" + i + "] == null"); } /* * If we're unwrapping, then check to make sure our * destination bufffers are writable. */ if (!wrapMethod && appData[i].isReadOnly()) { throw new ReadOnlyBufferException(); } appRemaining += appData[i].remaining(); appPoss[i] = appData[i].position(); appLims[i] = appData[i].limit(); } /* * Ok, looks like we have a good set of args, let's * store the rest of this stuff. */ this.netData = netData; this.appData = appData; this.offset = offset; this.len = len; } /* * Given spaceLeft bytes to transfer, gather up that much data * from the appData buffers (starting at offset in the array), * and transfer it into the netData buffer. * * The user has already ensured there is enough room. */ void gather(int spaceLeft) { for (int i = offset; (i < (offset + len)) && (spaceLeft > 0); i++) { int amount = Math.min(appData[i].remaining(), spaceLeft); appData[i].limit(appData[i].position() + amount); netData.put(appData[i]); spaceLeft -= amount; } } /* * Using the supplied buffer, scatter the data into the appData buffers * (starting at offset in the array). * * The user has already ensured there is enough room. */ void scatter(ByteBuffer readyData) { int amountLeft = readyData.remaining(); for (int i = offset; (i < (offset + len)) && (amountLeft > 0); i++) { int amount = Math.min(appData[i].remaining(), amountLeft); readyData.limit(readyData.position() + amount); appData[i].put(readyData); amountLeft -= amount; } assert(readyData.remaining() == 0); } int getAppRemaining() { return appRemaining; } /* * Calculate the bytesConsumed/byteProduced. Aren't you glad * we saved this off earlier? */ int deltaNet() { return (netData.position() - netPos); } /* * Calculate the bytesConsumed/byteProduced. Aren't you glad * we saved this off earlier? */ int deltaApp() { int sum = 0; // Only calculating 2^14 here, don't need a long. for (int i = offset; i < offset + len; i++) { sum += appData[i].position() - appPoss[i]; } return sum; } /* * In the case of Exception, we want to reset the positions * to appear as though no data has been consumed or produced. */ void resetPos() { netData.position(netPos); for (int i = offset; i < offset + len; i++) { appData[i].position(appPoss[i]); } } /* * We are doing lots of ByteBuffer manipulations, in which case * we need to make sure that the limits get set back correctly. * This is one of the last things to get done before returning to * the user. */ void resetLim() { netData.limit(netLim); for (int i = offset; i < offset + len; i++) { appData[i].limit(appLims[i]); } }}
/*
* Copyright (c) 2004, 2007, 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.
*/
package sun.security.ssl;
import javax.net.ssl.*;
import java.nio.*;
/*
* A multi-purpose class which handles all of the SSLEngine arguments.
* It validates arguments, checks for RO conditions, does space
* calculations, performs scatter/gather, etc.
*
* @author Brad R. Wetmore
*/
class EngineArgs {
/*
* Keep track of the input parameters.
*/
ByteBuffer netData;
ByteBuffer [] appData;
private int offset; // offset/len for the appData array.
private int len;
/*
* The initial pos/limit conditions. This is useful because we can
* quickly calculate the amount consumed/produced in successful
* operations, or easily return the buffers to their pre-error
* conditions.
*/
private int netPos;
private int netLim;
private int [] appPoss;
private int [] appLims;
/*
* Sum total of the space remaining in all of the appData buffers
*/
private int appRemaining = 0;
private boolean wrapMethod;
/*
* Called by the SSLEngine.wrap() method.
*/
EngineArgs(ByteBuffer [] appData, int offset, int len,
ByteBuffer netData) {
this.wrapMethod = true;
init(netData, appData, offset, len);
}
/*
* Called by the SSLEngine.unwrap() method.
*/
EngineArgs(ByteBuffer netData, ByteBuffer [] appData, int offset,
int len) {
this.wrapMethod = false;
init(netData, appData, offset, len);
}
/*
* The main initialization method for the arguments. Most
* of them are pretty obvious as to what they do.
*
* Since we're already iterating over appData array for validity
* checking, we also keep track of how much remainging space is
* available. Info is used in both unwrap (to see if there is
* enough space available in the destination), and in wrap (to
* determine how much more we can copy into the outgoing data
* buffer.
*/
private void init(ByteBuffer netData, ByteBuffer [] appData,
int offset, int len) {
if ((netData == null) || (appData == null)) {
throw new IllegalArgumentException("src/dst is null");
}
if ((offset < 0) || (len < 0) || (offset > appData.length - len)) {
throw new IndexOutOfBoundsException();
}
if (wrapMethod && netData.isReadOnly()) {
throw new ReadOnlyBufferException();
}
netPos = netData.position();
netLim = netData.limit();
appPoss = new int [appData.length];
appLims = new int [appData.length];
for (int i = offset; i < offset + len; i++) {
if (appData[i] == null) {
throw new IllegalArgumentException(
"appData[" + i + "] == null");
}
/*
* If we're unwrapping, then check to make sure our
* destination bufffers are writable.
*/
if (!wrapMethod && appData[i].isReadOnly()) {
throw new ReadOnlyBufferException();
}
appRemaining += appData[i].remaining();
appPoss[i] = appData[i].position();
appLims[i] = appData[i].limit();
}
/*
* Ok, looks like we have a good set of args, let's
* store the rest of this stuff.
*/
this.netData = netData;
this.appData = appData;
this.offset = offset;
this.len = len;
}
/*
* Given spaceLeft bytes to transfer, gather up that much data
* from the appData buffers (starting at offset in the array),
* and transfer it into the netData buffer.
*
* The user has already ensured there is enough room.
*/
void gather(int spaceLeft) {
for (int i = offset; (i < (offset + len)) && (spaceLeft > 0); i++) {
int amount = Math.min(appData[i].remaining(), spaceLeft);
appData[i].limit(appData[i].position() + amount);
netData.put(appData[i]);
spaceLeft -= amount;
}
}
/*
* Using the supplied buffer, scatter the data into the appData buffers
* (starting at offset in the array).
*
* The user has already ensured there is enough room.
*/
void scatter(ByteBuffer readyData) {
int amountLeft = readyData.remaining();
for (int i = offset; (i < (offset + len)) && (amountLeft > 0);
i++) {
int amount = Math.min(appData[i].remaining(), amountLeft);
readyData.limit(readyData.position() + amount);
appData[i].put(readyData);
amountLeft -= amount;
}
assert(readyData.remaining() == 0);
}
int getAppRemaining() {
return appRemaining;
}
/*
* Calculate the bytesConsumed/byteProduced. Aren't you glad
* we saved this off earlier?
*/
int deltaNet() {
return (netData.position() - netPos);
}
/*
* Calculate the bytesConsumed/byteProduced. Aren't you glad
* we saved this off earlier?
*/
int deltaApp() {
int sum = 0; // Only calculating 2^14 here, don't need a long.
for (int i = offset; i < offset + len; i++) {
sum += appData[i].position() - appPoss[i];
}
return sum;
}
/*
* In the case of Exception, we want to reset the positions
* to appear as though no data has been consumed or produced.
*/
void resetPos() {
netData.position(netPos);
for (int i = offset; i < offset + len; i++) {
appData[i].position(appPoss[i]);
}
}
/*
* We are doing lots of ByteBuffer manipulations, in which case
* we need to make sure that the limits get set back correctly.
* This is one of the last things to get done before returning to
* the user.
*/
void resetLim() {
netData.limit(netLim);
for (int i = offset; i < offset + len; i++) {
appData[i].limit(appLims[i]);
}
}
}