jcifs-1.3.13 from tgz
authorFelix Schumacher <felix.schumacher@internetallee.de>
Wed, 6 Jan 2010 13:50:44 +0000 (14:50 +0100)
committerFelix Schumacher <felix.schumacher@internetallee.de>
Wed, 6 Jan 2010 13:50:44 +0000 (14:50 +0100)
jcifs-1.3.13

Locking throughout the transport layer has been rewritten. This should
fix the long standing deadlock that has been reported in the past. Doubled
size of transient input buffer to accommodate SMB_COM_NEGOTIATE response
security blob (as observed with OSX Snow Leopard). A signing issue reading
data from an EMC server has been fixed. NTLMSSP logging has been improved.

97 files changed:
README.txt
build.xml
examples/AclCrawler.class [new file with mode: 0644]
examples/AllocInfo.class [new file with mode: 0644]
examples/Append.class [new file with mode: 0644]
examples/AuthListFiles.class [new file with mode: 0644]
examples/CallNamedPipe.class [new file with mode: 0644]
examples/CopyTo.class [new file with mode: 0644]
examples/CountPerms.class [new file with mode: 0644]
examples/CreateFile.class [new file with mode: 0644]
examples/Delete.class [new file with mode: 0644]
examples/Equals.class [new file with mode: 0644]
examples/Exists.class [new file with mode: 0644]
examples/FileInfo.class [new file with mode: 0644]
examples/FileOps.class [new file with mode: 0644]
examples/FilterFiles$BigFileFilter.class [new file with mode: 0644]
examples/FilterFiles$ShortFilenameFilter.class [new file with mode: 0644]
examples/FilterFiles.class [new file with mode: 0644]
examples/Format.class [new file with mode: 0644]
examples/Get.class [new file with mode: 0644]
examples/GetDate.class [new file with mode: 0644]
examples/GetDfsPath.class [new file with mode: 0644]
examples/GetGroupMemberSidsFromURL.class [new file with mode: 0644]
examples/GetSecurity.class [new file with mode: 0644]
examples/GetShareSecurity.class [new file with mode: 0644]
examples/GetType.class [new file with mode: 0644]
examples/GetURL.class [new file with mode: 0644]
examples/GrowWrite.class [new file with mode: 0644]
examples/HttpURL.class [new file with mode: 0644]
examples/Interleave$IThread.class [new file with mode: 0644]
examples/Interleave.class [new file with mode: 0644]
examples/InterruptTest.class [new file with mode: 0644]
examples/IsDir.class [new file with mode: 0644]
examples/LargeListFiles.class [new file with mode: 0644]
examples/Length.class [new file with mode: 0644]
examples/List.class [new file with mode: 0644]
examples/ListACL.class [new file with mode: 0644]
examples/ListFiles.class [new file with mode: 0644]
examples/ListTypes.class [new file with mode: 0644]
examples/Mkdir.class [new file with mode: 0644]
examples/NodeStatus.class [new file with mode: 0644]
examples/OpenExclusive.class [new file with mode: 0644]
examples/PeekNamedPipe$ReceiverThread.class [new file with mode: 0644]
examples/PeekNamedPipe.class [new file with mode: 0644]
examples/PipeTalk$ReceiverThread.class [new file with mode: 0644]
examples/PipeTalk.class [new file with mode: 0644]
examples/Put.class [new file with mode: 0644]
examples/Query.class [new file with mode: 0644]
examples/RenameTo.class [new file with mode: 0644]
examples/SetAttrs.class [new file with mode: 0644]
examples/SetTime.class [new file with mode: 0644]
examples/SidCacheTest.class [new file with mode: 0644]
examples/SidCrawler.class [new file with mode: 0644]
examples/SlowRead.class [new file with mode: 0644]
examples/SlowWrite.class [new file with mode: 0644]
examples/SmbCrawler.class [new file with mode: 0644]
examples/SmbShell.class [new file with mode: 0644]
examples/SmbTableFile.class [new file with mode: 0644]
examples/SmbTableFileRecord.class [new file with mode: 0644]
examples/T2Crawler$CrawlerThread.class [new file with mode: 0644]
examples/T2Crawler$Semaphore.class [new file with mode: 0644]
examples/T2Crawler.class [new file with mode: 0644]
examples/TestRandomAccess$TestRecord.class [new file with mode: 0644]
examples/TestRandomAccess.class [new file with mode: 0644]
examples/TestSmbURL.class [new file with mode: 0644]
examples/TestUnicode.class [new file with mode: 0644]
examples/ThreadedNbtQuery$QThread.class [new file with mode: 0644]
examples/ThreadedNbtQuery.class [new file with mode: 0644]
examples/ThreadedSmbCrawler$DirEntry.class [new file with mode: 0644]
examples/ThreadedSmbCrawler$SmbCrawlerThread.class [new file with mode: 0644]
examples/ThreadedSmbCrawler.class [new file with mode: 0644]
examples/ThreadedUniQuery$QThread.class [new file with mode: 0644]
examples/ThreadedUniQuery.class [new file with mode: 0644]
examples/Torture1.class [new file with mode: 0644]
examples/Torture2.class [new file with mode: 0644]
examples/TortureTest5.class [new file with mode: 0644]
examples/TransactNamedPipe.class [new file with mode: 0644]
examples/URLTest.class [new file with mode: 0644]
examples/VerifyGuest.class [new file with mode: 0644]
examples/VerifyIO.class [new file with mode: 0644]
examples/VerifyReads.class [new file with mode: 0644]
examples/Worker.class [new file with mode: 0644]
examples/runtests.sh
patches/SetAccessTime.patch [new file with mode: 0644]
src/jcifs/dcerpc/DcerpcHandle.java
src/jcifs/ntlmssp/Type1Message.java
src/jcifs/ntlmssp/Type2Message.java
src/jcifs/ntlmssp/Type3Message.java
src/jcifs/smb/BufferCache.jav [new file with mode: 0644]
src/jcifs/smb/BufferCache.java
src/jcifs/smb/NtlmContext.java
src/jcifs/smb/SmbFile.java
src/jcifs/smb/SmbSession.java
src/jcifs/smb/SmbTransport.java
src/jcifs/smb/SmbTree.java
src/jcifs/smb/TestLocking.java [new file with mode: 0644]
src/jcifs/util/transport/Transport.java

index 04d014e..92e79d4 100644 (file)
@@ -1,3 +1,11 @@
+jcifs-1.3.13
+
+Locking throughout the transport layer has been rewritten. This should
+fix the long standing deadlock that has been reported in the past. Doubled
+size of transient input buffer to accommodate SMB_COM_NEGOTIATE response
+security blob (as observed with OSX Snow Leopard). A signing issue reading
+data from an EMC server has been fixed. NTLMSSP logging has been improved.
+
 Fri Aug 14 13:45:57 EDT 2009
 jcifs-1.3.12
 
index 0fae674..ac701a2 100644 (file)
--- a/build.xml
+++ b/build.xml
@@ -1,7 +1,7 @@
 <project name="jcifs" default="usage" basedir=".">
 
-    <property name="version" value="1.3.12"/>
-    <property name="reldate" value="Aug 14, 2009"/>
+    <property name="version" value="1.3.13"/>
+    <property name="reldate" value="Jan 5, 2010"/>
 
     <target name="usage">
         <echo>
diff --git a/examples/AclCrawler.class b/examples/AclCrawler.class
new file mode 100644 (file)
index 0000000..c12c07a
Binary files /dev/null and b/examples/AclCrawler.class differ
diff --git a/examples/AllocInfo.class b/examples/AllocInfo.class
new file mode 100644 (file)
index 0000000..d052675
Binary files /dev/null and b/examples/AllocInfo.class differ
diff --git a/examples/Append.class b/examples/Append.class
new file mode 100644 (file)
index 0000000..eadb65a
Binary files /dev/null and b/examples/Append.class differ
diff --git a/examples/AuthListFiles.class b/examples/AuthListFiles.class
new file mode 100644 (file)
index 0000000..0f9f3bf
Binary files /dev/null and b/examples/AuthListFiles.class differ
diff --git a/examples/CallNamedPipe.class b/examples/CallNamedPipe.class
new file mode 100644 (file)
index 0000000..1378730
Binary files /dev/null and b/examples/CallNamedPipe.class differ
diff --git a/examples/CopyTo.class b/examples/CopyTo.class
new file mode 100644 (file)
index 0000000..1eec536
Binary files /dev/null and b/examples/CopyTo.class differ
diff --git a/examples/CountPerms.class b/examples/CountPerms.class
new file mode 100644 (file)
index 0000000..6632e6e
Binary files /dev/null and b/examples/CountPerms.class differ
diff --git a/examples/CreateFile.class b/examples/CreateFile.class
new file mode 100644 (file)
index 0000000..9ae7ab1
Binary files /dev/null and b/examples/CreateFile.class differ
diff --git a/examples/Delete.class b/examples/Delete.class
new file mode 100644 (file)
index 0000000..b52be49
Binary files /dev/null and b/examples/Delete.class differ
diff --git a/examples/Equals.class b/examples/Equals.class
new file mode 100644 (file)
index 0000000..d1ea38a
Binary files /dev/null and b/examples/Equals.class differ
diff --git a/examples/Exists.class b/examples/Exists.class
new file mode 100644 (file)
index 0000000..9f03ca4
Binary files /dev/null and b/examples/Exists.class differ
diff --git a/examples/FileInfo.class b/examples/FileInfo.class
new file mode 100644 (file)
index 0000000..fbdcf11
Binary files /dev/null and b/examples/FileInfo.class differ
diff --git a/examples/FileOps.class b/examples/FileOps.class
new file mode 100644 (file)
index 0000000..9a0e176
Binary files /dev/null and b/examples/FileOps.class differ
diff --git a/examples/FilterFiles$BigFileFilter.class b/examples/FilterFiles$BigFileFilter.class
new file mode 100644 (file)
index 0000000..1cd1710
Binary files /dev/null and b/examples/FilterFiles$BigFileFilter.class differ
diff --git a/examples/FilterFiles$ShortFilenameFilter.class b/examples/FilterFiles$ShortFilenameFilter.class
new file mode 100644 (file)
index 0000000..0b43d22
Binary files /dev/null and b/examples/FilterFiles$ShortFilenameFilter.class differ
diff --git a/examples/FilterFiles.class b/examples/FilterFiles.class
new file mode 100644 (file)
index 0000000..e8f82a5
Binary files /dev/null and b/examples/FilterFiles.class differ
diff --git a/examples/Format.class b/examples/Format.class
new file mode 100644 (file)
index 0000000..998801f
Binary files /dev/null and b/examples/Format.class differ
diff --git a/examples/Get.class b/examples/Get.class
new file mode 100644 (file)
index 0000000..8192c4a
Binary files /dev/null and b/examples/Get.class differ
diff --git a/examples/GetDate.class b/examples/GetDate.class
new file mode 100644 (file)
index 0000000..8a82eaa
Binary files /dev/null and b/examples/GetDate.class differ
diff --git a/examples/GetDfsPath.class b/examples/GetDfsPath.class
new file mode 100644 (file)
index 0000000..751b59a
Binary files /dev/null and b/examples/GetDfsPath.class differ
diff --git a/examples/GetGroupMemberSidsFromURL.class b/examples/GetGroupMemberSidsFromURL.class
new file mode 100644 (file)
index 0000000..5334b1f
Binary files /dev/null and b/examples/GetGroupMemberSidsFromURL.class differ
diff --git a/examples/GetSecurity.class b/examples/GetSecurity.class
new file mode 100644 (file)
index 0000000..0f1b2d2
Binary files /dev/null and b/examples/GetSecurity.class differ
diff --git a/examples/GetShareSecurity.class b/examples/GetShareSecurity.class
new file mode 100644 (file)
index 0000000..6d0f992
Binary files /dev/null and b/examples/GetShareSecurity.class differ
diff --git a/examples/GetType.class b/examples/GetType.class
new file mode 100644 (file)
index 0000000..1028177
Binary files /dev/null and b/examples/GetType.class differ
diff --git a/examples/GetURL.class b/examples/GetURL.class
new file mode 100644 (file)
index 0000000..e473c42
Binary files /dev/null and b/examples/GetURL.class differ
diff --git a/examples/GrowWrite.class b/examples/GrowWrite.class
new file mode 100644 (file)
index 0000000..2d0ecbb
Binary files /dev/null and b/examples/GrowWrite.class differ
diff --git a/examples/HttpURL.class b/examples/HttpURL.class
new file mode 100644 (file)
index 0000000..55faf3c
Binary files /dev/null and b/examples/HttpURL.class differ
diff --git a/examples/Interleave$IThread.class b/examples/Interleave$IThread.class
new file mode 100644 (file)
index 0000000..12d7d51
Binary files /dev/null and b/examples/Interleave$IThread.class differ
diff --git a/examples/Interleave.class b/examples/Interleave.class
new file mode 100644 (file)
index 0000000..4ea28d5
Binary files /dev/null and b/examples/Interleave.class differ
diff --git a/examples/InterruptTest.class b/examples/InterruptTest.class
new file mode 100644 (file)
index 0000000..65da543
Binary files /dev/null and b/examples/InterruptTest.class differ
diff --git a/examples/IsDir.class b/examples/IsDir.class
new file mode 100644 (file)
index 0000000..712a60e
Binary files /dev/null and b/examples/IsDir.class differ
diff --git a/examples/LargeListFiles.class b/examples/LargeListFiles.class
new file mode 100644 (file)
index 0000000..83f6e76
Binary files /dev/null and b/examples/LargeListFiles.class differ
diff --git a/examples/Length.class b/examples/Length.class
new file mode 100644 (file)
index 0000000..b096ceb
Binary files /dev/null and b/examples/Length.class differ
diff --git a/examples/List.class b/examples/List.class
new file mode 100644 (file)
index 0000000..2d2e7b0
Binary files /dev/null and b/examples/List.class differ
diff --git a/examples/ListACL.class b/examples/ListACL.class
new file mode 100644 (file)
index 0000000..6c591f9
Binary files /dev/null and b/examples/ListACL.class differ
diff --git a/examples/ListFiles.class b/examples/ListFiles.class
new file mode 100644 (file)
index 0000000..996f03a
Binary files /dev/null and b/examples/ListFiles.class differ
diff --git a/examples/ListTypes.class b/examples/ListTypes.class
new file mode 100644 (file)
index 0000000..6da499c
Binary files /dev/null and b/examples/ListTypes.class differ
diff --git a/examples/Mkdir.class b/examples/Mkdir.class
new file mode 100644 (file)
index 0000000..4c96536
Binary files /dev/null and b/examples/Mkdir.class differ
diff --git a/examples/NodeStatus.class b/examples/NodeStatus.class
new file mode 100644 (file)
index 0000000..12e8052
Binary files /dev/null and b/examples/NodeStatus.class differ
diff --git a/examples/OpenExclusive.class b/examples/OpenExclusive.class
new file mode 100644 (file)
index 0000000..1802220
Binary files /dev/null and b/examples/OpenExclusive.class differ
diff --git a/examples/PeekNamedPipe$ReceiverThread.class b/examples/PeekNamedPipe$ReceiverThread.class
new file mode 100644 (file)
index 0000000..642652c
Binary files /dev/null and b/examples/PeekNamedPipe$ReceiverThread.class differ
diff --git a/examples/PeekNamedPipe.class b/examples/PeekNamedPipe.class
new file mode 100644 (file)
index 0000000..dcbf77f
Binary files /dev/null and b/examples/PeekNamedPipe.class differ
diff --git a/examples/PipeTalk$ReceiverThread.class b/examples/PipeTalk$ReceiverThread.class
new file mode 100644 (file)
index 0000000..d05ca7a
Binary files /dev/null and b/examples/PipeTalk$ReceiverThread.class differ
diff --git a/examples/PipeTalk.class b/examples/PipeTalk.class
new file mode 100644 (file)
index 0000000..d297503
Binary files /dev/null and b/examples/PipeTalk.class differ
diff --git a/examples/Put.class b/examples/Put.class
new file mode 100644 (file)
index 0000000..43b1e70
Binary files /dev/null and b/examples/Put.class differ
diff --git a/examples/Query.class b/examples/Query.class
new file mode 100644 (file)
index 0000000..0112790
Binary files /dev/null and b/examples/Query.class differ
diff --git a/examples/RenameTo.class b/examples/RenameTo.class
new file mode 100644 (file)
index 0000000..c169e35
Binary files /dev/null and b/examples/RenameTo.class differ
diff --git a/examples/SetAttrs.class b/examples/SetAttrs.class
new file mode 100644 (file)
index 0000000..d36bada
Binary files /dev/null and b/examples/SetAttrs.class differ
diff --git a/examples/SetTime.class b/examples/SetTime.class
new file mode 100644 (file)
index 0000000..79b5e36
Binary files /dev/null and b/examples/SetTime.class differ
diff --git a/examples/SidCacheTest.class b/examples/SidCacheTest.class
new file mode 100644 (file)
index 0000000..fd2890b
Binary files /dev/null and b/examples/SidCacheTest.class differ
diff --git a/examples/SidCrawler.class b/examples/SidCrawler.class
new file mode 100644 (file)
index 0000000..ba712c5
Binary files /dev/null and b/examples/SidCrawler.class differ
diff --git a/examples/SlowRead.class b/examples/SlowRead.class
new file mode 100644 (file)
index 0000000..8e87e10
Binary files /dev/null and b/examples/SlowRead.class differ
diff --git a/examples/SlowWrite.class b/examples/SlowWrite.class
new file mode 100644 (file)
index 0000000..84a1cff
Binary files /dev/null and b/examples/SlowWrite.class differ
diff --git a/examples/SmbCrawler.class b/examples/SmbCrawler.class
new file mode 100644 (file)
index 0000000..efdb5e3
Binary files /dev/null and b/examples/SmbCrawler.class differ
diff --git a/examples/SmbShell.class b/examples/SmbShell.class
new file mode 100644 (file)
index 0000000..b9096fa
Binary files /dev/null and b/examples/SmbShell.class differ
diff --git a/examples/SmbTableFile.class b/examples/SmbTableFile.class
new file mode 100644 (file)
index 0000000..c1bfe46
Binary files /dev/null and b/examples/SmbTableFile.class differ
diff --git a/examples/SmbTableFileRecord.class b/examples/SmbTableFileRecord.class
new file mode 100644 (file)
index 0000000..b5d68ff
Binary files /dev/null and b/examples/SmbTableFileRecord.class differ
diff --git a/examples/T2Crawler$CrawlerThread.class b/examples/T2Crawler$CrawlerThread.class
new file mode 100644 (file)
index 0000000..0b40e5c
Binary files /dev/null and b/examples/T2Crawler$CrawlerThread.class differ
diff --git a/examples/T2Crawler$Semaphore.class b/examples/T2Crawler$Semaphore.class
new file mode 100644 (file)
index 0000000..af3b771
Binary files /dev/null and b/examples/T2Crawler$Semaphore.class differ
diff --git a/examples/T2Crawler.class b/examples/T2Crawler.class
new file mode 100644 (file)
index 0000000..4176b41
Binary files /dev/null and b/examples/T2Crawler.class differ
diff --git a/examples/TestRandomAccess$TestRecord.class b/examples/TestRandomAccess$TestRecord.class
new file mode 100644 (file)
index 0000000..872eb31
Binary files /dev/null and b/examples/TestRandomAccess$TestRecord.class differ
diff --git a/examples/TestRandomAccess.class b/examples/TestRandomAccess.class
new file mode 100644 (file)
index 0000000..5fdf0df
Binary files /dev/null and b/examples/TestRandomAccess.class differ
diff --git a/examples/TestSmbURL.class b/examples/TestSmbURL.class
new file mode 100644 (file)
index 0000000..d73dd32
Binary files /dev/null and b/examples/TestSmbURL.class differ
diff --git a/examples/TestUnicode.class b/examples/TestUnicode.class
new file mode 100644 (file)
index 0000000..92304e8
Binary files /dev/null and b/examples/TestUnicode.class differ
diff --git a/examples/ThreadedNbtQuery$QThread.class b/examples/ThreadedNbtQuery$QThread.class
new file mode 100644 (file)
index 0000000..1259b6d
Binary files /dev/null and b/examples/ThreadedNbtQuery$QThread.class differ
diff --git a/examples/ThreadedNbtQuery.class b/examples/ThreadedNbtQuery.class
new file mode 100644 (file)
index 0000000..0d21e06
Binary files /dev/null and b/examples/ThreadedNbtQuery.class differ
diff --git a/examples/ThreadedSmbCrawler$DirEntry.class b/examples/ThreadedSmbCrawler$DirEntry.class
new file mode 100644 (file)
index 0000000..f849d93
Binary files /dev/null and b/examples/ThreadedSmbCrawler$DirEntry.class differ
diff --git a/examples/ThreadedSmbCrawler$SmbCrawlerThread.class b/examples/ThreadedSmbCrawler$SmbCrawlerThread.class
new file mode 100644 (file)
index 0000000..a95e988
Binary files /dev/null and b/examples/ThreadedSmbCrawler$SmbCrawlerThread.class differ
diff --git a/examples/ThreadedSmbCrawler.class b/examples/ThreadedSmbCrawler.class
new file mode 100644 (file)
index 0000000..e0747bf
Binary files /dev/null and b/examples/ThreadedSmbCrawler.class differ
diff --git a/examples/ThreadedUniQuery$QThread.class b/examples/ThreadedUniQuery$QThread.class
new file mode 100644 (file)
index 0000000..02d02e0
Binary files /dev/null and b/examples/ThreadedUniQuery$QThread.class differ
diff --git a/examples/ThreadedUniQuery.class b/examples/ThreadedUniQuery.class
new file mode 100644 (file)
index 0000000..08632f7
Binary files /dev/null and b/examples/ThreadedUniQuery.class differ
diff --git a/examples/Torture1.class b/examples/Torture1.class
new file mode 100644 (file)
index 0000000..72d5f77
Binary files /dev/null and b/examples/Torture1.class differ
diff --git a/examples/Torture2.class b/examples/Torture2.class
new file mode 100644 (file)
index 0000000..e688b4f
Binary files /dev/null and b/examples/Torture2.class differ
diff --git a/examples/TortureTest5.class b/examples/TortureTest5.class
new file mode 100644 (file)
index 0000000..cadf7c2
Binary files /dev/null and b/examples/TortureTest5.class differ
diff --git a/examples/TransactNamedPipe.class b/examples/TransactNamedPipe.class
new file mode 100644 (file)
index 0000000..faea615
Binary files /dev/null and b/examples/TransactNamedPipe.class differ
diff --git a/examples/URLTest.class b/examples/URLTest.class
new file mode 100644 (file)
index 0000000..5263435
Binary files /dev/null and b/examples/URLTest.class differ
diff --git a/examples/VerifyGuest.class b/examples/VerifyGuest.class
new file mode 100644 (file)
index 0000000..6a8ce08
Binary files /dev/null and b/examples/VerifyGuest.class differ
diff --git a/examples/VerifyIO.class b/examples/VerifyIO.class
new file mode 100644 (file)
index 0000000..1168477
Binary files /dev/null and b/examples/VerifyIO.class differ
diff --git a/examples/VerifyReads.class b/examples/VerifyReads.class
new file mode 100644 (file)
index 0000000..ff0d0a1
Binary files /dev/null and b/examples/VerifyReads.class differ
diff --git a/examples/Worker.class b/examples/Worker.class
new file mode 100644 (file)
index 0000000..25fa3b2
Binary files /dev/null and b/examples/Worker.class differ
index d648054..c44872f 100644 (file)
@@ -16,7 +16,7 @@ SERVER=w.net
 SHARE=root2
 DIR=test
 
-# smb://fs1.w.net/DFSStandaloneRoot/DFSStandaloneLink/test/
+# smb://fs4.w.net/DFSStandaloneRoot/DFSStandaloneLink/test/
 # smb://dc1.w.net/root2/link2/test/
 # smb://dc1.w.net/tmp/test/
 # smb://dc3.x.net/tmp/test/
diff --git a/patches/SetAccessTime.patch b/patches/SetAccessTime.patch
new file mode 100644 (file)
index 0000000..71bdb55
--- /dev/null
@@ -0,0 +1,101 @@
+--- jcifs_1.3.12/src/jcifs/smb/SmbFile.java
++++ jcifs/src/jcifs/smb/SmbFile.java
+@@ -2564,6 +2564,21 @@
+         attrExpiration = 0;
+     }
++    void setPathInformation( int attrs, long ctime, long atime, long mtime ) throws SmbException {
++    int f, dir;
++
++    exists();
++    dir = attributes & ATTR_DIRECTORY;
++
++    f = open0( O_RDONLY, FILE_WRITE_ATTRIBUTES,
++    dir, dir != 0 ? 0x0001 : 0x0040 );
++    send( new Trans2SetFileInformation( f, attrs | dir, ctime, atime, mtime ),
++    new Trans2SetFileInformationResponse() );
++    close( f, 0L );
++
++    attrExpiration = 0;
++    }
++
+ /**
+  * Set the create time of the file. The time is specified as milliseconds
+  * from Jan 1, 1970 which is the same as that which is returned by the
+@@ -2581,6 +2596,22 @@
+         setPathInformation( 0, time, 0L );
+     }
+ /**
++ * Set the access time of the file. The time is specified as milliseconds
++ * from Jan 1, 1970 which is the same as that which is returned by the
++ * <tt>createTime()</tt> method.
++ * <p/>
++ * This method does not apply to workgroups, servers, or shares.
++ *
++ * @param time the create time as milliseconds since Jan 1, 1970
++ */
++    public void setAccessTime( long time ) throws SmbException {
++        if( getUncPath0().length() == 1 ) {
++            throw new SmbException( "Invalid operation for workgroups, servers, or shares" );
++        }
++
++        setPathInformation( 0, 0L, time, 0L );
++    }
++/**
+  * Set the last modified time of the file. The time is specified as milliseconds
+  * from Jan 1, 1970 which is the same as that which is returned by the
+  * <tt>lastModified()</tt>, <tt>getLastModified()</tt>, and <tt>getDate()</tt> methods.
+--- jcifs_1.3.12/src/jcifs/smb/Trans2SetFileInformation.java
++++ jcifs/src/jcifs/smb/Trans2SetFileInformation.java
+@@ -25,6 +25,7 @@
+     private int fid;
+     private int attributes;
+     private long createTime, lastWriteTime;
++    private long accessTime;
+     Trans2SetFileInformation( int fid, int attributes, long createTime, long lastWriteTime ) {
+         this.fid = fid;
+@@ -38,6 +39,19 @@
+         maxSetupCount = (byte)0x00;
+     }
++     Trans2SetFileInformation( int fid, int attributes, long createTime, long accessTime, long lastWriteTime ) {
++        this.fid = fid;
++        this.attributes = attributes;
++        this.accessTime = accessTime;
++        this.createTime = createTime;
++        this.lastWriteTime = lastWriteTime;
++        command = SMB_COM_TRANSACTION2;
++        subCommand = TRANS2_SET_FILE_INFORMATION;
++        maxParameterCount = 6;
++        maxDataCount = 0;
++        maxSetupCount = (byte)0x00;
++    }
++
+     int writeSetupWireFormat( byte[] dst, int dstIndex ) {
+         dst[dstIndex++] = subCommand;
+         dst[dstIndex++] = (byte)0x00;
+@@ -58,13 +72,22 @@
+     int writeDataWireFormat( byte[] dst, int dstIndex ) {
+         int start = dstIndex;
++        // create time
+         writeTime( createTime, dst, dstIndex ); dstIndex += 8;
+-        writeInt8( 0L, dst, dstIndex ); dstIndex += 8;
++
++        // access time
++        writeInt8( accessTime, dst, dstIndex ); dstIndex += 8;
++
++        // last write time [modification]
+         writeTime( lastWriteTime, dst, dstIndex ); dstIndex += 8;
++
++        // change time
+         writeInt8( 0L, dst, dstIndex ); dstIndex += 8;
++
+ /* Samba 2.2.7 needs ATTR_NORMAL
+  */
+         writeInt2( 0x80 | attributes, dst, dstIndex ); dstIndex += 2; 
++
+                                         /* 6 zeros observed with NT */
+         writeInt8( 0L, dst, dstIndex ); dstIndex += 6;
index 72bd37b..279dd16 100644 (file)
@@ -140,11 +140,7 @@ public abstract class DcerpcHandle implements DcerpcConstants {
 
         isDirect = msg instanceof DcerpcBind;
 
-        try {
-            stub = jcifs.smb.BufferCache.getBuffer();
-        } catch (InterruptedException ie) {
-            throw new IOException(ie.getMessage());
-        }
+        stub = jcifs.smb.BufferCache.getBuffer();
         try {
             int off, tot, n;
 
index 754575b..450fb2b 100644 (file)
@@ -169,29 +169,9 @@ public class Type1Message extends NtlmMessage {
     public String toString() {
         String suppliedDomain = getSuppliedDomain();
         String suppliedWorkstation = getSuppliedWorkstation();
-        int flags = getFlags();
-        StringBuffer buffer = new StringBuffer();
-        if (suppliedDomain != null) {
-            buffer.append("suppliedDomain: ").append(suppliedDomain);
-        }
-        if (suppliedWorkstation != null) {
-            if (buffer.length() > 0) buffer.append("; ");
-            buffer.append("suppliedWorkstation: ").append(suppliedWorkstation);
-        }
-        if (flags != 0) {
-            if (buffer.length() > 0) buffer.append("; ");
-            buffer.append("flags: ");
-            buffer.append("0x");
-            buffer.append(Integer.toHexString((flags >> 28) & 0x0f));
-            buffer.append(Integer.toHexString((flags >> 24) & 0x0f));
-            buffer.append(Integer.toHexString((flags >> 20) & 0x0f));
-            buffer.append(Integer.toHexString((flags >> 16) & 0x0f));
-            buffer.append(Integer.toHexString((flags >> 12) & 0x0f));
-            buffer.append(Integer.toHexString((flags >> 8) & 0x0f));
-            buffer.append(Integer.toHexString((flags >> 4) & 0x0f));
-            buffer.append(Integer.toHexString(flags & 0x0f));
-        }
-        return buffer.toString();
+        return "Type1Message[suppliedDomain=" + (suppliedDomain == null ? "null" : suppliedDomain) +
+                ",suppliedWorkstation=" + (suppliedWorkstation == null ? "null" : suppliedWorkstation) +
+                ",flags=0x" + jcifs.util.Hexdump.toHexString(getFlags(), 8) + "]";
     }
 
     /**
index 355a0b3..26fe976 100644 (file)
@@ -276,53 +276,12 @@ public class Type2Message extends NtlmMessage {
         byte[] challenge = getChallenge();
         byte[] context = getContext();
         byte[] targetInformation = getTargetInformation();
-        int flags = getFlags();
-        StringBuffer buffer = new StringBuffer();
-        if (target != null) {
-            buffer.append("target: ").append(target);
-        }
-        if (challenge != null) {
-            if (buffer.length() > 0) buffer.append("; ");
-            buffer.append("challenge: ");
-            buffer.append("0x");
-            for (int i = 0; i < challenge.length; i++) {
-                buffer.append(Integer.toHexString((challenge[i] >> 4) & 0x0f));
-                buffer.append(Integer.toHexString(challenge[i] & 0x0f));
-            }
-        }
-        if (context != null) {
-            if (buffer.length() > 0) buffer.append("; ");
-            buffer.append("context: ");
-            buffer.append("0x");
-            for (int i = 0; i < context.length; i++) {
-                buffer.append(Integer.toHexString((context[i] >> 4) & 0x0f));
-                buffer.append(Integer.toHexString(context[i] & 0x0f));
-            }
-        }
-        if (targetInformation != null) {
-            if (buffer.length() > 0) buffer.append("; ");
-            buffer.append("targetInformation: ");
-            buffer.append("0x");
-            for (int i = 0; i < targetInformation.length; i++) {
-                buffer.append(Integer.toHexString((targetInformation[i] >> 4) &
-                        0x0f));
-                buffer.append(Integer.toHexString(targetInformation[i] & 0x0f));
-            }
-        }
-        if (flags != 0) {
-            if (buffer.length() > 0) buffer.append("; ");
-            buffer.append("flags: ");
-            buffer.append("0x");
-            buffer.append(Integer.toHexString((flags >> 28) & 0x0f));
-            buffer.append(Integer.toHexString((flags >> 24) & 0x0f));
-            buffer.append(Integer.toHexString((flags >> 20) & 0x0f));
-            buffer.append(Integer.toHexString((flags >> 16) & 0x0f));
-            buffer.append(Integer.toHexString((flags >> 12) & 0x0f));
-            buffer.append(Integer.toHexString((flags >> 8) & 0x0f));
-            buffer.append(Integer.toHexString((flags >> 4) & 0x0f));
-            buffer.append(Integer.toHexString(flags & 0x0f));
-        }
-        return buffer.toString();
+
+        return "Type2Message[target=" + target +
+            ",challenge=" + (challenge == null ? "null" : "<" + challenge.length + " bytes>") +
+            ",context=" + (context == null ? "null" : "<" + context.length + " bytes>") +
+            ",targetInformation=" + (targetInformation == null ? "null" : "<" + targetInformation.length + " bytes>") +
+            ",flags=0x" + jcifs.util.Hexdump.toHexString(getFlags(), 8) + "]";
     }
 
     /**
index 8bfe930..5f74054 100644 (file)
@@ -489,60 +489,14 @@ public class Type3Message extends NtlmMessage {
         byte[] lmResponse = getLMResponse();
         byte[] ntResponse = getNTResponse();
         byte[] sessionKey = getSessionKey();
-        int flags = getFlags();
-        StringBuffer buffer = new StringBuffer();
-        if (domain != null) {
-            buffer.append("domain: ").append(domain);
-        }
-        if (user != null) {
-            if (buffer.length() > 0) buffer.append("; ");
-            buffer.append("user: ").append(user);
-        }
-        if (workstation != null) {
-            if (buffer.length() > 0) buffer.append("; ");
-            buffer.append("workstation: ").append(workstation);
-        }
-        if (lmResponse != null) {
-            if (buffer.length() > 0) buffer.append("; ");
-            buffer.append("lmResponse: ");
-            buffer.append("0x");
-            for (int i = 0; i < lmResponse.length; i++) {
-                buffer.append(Integer.toHexString((lmResponse[i] >> 4) & 0x0f));
-                buffer.append(Integer.toHexString(lmResponse[i] & 0x0f));
-            }
-        }
-        if (ntResponse != null) {
-            if (buffer.length() > 0) buffer.append("; ");
-            buffer.append("ntResponse: ");
-            buffer.append("0x");
-            for (int i = 0; i < ntResponse.length; i++) {
-                buffer.append(Integer.toHexString((ntResponse[i] >> 4) & 0x0f));
-                buffer.append(Integer.toHexString(ntResponse[i] & 0x0f));
-            }
-        }
-        if (sessionKey != null) {
-            if (buffer.length() > 0) buffer.append("; ");
-            buffer.append("sessionKey: ");
-            buffer.append("0x");
-            for (int i = 0; i < sessionKey.length; i++) {
-                buffer.append(Integer.toHexString((sessionKey[i] >> 4) & 0x0f));
-                buffer.append(Integer.toHexString(sessionKey[i] & 0x0f));
-            }
-        }
-        if (flags != 0) {
-            if (buffer.length() > 0) buffer.append("; ");
-            buffer.append("flags: ");
-            buffer.append("0x");
-            buffer.append(Integer.toHexString((flags >> 28) & 0x0f));
-            buffer.append(Integer.toHexString((flags >> 24) & 0x0f));
-            buffer.append(Integer.toHexString((flags >> 20) & 0x0f));
-            buffer.append(Integer.toHexString((flags >> 16) & 0x0f));
-            buffer.append(Integer.toHexString((flags >> 12) & 0x0f));
-            buffer.append(Integer.toHexString((flags >> 8) & 0x0f));
-            buffer.append(Integer.toHexString((flags >> 4) & 0x0f));
-            buffer.append(Integer.toHexString(flags & 0x0f));
-        }
-        return buffer.toString();
+
+        return "Type3Message[domain=" + domain +
+            ",user=" + user +
+            ",workstation=" + workstation +
+            ",lmResponse=" + (lmResponse == null ? "null" : "<" + lmResponse.length + " bytes>") +
+            ",ntResponse=" + (ntResponse == null ? "null" : "<" + ntResponse.length + " bytes>") +
+            ",sessionKey=" + (sessionKey == null ? "null" : "<" + sessionKey.length + " bytes>") +
+            ",flags=0x" + jcifs.util.Hexdump.toHexString(getFlags(), 8) + "]";
     }
 
     /**
diff --git a/src/jcifs/smb/BufferCache.jav b/src/jcifs/smb/BufferCache.jav
new file mode 100644 (file)
index 0000000..1dea6bf
--- /dev/null
@@ -0,0 +1,83 @@
+/* jcifs smb client library in Java
+ * Copyright (C) 2000  "Michael B. Allen" <jcifs at samba dot org>
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library 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
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+package jcifs.smb;
+
+import jcifs.Config;
+
+public class BufferCache {
+
+    private static final int MAX_BUFFERS = Config.getInt( "jcifs.smb.maxBuffers", 16 );
+
+    static Object[] cache = new Object[MAX_BUFFERS];
+    private static int freeBuffers = 0;
+
+    private static byte[] getBuffer0() {
+        byte[] buf;
+
+        if (freeBuffers > 0) {
+            for (int i = 0; i < MAX_BUFFERS; i++) {
+                if( cache[i] != null ) {
+                    buf = (byte[])cache[i];
+                    cache[i] = null;
+                    freeBuffers--;
+                    return buf;
+                }
+            }
+        }
+
+        buf = new byte[SmbComTransaction.TRANSACTION_BUF_SIZE];
+
+        return buf;
+    }
+
+    static void getBuffers( SmbComTransaction req,
+                    SmbComTransactionResponse rsp ) throws InterruptedException {
+        synchronized( cache ) {
+            if (freeBuffers < 2) {
+                /* The first time this is called we always wait because freeBuffers
+                 * will be 0. But after a few calls to releaseBuffer, threads will
+                 * no longer wait.
+                 */
+                cache.wait(100);
+            }
+            req.txn_buf = getBuffer0();
+            rsp.txn_buf = getBuffer0();
+        }
+    }
+    static public byte[] getBuffer() throws InterruptedException {
+        synchronized( cache ) {
+            if (freeBuffers < 1) {
+                cache.wait(100);
+            }
+            return getBuffer0();
+        }
+    }
+    static public void releaseBuffer( byte[] buf ) {
+        synchronized( cache ) {
+            for (int i = 0; i < MAX_BUFFERS; i++) {
+                if (cache[i] == null) {
+                    cache[i] = buf;
+                    freeBuffers++;
+                    cache.notify();
+                    return;
+                }
+            }
+        }
+    }
+}
index 14fa4fa..dce2525 100644 (file)
@@ -25,55 +25,43 @@ public class BufferCache {
     private static final int MAX_BUFFERS = Config.getInt( "jcifs.smb.maxBuffers", 16 );
 
     static Object[] cache = new Object[MAX_BUFFERS];
-    private static int numBuffers = 0;
     private static int freeBuffers = 0;
 
-    private static byte[] getBuffer0() {
-        byte[] buf;
+    static public byte[] getBuffer() {
+        synchronized( cache ) {
+            byte[] buf;
 
-        if (freeBuffers > 0) {
-            for (int i = 0; i < MAX_BUFFERS; i++) {
-                if( cache[i] != null ) {
-                    buf = (byte[])cache[i];
-                    cache[i] = null;
-                    freeBuffers--;
-                    return buf;
+            if (freeBuffers > 0) {
+                for (int i = 0; i < MAX_BUFFERS; i++) {
+                    if( cache[i] != null ) {
+                        buf = (byte[])cache[i];
+                        cache[i] = null;
+                        freeBuffers--;
+                        return buf;
+                    }
                 }
             }
-        }
 
-        buf = new byte[SmbComTransaction.TRANSACTION_BUF_SIZE];
-        numBuffers++;
-
-        return buf;
-    }
+            buf = new byte[SmbComTransaction.TRANSACTION_BUF_SIZE];
 
-    static void getBuffers( SmbComTransaction req,
-                    SmbComTransactionResponse rsp ) throws InterruptedException {
-        synchronized( cache ) {
-            while ((freeBuffers + (MAX_BUFFERS - numBuffers)) < 2) {
-                cache.wait();
-            }
-            req.txn_buf = getBuffer0();
-            rsp.txn_buf = getBuffer0();
+            return buf;
         }
     }
-    static public byte[] getBuffer() throws InterruptedException {
+    static void getBuffers( SmbComTransaction req, SmbComTransactionResponse rsp ) {
         synchronized( cache ) {
-            while ((freeBuffers + (MAX_BUFFERS - numBuffers)) < 1) {
-                cache.wait();
-            }
-            return getBuffer0();
+            req.txn_buf = getBuffer();
+            rsp.txn_buf = getBuffer();
         }
     }
     static public void releaseBuffer( byte[] buf ) {
         synchronized( cache ) {
-            for (int i = 0; i < MAX_BUFFERS; i++) {
-                if (cache[i] == null) {
-                    cache[i] = buf;
-                    freeBuffers++;
-                    cache.notify();
-                    return;
+            if (freeBuffers < MAX_BUFFERS) {
+                for (int i = 0; i < MAX_BUFFERS; i++) {
+                    if (cache[i] == null) {
+                        cache[i] = buf;
+                        freeBuffers++;
+                        return;
+                    }
                 }
             }
         }
index 9484dd6..84217a7 100644 (file)
@@ -21,6 +21,8 @@ package jcifs.smb;
 import java.io.IOException;
 import java.security.*;
 import jcifs.ntlmssp.*;
+import jcifs.util.LogStream;
+import jcifs.util.Hexdump;
 
 /**
 For initiating NTLM authentication (including NTLMv2). If you want to add NTLMv2 authentication support to something this is what you want to use. See the code for details. Note that JCIFS does not implement the acceptor side of NTLM authentication.
@@ -28,6 +30,7 @@ For initiating NTLM authentication (including NTLMv2). If you want to add NTLMv2
 
 public class NtlmContext {
 
+
     NtlmPasswordAuthentication auth;
     int ntlmsspFlags;
     String workstation;
@@ -35,6 +38,7 @@ public class NtlmContext {
     byte[] serverChallenge = null;
     byte[] signingKey = null;
     int state = 1;
+    LogStream log;
 
     public NtlmContext(NtlmPasswordAuthentication auth, boolean doSigning) {
         this.auth = auth;
@@ -48,6 +52,29 @@ public class NtlmContext {
                 NtlmFlags.NTLMSSP_NEGOTIATE_KEY_EXCH;
         }
         this.workstation = Type1Message.getDefaultWorkstation();
+        log = LogStream.getInstance();
+    }
+
+    public String toString() {
+        String ret = "NtlmContext[auth=" + auth +
+            ",ntlmsspFlags=0x" + Hexdump.toHexString(ntlmsspFlags, 8) +
+            ",workstation=" + workstation +
+            ",isEstablished=" + isEstablished +
+            ",state=" + state +
+            ",serverChallenge=";
+        if (serverChallenge == null) {
+            ret += "null";
+        } else {
+            ret += Hexdump.toHexString(serverChallenge, 0, serverChallenge.length * 2);
+        }
+        ret += ",signingKey=";
+        if (signingKey == null) {
+            ret += "null";
+        } else {
+            ret += Hexdump.toHexString(signingKey, 0, signingKey.length * 2);
+        }
+        ret += "]";
+        return ret;
     }
 
     public boolean isEstablished() {
@@ -67,12 +94,25 @@ public class NtlmContext {
             case 1:
                 Type1Message msg1 = new Type1Message(ntlmsspFlags, auth.getDomain(), workstation);
                 token = msg1.toByteArray();
+
+                if (log.level >= 4) {
+                    log.println(msg1);
+                    if (log.level >= 6)
+                        Hexdump.hexdump(log, token, 0, token.length);
+                }
+
                 state++;
                 break;
             case 2:
                 try {
                     Type2Message msg2 = new Type2Message(token);
 
+                    if (log.level >= 4) {
+                        log.println(msg2);
+                        if (log.level >= 6)
+                            Hexdump.hexdump(log, token, 0, token.length);
+                    }
+
                     serverChallenge = msg2.getChallenge();
                     ntlmsspFlags &= msg2.getFlags();
 
@@ -84,6 +124,12 @@ public class NtlmContext {
                                 ntlmsspFlags);
                     token = msg3.toByteArray();
 
+                    if (log.level >= 4) {
+                        log.println(msg3);
+                        if (log.level >= 6)
+                            Hexdump.hexdump(log, token, 0, token.length);
+                    }
+
                     if ((ntlmsspFlags & NtlmFlags.NTLMSSP_NEGOTIATE_SIGN) != 0)
                         signingKey = msg3.getMasterKey();
 
index 8ff3a44..07fdf22 100644 (file)
@@ -423,7 +423,7 @@ public class SmbFile extends URLConnection implements SmbConstants {
     protected static Dfs dfs;
 
     NtlmPasswordAuthentication auth; // Cannot be null
-    SmbTree tree = null;             // Initially null; may be !tree.treeConnected
+    SmbTree tree = null;             // Initially null
     String unc;                      // Initially null; set by getUncPath; never ends with '/'
     int fid;                         // Initially 0; set by open()
     int type;
@@ -889,7 +889,7 @@ int addressIndex;
         String hostName = getServerWithDfs();
         tree.inDomainDfs = dfs.resolve(hostName, tree.share, null, auth) != null;
         if (tree.inDomainDfs) {
-            tree.treeConnected = true;
+            tree.connectionState = 2;
         }
 
         try {
@@ -912,7 +912,7 @@ int addressIndex;
                 tree = ssn.getSmbTree(share, null);
                 tree.inDomainDfs = dfs.resolve(hostName, tree.share, null, auth) != null;
                 if (tree.inDomainDfs) {
-                    tree.treeConnected = true;
+                    tree.connectionState = 2;
                 }
                 tree.treeConnect(null, null);
             } else {
@@ -950,7 +950,7 @@ int addressIndex;
         }
     }
     boolean isConnected() {
-        return tree != null && tree.treeConnected;
+        return tree != null && tree.connectionState == 2;
     }
     int open0( int flags, int access, int attrs, int options ) throws SmbException {
         int f;
@@ -994,7 +994,7 @@ if (this instanceof SmbNamedPipe) {
         tree_num = tree.tree_num;
     }
     boolean isOpen() {
-        boolean ans =  opened && isConnected() && tree_num == tree.tree_num;
+        boolean ans = opened && isConnected() && tree_num == tree.tree_num;
         return ans;
     }
     void close( int f, long lastWriteTime ) throws SmbException {
index 1f48337..60646f3 100644 (file)
@@ -70,48 +70,48 @@ public final class SmbSession {
         if( DOMAIN == null ) {
             throw new SmbException( "A domain was not specified" );
         }
-        synchronized (DOMAIN) {
+synchronized (DOMAIN) {
             long now = System.currentTimeMillis();
-int retry = 1;
-
-do {
-            if (dc_list_expiration < now) {
-                NbtAddress[] list = NbtAddress.getAllByName( DOMAIN, 0x1C, null, null );
-                dc_list_expiration = now + CACHE_POLICY * 1000L;
-                if (list != null && list.length > 0) {
-                    dc_list = list;
-                } else { /* keep using the old list */
-                    dc_list_expiration = now + 1000 * 60 * 15; /* 15 min */
-                    if (SmbTransport.log.level >= 2) {
-                        SmbTransport.log.println( "Failed to retrieve DC list from WINS" );
+            int retry = 1;
+
+            do {
+                if (dc_list_expiration < now) {
+                    NbtAddress[] list = NbtAddress.getAllByName( DOMAIN, 0x1C, null, null );
+                    dc_list_expiration = now + CACHE_POLICY * 1000L;
+                    if (list != null && list.length > 0) {
+                        dc_list = list;
+                    } else { /* keep using the old list */
+                        dc_list_expiration = now + 1000 * 60 * 15; /* 15 min */
+                        if (SmbTransport.log.level >= 2) {
+                            SmbTransport.log.println( "Failed to retrieve DC list from WINS" );
+                        }
                     }
                 }
-            }
 
-            int max = Math.min( dc_list.length, LOOKUP_RESP_LIMIT );
-            for (int j = 0; j < max; j++) {
-                int i = dc_list_counter++ % max;
-                if (dc_list[i] != null) {
-                    try {
-                        return interrogate( dc_list[i] );
-                    } catch (SmbException se) {
-                        if (SmbTransport.log.level >= 2) {
-                            SmbTransport.log.println( "Failed validate DC: " + dc_list[i] );
-                            if (SmbTransport.log.level > 2)
-                                se.printStackTrace( SmbTransport.log );
+                int max = Math.min( dc_list.length, LOOKUP_RESP_LIMIT );
+                for (int j = 0; j < max; j++) {
+                    int i = dc_list_counter++ % max;
+                    if (dc_list[i] != null) {
+                        try {
+                            return interrogate( dc_list[i] );
+                        } catch (SmbException se) {
+                            if (SmbTransport.log.level >= 2) {
+                                SmbTransport.log.println( "Failed validate DC: " + dc_list[i] );
+                                if (SmbTransport.log.level > 2)
+                                    se.printStackTrace( SmbTransport.log );
+                            }
                         }
+                        dc_list[i] = null;
                     }
-                    dc_list[i] = null;
                 }
-            }
 
-/* No DCs found, for retieval of list by expiring it and retry.
- */
-            dc_list_expiration = 0;
-} while (retry-- > 0);
+                /* No DCs found, for retieval of list by expiring it and retry.
                */
+                dc_list_expiration = 0;
+            } while (retry-- > 0);
 
             dc_list_expiration = now + 1000 * 60 * 15; /* 15 min */
-        }
+}
 
         throw new UnknownHostException(
                 "Failed to negotiate with a suitable domain controller for " + DOMAIN );
@@ -158,9 +158,14 @@ do {
         }
     }
 
-    private int uid;
+    /* 0 - not connected
+     * 1 - connecting
+     * 2 - connected
+     * 3 - disconnecting
+     */
+    int connectionState;
+    int uid;
     Vector trees;
-    private boolean sessionSetup;
     // Transport parameters allows trans to be removed from CONNECTIONS
     private UniAddress address;
     private int port, localPort;
@@ -179,6 +184,7 @@ do {
         this.localPort = localPort;
         this.auth = auth;
         trees = new Vector();
+        connectionState = 0;
     }
 
     synchronized SmbTree getSmbTree( String share, String service ) {
@@ -208,31 +214,32 @@ do {
     }
     void send( ServerMessageBlock request,
                             ServerMessageBlock response ) throws SmbException {
+synchronized (transport()) {
         if( response != null ) {
             response.received = false;
         }
 
-        synchronized(transport.setupDiscoLock) {
-            expiration = System.currentTimeMillis() + SmbTransport.SO_TIMEOUT;
-            sessionSetup( request, response );
-            if( response != null && response.received ) {
-                return;
-            }
-            request.uid = uid;
-            request.auth = auth;
-            try {
-                transport.send( request, response );
-            } catch (SmbException se) {
-                if (request instanceof SmbComTreeConnectAndX) {
-                    logoff(true);
-                }
-                request.digest = null;
-                throw se;
+        expiration = System.currentTimeMillis() + SmbTransport.SO_TIMEOUT;
+        sessionSetup( request, response );
+        if( response != null && response.received ) {
+            return;
+        }
+        request.uid = uid;
+        request.auth = auth;
+        try {
+            transport.send( request, response );
+        } catch (SmbException se) {
+            if (request instanceof SmbComTreeConnectAndX) {
+                logoff(true);
             }
+            request.digest = null;
+            throw se;
         }
+}
     }
     void sessionSetup( ServerMessageBlock andx,
-                            ServerMessageBlock andxResponse ) throws SmbException {
+                ServerMessageBlock andxResponse ) throws SmbException {
+synchronized (transport()) {
         NtlmContext nctx = null;
         SmbException ex = null;
         SmbComSessionSetupAndX request;
@@ -240,166 +247,187 @@ do {
         byte[] token = new byte[0];
         int state = 10;
 
-synchronized( transport() ) {
-        if( sessionSetup ) {
-            return;
+        while (connectionState != 0) {
+            if (connectionState == 2 || connectionState == 3) // connected or disconnecting
+                return;
+            try {
+                transport.wait();
+            } catch (InterruptedException ie) {
+                throw new SmbException(ie.getMessage(), ie);
+            }
         }
+        connectionState = 1; // trying ...
 
-        transport.connect();
-
-        /*
-         * Session Setup And X Request / Response
-         */
-
-        if( transport.log.level >= 4 )
-            transport.log.println( "sessionSetup: accountName=" + auth.username + ",primaryDomain=" + auth.domain );
-
-        /* We explicitly set uid to 0 here to prevent a new
-         * SMB_COM_SESSION_SETUP_ANDX from having it's uid set to an
-         * old value when the session is re-established. Otherwise a
-         * "The parameter is incorrect" error can occur.
-         */
-        uid = 0;
-
-        do {
-            switch (state) {
-                case 10: /* NTLM */
-                    if (auth != NtlmPasswordAuthentication.ANONYMOUS &&
-                            transport.hasCapability(SmbConstants.CAP_EXTENDED_SECURITY)) {
-                        state = 20; /* NTLMSSP */
-                        break;
-                    }
-
-                    request = new SmbComSessionSetupAndX( this, andx, auth );
-                    response = new SmbComSessionSetupAndXResponse( andxResponse );
+        try {
+            transport.connect();
 
-                    /* Create SMB signature digest if necessary
-                     * Only the first SMB_COM_SESSION_SETUP_ANX with non-null or
-                     * blank password initializes signing.
-                     */
-                    if (transport.isSignatureSetupRequired( auth )) {
-                        if( auth.hashesExternal && NtlmPasswordAuthentication.DEFAULT_PASSWORD != NtlmPasswordAuthentication.BLANK ) {
-                            /* preauthentication
-                             */
-                            transport.getSmbSession( NtlmPasswordAuthentication.DEFAULT ).getSmbTree( LOGON_SHARE, null ).treeConnect( null, null );
-                        } else {
-                            byte[] signingKey = auth.getSigningKey(transport.server.encryptionKey);
-                            request.digest = new SigningDigest(signingKey, false);
+            /*
+             * Session Setup And X Request / Response
+             */
+    
+            if( transport.log.level >= 4 )
+                transport.log.println( "sessionSetup: accountName=" + auth.username + ",primaryDomain=" + auth.domain );
+    
+            /* We explicitly set uid to 0 here to prevent a new
+             * SMB_COM_SESSION_SETUP_ANDX from having it's uid set to an
+             * old value when the session is re-established. Otherwise a
+             * "The parameter is incorrect" error can occur.
+             */
+            uid = 0;
+    
+            do {
+                switch (state) {
+                    case 10: /* NTLM */
+                        if (auth != NtlmPasswordAuthentication.ANONYMOUS &&
+                                transport.hasCapability(SmbConstants.CAP_EXTENDED_SECURITY)) {
+                            state = 20; /* NTLMSSP */
+                            break;
                         }
-                    }
-
-                    request.auth = auth;
-
-                    try {
-                        transport.send( request, response );
-                    } catch (SmbAuthException sae) {
-                        throw sae;
-                    } catch (SmbException se) {
-                        ex = se;
-                    }
-
-                    if( response.isLoggedInAsGuest &&
-                                "GUEST".equalsIgnoreCase( auth.username ) == false &&
-                                transport.server.security != SmbConstants.SECURITY_SHARE) {
-                        throw new SmbAuthException( NtStatus.NT_STATUS_LOGON_FAILURE );
-                    }
-
-                    if (ex != null)
-                        throw ex;
-
-                    uid = response.uid;
-
-                    if( request.digest != null ) {
-                        /* success - install the signing digest */
-                        transport.digest = request.digest;
-                    }
-
-                    sessionSetup = true;
-                    state = 0;
-
-                    break;
-                case 20:
-                    if (nctx == null) {
-                        boolean doSigning = (transport.flags2 & ServerMessageBlock.FLAGS2_SECURITY_SIGNATURES) != 0;
-                        nctx = new NtlmContext(auth, doSigning);
-                    }
-
-                    if (nctx.isEstablished()) {
-                        sessionSetup = true;
-                        state = 0;
-                        break;
-                    }
-
-                    try {
-                        token = nctx.initSecContext(token, 0, token.length);
-                    } catch (SmbException se) {
-                        /* We must close the transport or the server will be expecting a
-                         * Type3Message. Otherwise, when we send a Type1Message it will return
-                         * "Invalid parameter".
+    
+                        request = new SmbComSessionSetupAndX( this, andx, auth );
+                        response = new SmbComSessionSetupAndXResponse( andxResponse );
+    
+                        /* Create SMB signature digest if necessary
+                         * Only the first SMB_COM_SESSION_SETUP_ANX with non-null or
+                         * blank password initializes signing.
                          */
-                        try { transport.disconnect(true); } catch (IOException ioe) {}
-                        uid = 0;
-                        throw se;
-                    }
-
-                    if (token != null) {
-                        request = new SmbComSessionSetupAndX(this, null, token);
-                        response = new SmbComSessionSetupAndXResponse(null);
-
                         if (transport.isSignatureSetupRequired( auth )) {
-                            byte[] signingKey = nctx.getSigningKey();
-                            if (signingKey != null)
-                                request.digest = new SigningDigest(signingKey, true);
+                            if( auth.hashesExternal && NtlmPasswordAuthentication.DEFAULT_PASSWORD != NtlmPasswordAuthentication.BLANK ) {
+                                /* preauthentication
+                                 */
+                                transport.getSmbSession( NtlmPasswordAuthentication.DEFAULT ).getSmbTree( LOGON_SHARE, null ).treeConnect( null, null );
+                            } else {
+                                byte[] signingKey = auth.getSigningKey(transport.server.encryptionKey);
+                                request.digest = new SigningDigest(signingKey, false);
+                            }
                         }
-
-                        request.uid = uid;
-                        uid = 0;
-
+    
+                        request.auth = auth;
+    
                         try {
                             transport.send( request, response );
                         } catch (SmbAuthException sae) {
                             throw sae;
                         } catch (SmbException se) {
                             ex = se;
-                            /* Apparently once a successfull NTLMSSP login occurs, the
-                             * server will return "Access denied" even if a logoff is
-                             * sent. Unfortunately calling disconnect() doesn't always
-                             * actually shutdown the connection before other threads
-                             * have committed themselves (e.g. InterruptTest example).
-                             */
-                            try { transport.disconnect(true); } catch (Exception e) {}
                         }
-
+    
                         if( response.isLoggedInAsGuest &&
-                                    "GUEST".equalsIgnoreCase( auth.username ) == false) {
+                                    "GUEST".equalsIgnoreCase( auth.username ) == false &&
+                                    transport.server.security != SmbConstants.SECURITY_SHARE) {
                             throw new SmbAuthException( NtStatus.NT_STATUS_LOGON_FAILURE );
                         }
-
+    
                         if (ex != null)
                             throw ex;
-
+    
                         uid = response.uid;
-
-                        if (request.digest != null) {
+    
+                        if( request.digest != null ) {
                             /* success - install the signing digest */
                             transport.digest = request.digest;
                         }
+    
+                        connectionState = 2;    
 
-                        token = response.blob;
-                    }
+                        state = 0;
+    
+                        break;
+                    case 20:
+                        if (nctx == null) {
+                            boolean doSigning = (transport.flags2 & ServerMessageBlock.FLAGS2_SECURITY_SIGNATURES) != 0;
+                            nctx = new NtlmContext(auth, doSigning);
+                        }
+    
+                        if (SmbTransport.log.level >= 4)
+                            SmbTransport.log.println(nctx);
+    
+                        if (nctx.isEstablished()) {
 
-                    break;
-                default:
-                    throw new SmbException("Unexpected session setup state: " + state);
-            }
-        } while (state != 0);
+                            connectionState = 2;
+
+                            state = 0;
+                            break;
+                        }
+    
+                        try {
+                            token = nctx.initSecContext(token, 0, token.length);
+                        } catch (SmbException se) {
+                            /* We must close the transport or the server will be expecting a
+                             * Type3Message. Otherwise, when we send a Type1Message it will return
+                             * "Invalid parameter".
+                             */
+                            try { transport.disconnect(true); } catch (IOException ioe) {}
+                            uid = 0;
+                            throw se;
+                        }
+    
+                        if (token != null) {
+                            request = new SmbComSessionSetupAndX(this, null, token);
+                            response = new SmbComSessionSetupAndXResponse(null);
+    
+                            if (transport.isSignatureSetupRequired( auth )) {
+                                byte[] signingKey = nctx.getSigningKey();
+                                if (signingKey != null)
+                                    request.digest = new SigningDigest(signingKey, true);
+                            }
+    
+                            request.uid = uid;
+                            uid = 0;
+    
+                            try {
+                                transport.send( request, response );
+                            } catch (SmbAuthException sae) {
+                                throw sae;
+                            } catch (SmbException se) {
+                                ex = se;
+                                /* Apparently once a successfull NTLMSSP login occurs, the
+                                 * server will return "Access denied" even if a logoff is
+                                 * sent. Unfortunately calling disconnect() doesn't always
+                                 * actually shutdown the connection before other threads
+                                 * have committed themselves (e.g. InterruptTest example).
+                                 */
+                                try { transport.disconnect(true); } catch (Exception e) {}
+                            }
+    
+                            if( response.isLoggedInAsGuest &&
+                                        "GUEST".equalsIgnoreCase( auth.username ) == false) {
+                                throw new SmbAuthException( NtStatus.NT_STATUS_LOGON_FAILURE );
+                            }
+    
+                            if (ex != null)
+                                throw ex;
+    
+                            uid = response.uid;
+    
+                            if (request.digest != null) {
+                                /* success - install the signing digest */
+                                transport.digest = request.digest;
+                            }
+    
+                            token = response.blob;
+                        }
+    
+                        break;
+                    default:
+                        throw new SmbException("Unexpected session setup state: " + state);
+                }
+            } while (state != 0);
+        } catch (SmbException se) {
+            logoff(true);
+            connectionState = 0;
+            throw se;
+        } finally {
+            transport.notifyAll();
+        }
 }
     }
     void logoff( boolean inError ) {
-synchronized( transport() ) {
-        if( sessionSetup == false ) {
+synchronized (transport()) {
+
+        if (connectionState != 2) // not-connected
             return;
-        }
+        connectionState = 3; // disconnecting
 
         for( Enumeration e = trees.elements(); e.hasMoreElements(); ) {
             SmbTree t = (SmbTree)e.nextElement();
@@ -410,7 +438,7 @@ synchronized( transport() ) {
             /*
              * Logoff And X Request / Response
              */
-    
+
             SmbComLogoffAndX request = new SmbComLogoffAndX( null );
             request.uid = uid;
             try {
@@ -420,13 +448,14 @@ synchronized( transport() ) {
             uid = 0;
         }
 
-        sessionSetup = false;
+        connectionState = 0;
+        transport.notifyAll();
 }
     }
     public String toString() {
         return "SmbSession[accountName=" + auth.username +
                 ",primaryDomain=" + auth.domain +
                 ",uid=" + uid +
-                ",sessionSetup=" + sessionSetup + "]";
+                ",connectionState=" + connectionState + "]";
     }
 }
index 342ac47..42c0982 100644 (file)
@@ -92,7 +92,7 @@ public class SmbTransport extends Transport implements SmbConstants {
     int port, mid;
     OutputStream out;
     InputStream in;
-    byte[] sbuf = new byte[255]; /* small local buffer */
+    byte[] sbuf = new byte[512]; /* small local buffer */
     SmbComBlankResponse key = new SmbComBlankResponse();
     long sessionExpiration = System.currentTimeMillis() + SO_TIMEOUT;
     LinkedList referrals = new LinkedList();
@@ -470,10 +470,13 @@ public class SmbTransport extends Transport implements SmbConstants {
                                     /* WordCount thru dataOffset always 27 */
                 readn( in, BUF, 4 + off, 27 ); off += 27;
                 resp.decode( BUF, 4 );
-                if (r.dataLength > 0) {
-                    readn( in, BUF, 4 + off, r.dataOffset - off);   /* pad */
+                                              /* EMC can send pad w/o data */
+                int pad = r.dataOffset - off;
+                if (r.byteCount > 0 && pad > 0 && pad < 4)
+                    readn( in, BUF, 4 + off, pad);
+
+                if (r.dataLength > 0)
                     readn( in, r.b, r.off, r.dataLength );  /* read direct */
-                }
             } else {
                 readn( in, BUF, 4 + 32, size - 32 );
                 resp.decode( BUF, 4 );
@@ -586,7 +589,7 @@ public class SmbTransport extends Transport implements SmbConstants {
                         makeKey( req );
                     }
 
-                    synchronized (response_map) {
+                    synchronized (this) {
                         response.received = false;
                         resp.isReceived = false;
                         try {
@@ -607,7 +610,7 @@ public class SmbTransport extends Transport implements SmbConstants {
                             long timeout = RESPONSE_TIMEOUT;
                             resp.expiration = System.currentTimeMillis() + timeout;
                             while( resp.hasMoreElements() ) {
-                                response_map.wait( timeout );
+                                wait( timeout );
                                 timeout = resp.expiration - System.currentTimeMillis();
                                 if (timeout <= 0) {
                                     throw new TransportException( this +
@@ -635,8 +638,6 @@ public class SmbTransport extends Transport implements SmbConstants {
             }
         } catch( SmbException se ) {
             throw se;
-        } catch( InterruptedException ie ) {
-            throw new SmbException( ie.getMessage(), ie );
         } catch( IOException ioe ) {
             throw new SmbException( ioe.getMessage(), ioe );
         }
index 7ecabb5..3a65248 100644 (file)
@@ -28,14 +28,20 @@ class SmbTree {
 
     private static int tree_conn_counter;
 
-    private int tid;
+    /* 0 - not connected
+     * 1 - connecting
+     * 2 - connected
+     * 3 - disconnecting
+     */
+    int connectionState;
+    int tid;
 
     String share;
     String service = "?????";
     String service0;
     SmbSession session;
-    boolean treeConnected, inDfs, inDomainDfs;
-    int tree_num;
+    boolean inDfs, inDomainDfs;
+    int tree_num; // used by SmbFile.isOpen
 
     SmbTree( SmbSession session, String share, String service ) {
         this.session = session;
@@ -44,6 +50,7 @@ class SmbTree {
             this.service = service;
         }
         this.service0 = this.service;
+        this.connectionState = 0;
     }
 
     boolean matches( String share, String service ) {
@@ -60,6 +67,7 @@ class SmbTree {
     }
     void send( ServerMessageBlock request,
                             ServerMessageBlock response ) throws SmbException {
+synchronized (session.transport()) {
         if( response != null ) {
             response.received = false;
         }
@@ -120,57 +128,74 @@ class SmbTree {
             }
             throw se;
         }
+}
     }
     void treeConnect( ServerMessageBlock andx,
                             ServerMessageBlock andxResponse ) throws SmbException {
-        String unc;
-        SmbTransport transport = session.transport();
 
-synchronized(transport.setupDiscoLock) {
-synchronized(transport) {
+synchronized (session.transport()) {
+        String unc;
 
-        if (treeConnected) {
-            return;
+        while (connectionState != 0) {
+            if (connectionState == 2 || connectionState == 3) // connected or disconnecting
+                return;
+            try {
+                session.transport.wait();
+            } catch (InterruptedException ie) {
+                throw new SmbException(ie.getMessage(), ie);
+            }
         }
+        connectionState = 1; // trying ...
 
-        /* The hostname to use in the path is only known for
-         * sure if the NetBIOS session has been successfully
-         * established.
-         */
-
-        session.transport.connect();
-
-        unc = "\\\\" + session.transport.tconHostName + '\\' + share;
-
-        /* IBM iSeries doesn't like specifying a service. Always reset
-         * the service to whatever was determined in the constructor.
-         */
-        service = service0;
-
-        /*
-         * Tree Connect And X Request / Response
-         */
-
-        if( session.transport.log.level >= 4 )
-            session.transport.log.println( "treeConnect: unc=" + unc + ",service=" + service );
-
-        SmbComTreeConnectAndXResponse response =
-                new SmbComTreeConnectAndXResponse( andxResponse );
-        SmbComTreeConnectAndX request =
-                new SmbComTreeConnectAndX( session, unc, service, andx );
-        session.send( request, response );
-
-        tid = response.tid;
-        service = response.service;
-        inDfs = response.shareIsInDfs;
-        treeConnected = true;
-        tree_num = tree_conn_counter++;
-}
+        try {
+            /* The hostname to use in the path is only known for
+             * sure if the NetBIOS session has been successfully
+             * established.
+             */
+    
+            session.transport.connect();
+    
+            unc = "\\\\" + session.transport.tconHostName + '\\' + share;
+    
+            /* IBM iSeries doesn't like specifying a service. Always reset
+             * the service to whatever was determined in the constructor.
+             */
+            service = service0;
+    
+            /*
+             * Tree Connect And X Request / Response
+             */
+    
+            if( session.transport.log.level >= 4 )
+                session.transport.log.println( "treeConnect: unc=" + unc + ",service=" + service );
+    
+            SmbComTreeConnectAndXResponse response =
+                    new SmbComTreeConnectAndXResponse( andxResponse );
+            SmbComTreeConnectAndX request =
+                    new SmbComTreeConnectAndX( session, unc, service, andx );
+            session.send( request, response );
+    
+            tid = response.tid;
+            service = response.service;
+            inDfs = response.shareIsInDfs;
+            tree_num = tree_conn_counter++;
+    
+            connectionState = 2; // connected
+        } catch (SmbException se) {
+            treeDisconnect(true);
+            connectionState = 0;
+            throw se;
+        }
 }
     }
     void treeDisconnect( boolean inError ) {
-synchronized( session.transport ) {
-        if (treeConnected && !inError && tid != 0) {
+synchronized (session.transport()) {
+
+        if (connectionState != 2) // not-connected
+            return;
+        connectionState = 3; // disconnecting
+
+        if (!inError && tid != 0) {
             try {
                 send( new SmbComTreeDisconnect(), null );
             } catch( SmbException se ) {
@@ -179,9 +204,12 @@ synchronized( session.transport ) {
                 }
             }
         }
-        treeConnected = false;
         inDfs = false;
         inDomainDfs = false;
+
+        connectionState = 0;
+
+        session.transport.notifyAll();
 }
     }
 
@@ -191,6 +219,6 @@ synchronized( session.transport ) {
             ",tid=" + tid +
             ",inDfs=" + inDfs +
             ",inDomainDfs=" + inDomainDfs +
-            ",treeConnected=" + treeConnected + "]";
+            ",connectionState=" + connectionState + "]";
     }
 }
diff --git a/src/jcifs/smb/TestLocking.java b/src/jcifs/smb/TestLocking.java
new file mode 100644 (file)
index 0000000..ca2c02b
--- /dev/null
@@ -0,0 +1,124 @@
+package jcifs.smb;
+
+import java.io.InputStream;
+import java.io.IOException;
+
+public class TestLocking implements Runnable
+{
+
+    int numThreads = 1;
+    int numIter = 1;
+    long delay = 100;
+    String url = null;
+    int numComplete = 0;
+    long ltime = 0L;
+
+    public void run()
+    {
+        try {
+            SmbFile f = new SmbFile(url);
+            SmbFile d = new SmbFile(f.getParent());
+            byte[] buf = new byte[1024];
+
+            for (int ii = 0; ii < numIter; ii++) {
+
+                synchronized (this) {
+                    ltime = System.currentTimeMillis();
+                    wait();
+                }
+
+                try {
+                    double r = Math.random();
+                    if (r < 0.333) {
+                        f.exists();
+//                      System.out.print('e');
+                    } else if (r < 0.667) {
+                        d.listFiles();
+//                      System.out.print('l');
+                    } else if (r < 1.0) {
+                        InputStream in = f.getInputStream();
+                        while (in.read(buf) > 0) {
+//                          System.out.print('r');
+                        }
+                        in.close();
+                    }
+                } catch (IOException ioe) {
+                    System.err.println(ioe.getMessage());
+//ioe.printStackTrace(System.err);
+                }
+
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        } finally {
+            numComplete++;
+        }
+    }
+
+    public static void main(String[] args) throws Exception
+    {
+        if (args.length < 1) {
+            System.err.println("usage: TestLocking [-t <numThreads>] [-i <numIter>] [-d <delay>] url");
+            System.exit(1);
+        }
+
+        TestLocking t = new TestLocking();
+        t.ltime = System.currentTimeMillis();
+
+        for (int ai = 0; ai < args.length; ai++) {
+            if (args[ai].equals("-t")) {
+                ai++;
+                t.numThreads = Integer.parseInt(args[ai]);
+            } else if (args[ai].equals("-i")) {
+                ai++;
+                t.numIter = Integer.parseInt(args[ai]);
+            } else if (args[ai].equals("-d")) {
+                ai++;
+                t.delay = Long.parseLong(args[ai]);
+            } else {
+                t.url = args[ai];
+            }
+        }
+
+        Thread[] threads = new Thread[t.numThreads];
+        int ti;
+
+        for (ti = 0; ti < t.numThreads; ti++) {
+            threads[ti] = new Thread(t);
+            System.out.print(threads[ti].getName());
+            threads[ti].start();
+        }
+
+        while (t.numComplete < t.numThreads) {
+            long delay;
+
+            do {
+                delay = 2L;
+
+                synchronized (t) {
+                    long expire = t.ltime + t.delay;
+                    long ctime = System.currentTimeMillis();
+
+                    if (expire > ctime)
+                        delay = expire - ctime;
+                }
+
+if (delay > 2)
+System.out.println("delay=" + delay);
+                Thread.sleep(delay);
+            } while (delay > 2);
+
+            synchronized (t) {
+                t.notifyAll();
+            }
+//System.out.println("numComplete=" + t.numComplete + ",numThreads=" + t.numThreads);
+        }
+
+        for (ti = 0; ti < t.numThreads; ti++) {
+            threads[ti].join();
+            System.out.print(threads[ti].getName());
+        }
+
+        System.out.println();
+    }
+}
index e244384..56eec39 100644 (file)
@@ -57,12 +57,9 @@ public abstract class Transport implements Runnable {
     protected abstract void doRecv( Response response ) throws IOException;
     protected abstract void doSkip() throws IOException;
 
-    public Object setupDiscoLock = new Object();
-
-    public void sendrecv( Request request,
+    public synchronized void sendrecv( Request request,
                     Response response,
                     long timeout ) throws IOException {
-        synchronized (response_map) {
             makeKey( request );
             response.isReceived = false;
             try {
@@ -70,7 +67,7 @@ public abstract class Transport implements Runnable {
                 doSend( request );
                 response.expiration = System.currentTimeMillis() + timeout;
                 while (!response.isReceived) {
-                    response_map.wait( timeout );
+                    wait( timeout );
                     timeout = response.expiration - System.currentTimeMillis();
                     if (timeout <= 0) {
                         throw new TransportException( name +
@@ -92,7 +89,6 @@ public abstract class Transport implements Runnable {
             } finally {
                 response_map.remove( request );
             }
-        }
     }
     private void loop() {
         while( thread == Thread.currentThread() ) {
@@ -100,7 +96,7 @@ public abstract class Transport implements Runnable {
                 Request key = peekKey();
                 if (key == null)
                     throw new IOException( "end of stream" );
-                synchronized (response_map) {
+                synchronized (this) {
                     Response response = (Response)response_map.get( key );
                     if (response == null) {
                         if (log.level >= 4)
@@ -109,7 +105,7 @@ public abstract class Transport implements Runnable {
                     } else {
                         doRecv( response );
                         response.isReceived = true;
-                        response_map.notifyAll();
+                        notifyAll();
                     }
                 }
             } catch( Exception ex ) {
@@ -201,31 +197,27 @@ public abstract class Transport implements Runnable {
             }
         }
     }
-    public void disconnect( boolean hard ) throws IOException {
-        synchronized(setupDiscoLock) {
-            synchronized(this) {
-                switch (state) {
-                    case 0: /* not connected - just return */
-                        return;
-                    case 2:
-                        hard = true;
-                    case 3: /* connected - go ahead and disconnect */
-                        if (response_map.size() != 0 && !hard) {
-                            break; /* outstanding requests */
-                        }
-                        doDisconnect( hard );
-                    case 4: /* in error - reset the transport */
-                        thread = null;
-                        state = 0;
-                        break;
-                    default:
-                        if (log.level >= 1)
-                            log.println("Invalid state: " + state);
-                        thread = null;
-                        state = 0;
-                        break;
+    public synchronized void disconnect( boolean hard ) throws IOException {
+        switch (state) {
+            case 0: /* not connected - just return */
+                return;
+            case 2:
+                hard = true;
+            case 3: /* connected - go ahead and disconnect */
+                if (response_map.size() != 0 && !hard) {
+                    break; /* outstanding requests */
                 }
-            }
+                doDisconnect( hard );
+            case 4: /* in error - reset the transport */
+                thread = null;
+                state = 0;
+                break;
+            default:
+                if (log.level >= 1)
+                    log.println("Invalid state: " + state);
+                thread = null;
+                state = 0;
+                break;
         }
     }
     public void run() {