Re: Large Read/Write Patch

"M. D." <[email protected]> Wed, 17 Dec 2014 15:30:34 +0200 (EET)
Newsgroups gmane.network.samba.java
Message-ID <[email protected]>
 Hi,

I'm uploading a new patch. It now contains checks if signatures are desired. If that's the case then the old buffer size is used.

Best regards,
M.D




 >-------- Оригинално писмо --------
 >От:   M. D.  
 >Относно: Re: [jcifs] Large Read/Write Patch
 >До: Robin Jansohn 
 >Изпратено на: Сряда, 2014, Декември 17 10:58:08 EET
 >
 >
 > Hello,
 >
 >I also confirm that read/write operations with the patch applied are significantly faster.
 >
 >However, I think there is a problem with the patch:
 >
 >According to the official SMB documentation: 
 >http://download.microsoft.com/download/9/5/E/95EF66AF-9026-4BB0-A41D-A4F81802D92C/[MS-SMB].pdf
 >
 >... sections 2.2.4.5, 2.2.4.5.2: 
 >&quot;Capabilities (4 bytes): A 32-bit field providing a set of server capability indicators. This bit field is
 >used to indicate to the client which features are supported by the server. Any value not listed in the
 >following table is unused. The server MUST set the unused bits to zero. The client MUST ignore
 >these bits.&quot;. 
 >
 >The CAP_LARGE_WRITEX flag that is part of the Capabilities (4 bytes) field is responsible for:
 >
 >&quot;The server supports large write operations. This
 >capability affects the maximum size, in bytes, of the
 >server buffer for receiving an SMB_COM_WRITE_ANDX
 >client request. When this capability is set by the server
 >(and set by the client in the
 >SMB_COM_SESSION_SETUP_ANDX request), then the
 >maximum server buffer size of bytes it writes can
 >exceed the MaxBufferSize field. Therefore, a client
 >can send a single SMB_COM_WRITE_ANDX request up
 >to this size.
 >When signing is active on a connection, then clients
 >MUST limit write lengths to the MaxBufferSize value
 >negotiated by the server, irrespective of the value of
 >the CAP_LARGE_WRITEX flag.&quot;
 >
 >... so it is true that we can safely ignore the MaxBufferSize and send larger chunks of data UNLESS signing is active on a connection. Therefore, I think checks for signing should be added to the patch. 
 >
 >Hope that helps!
 >
 >
 >Best regards,
 >M.D
 >
 >
 >
 >
 > >-------- Оригинално писмо --------
 > >От:  Robin Jansohn 
 > >Относно: Re: [jcifs] Large Read/Write Patch
 > >До: [email protected]
 > >Изпратено на: Понеделник, 2014, Декември 15 09:08:49 EET
 > >
 > >
 > >No, I'm using a Maven repository and although I explicitly excluded the
 > >package it somehow did not work as expected. The test itself is run in a
 > >simple Main class, no webapp or similar large application.
 > >
 > >
 > >
 > >--
 > >View this message in context: http://samba.2283325.n4.nabble.com/Large-Read-Write-Patch-tp3674893p4677877.html
 > >Sent from the Samba - jcifs mailing list archive at Nabble.com.
 > >
 >
LargeReadWrite.patch (application/octet-stream, 6.6 KB)
### Eclipse Workspace Patch 1.0
#P jcifs
Index: src/jcifs/smb/SmbFileOutputStream.java
===================================================================
--- src/jcifs/smb/SmbFileOutputStream.java  (revision 54857)
+++ src/jcifs/smb/SmbFileOutputStream.java  (working copy)
@@ -33,7 +33,7 @@
 
     private SmbFile file;
     private boolean append, useNTSmbs;
-    private int openFlags, access, writeSize;
+    private int openFlags, writeSizeFile, access, writeSize;
     private long fp;
     private byte[] tmp = new byte[1];
     private SmbComWriteAndX reqx;
@@ -142,6 +142,11 @@
         file.open( openFlags, access | SmbConstants.FILE_WRITE_DATA, SmbFile.ATTR_NORMAL, 0 );
         this.openFlags &= ~(SmbFile.O_CREAT | SmbFile.O_TRUNC); /* in case close and reopen */
         writeSize = file.tree.session.transport.snd_buf_size - 70;
+		 boolean isSignatureActive =
+		     file.tree.session.transport.server.signaturesRequired ||
+		     (file.tree.session.transport.server.signaturesEnabled && SmbTransport.SIGNPREF);
+        if((file.tree.session.transport.server.capabilities & SmbConstants.CAP_LARGE_WRITEX) == SmbConstants.CAP_LARGE_WRITEX && !isSignatureActive) {
+            writeSizeFile = Math.min(SmbConstants.RCV_BUF_SIZE - 70, 0xFFFF - 70);
+        } else {
+            writeSizeFile = writeSize;
+        }
 
         useNTSmbs = file.tree.session.transport.hasCapability( ServerMessageBlock.CAP_NT_SMBS );
         if( useNTSmbs ) {
@@ -233,15 +238,17 @@
 
         int w;
         do {
-            w = len > writeSize ? writeSize : len;
+            int blockSize = (file.getType() == SmbFile.TYPE_FILESYSTEM) ? writeSizeFile : writeSize;
+            w = len > blockSize ? blockSize : len;
+
             if( useNTSmbs ) {
                 reqx.setParam( file.fid, fp, len - w, b, off, w );
-if ((flags & 1) != 0) {
-    reqx.setParam( file.fid, fp, len, b, off, w );
-    reqx.writeMode = 0x8;
-} else {
-    reqx.writeMode = 0;
-}
+            if ((flags & 1) != 0) {
+                reqx.setParam( file.fid, fp, len, b, off, w );
+                reqx.writeMode = 0x8;
+            } else {
+                reqx.writeMode = 0;
+            }
                 file.send( reqx, rspx );
                 fp += rspx.count;
                 len -= rspx.count;
Index: src/jcifs/smb/SmbRandomAccessFile.java
===================================================================
--- src/jcifs/smb/SmbRandomAccessFile.java  (revision 54857)
+++ src/jcifs/smb/SmbRandomAccessFile.java  (working copy)
@@ -55,8 +55,19 @@
             throw new IllegalArgumentException( "Invalid mode" );
         }
         file.open( openFlags, access, SmbFile.ATTR_NORMAL, options );
-        readSize = file.tree.session.transport.rcv_buf_size - 70;
-        writeSize = file.tree.session.transport.snd_buf_size - 70;
+		 boolean isSignatureActive =
+		     file.tree.session.transport.server.signaturesRequired ||
+		     (file.tree.session.transport.server.signaturesEnabled && SmbTransport.SIGNPREF);       
+      if((file.tree.session.transport.server.capabilities & SmbConstants.CAP_LARGE_READX) == SmbConstants.CAP_LARGE_READX && !isSignatureActive) {
+            readSize = Math.min(SmbConstants.RCV_BUF_SIZE - 70, 0xFFFF -70);
+        } else {
+            readSize = file.tree.session.transport.rcv_buf_size - 70;
+        }
+        
+        if((file.tree.session.transport.server.capabilities & SmbConstants.CAP_LARGE_WRITEX) == SmbConstants.CAP_LARGE_WRITEX && !isSignatureActive) {
+            writeSize = Math.min(SmbConstants.SND_BUF_SIZE - 70, 0xFFFF - 70);
+        } else {
+            writeSize = Math.min( file.tree.session.transport.snd_buf_size - 70,
+                                  file.tree.session.transport.server.maxBufferSize - 70 );
+        }
         fp = 0L;
     }
 
Index: src/jcifs/smb/SmbConstants.java
===================================================================
--- src/jcifs/smb/SmbConstants.java (revision 54857)
+++ src/jcifs/smb/SmbConstants.java (working copy)
@@ -12,8 +12,8 @@
     static final int DEFAULT_MAX_MPX_COUNT = 10;
     static final int DEFAULT_RESPONSE_TIMEOUT = 30000;
     static final int DEFAULT_SO_TIMEOUT = 35000;
-    static final int DEFAULT_RCV_BUF_SIZE = 60416;
-    static final int DEFAULT_SND_BUF_SIZE = 16644;
+   static final int DEFAULT_RCV_BUF_SIZE = 0xFFFF;
+   static final int DEFAULT_SND_BUF_SIZE = 0xFFFF;
     static final int DEFAULT_SSN_LIMIT = 250;
 
     static final InetAddress LADDR = Config.getLocalHost();
@@ -61,7 +61,9 @@
     static final int CAP_LEVEL_II_OPLOCKS = 0x0080;
     static final int CAP_LOCK_AND_READ    = 0x0100;
     static final int CAP_NT_FIND          = 0x0200;
-    static final int CAP_DFS              = 0x1000;
+    static final int CAP_DFS              = 0x1000;
+   static final int CAP_LARGE_READX = 0x4000;
+   static final int CAP_LARGE_WRITEX = 0x8000;
     static final int CAP_EXTENDED_SECURITY = 0x80000000;
 
     // file attribute encoding
Index: src/jcifs/smb/SmbFileInputStream.java
===================================================================
--- src/jcifs/smb/SmbFileInputStream.java   (revision 54857)
+++ src/jcifs/smb/SmbFileInputStream.java   (working copy)
@@ -34,7 +34,7 @@
 public class SmbFileInputStream extends InputStream {
 
     private long fp;
-    private int readSize, openFlags, access;
+    private int readSize, readSizeFile, openFlags, access;
     private byte[] tmp = new byte[1];
 
     SmbFile file;
@@ -76,7 +76,12 @@
             file.connect0();
         }
         readSize = Math.min( file.tree.session.transport.rcv_buf_size - 70,
-                            file.tree.session.transport.server.maxBufferSize - 70 );
+                            file.tree.session.transport.server.maxBufferSize - 70 );
+		 boolean isSignatureActive =
+		     file.tree.session.transport.server.signaturesRequired ||
+		     (file.tree.session.transport.server.signaturesEnabled && SmbTransport.SIGNPREF);
+        if((file.tree.session.transport.server.capabilities & SmbConstants.CAP_LARGE_READX) == SmbConstants.CAP_LARGE_READX && !isSignatureActive) {
+            readSizeFile = Math.min(SmbConstants.RCV_BUF_SIZE - 70, 0xFFFF - 70);
+        } else {
+            readSizeFile = readSize;
+        }
     }
 
     protected IOException seToIoe(SmbException se) {
@@ -168,7 +173,8 @@
 
         int r, n;
         do {
-            r = len > readSize ? readSize : len;
+            int blockSize = (file.getType() == SmbFile.TYPE_FILESYSTEM) ? readSizeFile : readSize;
+            r = len > blockSize ? blockSize : len;
 
             if( file.log.level >= 4 )
                 file.log.println( "read: len=" + len + ",r=" + r + ",fp=" + fp );