
com.hierynomus.smbj.connection.SequenceWindow Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of smbj Show documentation
Show all versions of smbj Show documentation
SMB2 protocol library for communication with Windows servers
The newest version!
/*
* Copyright (C)2016 - SMBJ Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hierynomus.smbj.connection;
import com.hierynomus.smbj.common.SMBRuntimeException;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
/**
* [MS-SMB2] 3.2.4.1.6 Algorithm for Handling Available Message Sequence Numbers by the Client.
*
* The client MUST implement an algorithm to manage message sequence numbers.
*
* Sequence numbers are used to associate requests with responses and to determine what requests are allowed for processing.
* The algorithm MUST meet the following conditions:
*
* - When the connection is first established, the allowable sequence numbers for sending a request MUST be set to the set { 0 }.
* - The client MUST never send a request on a given connection with a sequence number that has already been used unless it is a request to cancel a previously sent request.
* - The client MUST grow the set in a monotonically increasing manner based on the credits granted. If the set is { 0 }, and 2 credits are granted, the set MUST grow to { 0, 1, 2 }.
* - The client MUST use the lowest available sequence number in its allowable set for each request.
* - For a multi-credit request as specified in section 3.2.4.1.5, the client MUST use the lowest available range of consecutive sequence numbers.
*
*/
public class SequenceWindow {
static final int PREFERRED_MINIMUM_CREDITS = 512;
private AtomicLong lowestAvailable = new AtomicLong(0);
private Semaphore available = new Semaphore(1);
private static final long MAX_WAIT = 5000;
long get() {
return get(1)[0];
}
long[] get(int credits) {
try {
if (available.tryAcquire(credits, MAX_WAIT, TimeUnit.MILLISECONDS)) {
long lowest = lowestAvailable.getAndAdd(credits);
return range(lowest, lowest + credits);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new SMBRuntimeException("Got interrupted waiting for " + credits + " to be available. Credits available at this moment: " + available.availablePermits());
}
throw new SMBRuntimeException("Not enough credits (" + available.availablePermits() + " available) to hand out " + credits + " sequence numbers");
}
void disableCredits() {
this.available = new NoopSemaphore();
}
public int available() {
return available.availablePermits();
}
public void creditsGranted(int credits) {
available.release(credits);
}
private long[] range(long start, long stop) {
int l = (int) (stop - start);
long[] result = new long[l];
for (int i = 0; i < l; i++)
result[i] = start + i;
return result;
}
@SuppressWarnings("serial")
private static class NoopSemaphore extends Semaphore {
public NoopSemaphore() {
super(1);
}
@Override
public boolean tryAcquire() {
return true;
}
@Override
public boolean tryAcquire(long timeout, TimeUnit unit) {
return true;
}
@Override
public boolean tryAcquire(int permits) {
return true;
}
@Override
public boolean tryAcquire(int permits, long timeout, TimeUnit unit) {
return true;
}
@Override
public void release(int permits) {
// no-op
}
@Override
public int availablePermits() {
return Integer.MAX_VALUE;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy