KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jcifs > smb > AndXServerMessageBlock


1 /* jcifs smb client library in Java
2  * Copyright (C) 2000 "Michael B. Allen" <jcifs at samba dot org>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  */

18
19 package jcifs.smb;
20
21 import java.io.InputStream JavaDoc;
22 import java.io.IOException JavaDoc;
23 import jcifs.util.Hexdump;
24
25 abstract class AndXServerMessageBlock extends ServerMessageBlock {
26
27     private static final int ANDX_COMMAND_OFFSET = 1;
28     private static final int ANDX_RESERVED_OFFSET = 2;
29     private static final int ANDX_OFFSET_OFFSET = 3;
30
31     private byte andxCommand = (byte)0xFF;
32     private int andxOffset = 0;
33
34     ServerMessageBlock andx = null;
35
36     AndXServerMessageBlock() {
37     }
38     AndXServerMessageBlock( ServerMessageBlock andx ) {
39         if (andx != null) {
40             this.andx = andx;
41             andxCommand = andx.command;
42         }
43     }
44
45     int getBatchLimit( byte command ) {
46         /* the default limit is 0 batched messages before this
47          * one, meaning this message cannot be batched.
48          */

49         return 0;
50     }
51
52     /*
53      * We overload this method from ServerMessageBlock because
54      * we want writeAndXWireFormat to write the parameterWords
55      * and bytes. This is so we can write batched smbs because
56      * all but the first smb of the chaain do not have a header
57      * and therefore we do not want to writeHeaderWireFormat. We
58      * just recursivly call writeAndXWireFormat.
59      */

60
61     int encode( byte[] dst, int dstIndex ) {
62         int start = headerStart = dstIndex;
63
64         dstIndex += writeHeaderWireFormat( dst, dstIndex );
65         dstIndex += writeAndXWireFormat( dst, dstIndex );
66         length = dstIndex - start;
67
68         if( digest != null ) {
69             digest.sign( dst, headerStart, length, this, response );
70         }
71
72         return length;
73     }
74
75     /*
76      * We overload this because we want readAndXWireFormat to
77      * read the parameter words and bytes. This is so when
78      * commands are batched together we can recursivly call
79      * readAndXWireFormat without reading the non-existent header.
80      */

81
82     int decode( byte[] buffer, int bufferIndex ) {
83         int start = headerStart = bufferIndex;
84
85         bufferIndex += readHeaderWireFormat( buffer, bufferIndex );
86         bufferIndex += readAndXWireFormat( buffer, bufferIndex );
87
88         length = bufferIndex - start;
89         return length;
90     }
91     int writeAndXWireFormat( byte[] dst, int dstIndex ) {
92         int start = dstIndex;
93
94         wordCount = writeParameterWordsWireFormat( dst,
95                     start + ANDX_OFFSET_OFFSET + 2 );
96         wordCount += 4; // for command, reserved, and offset
97
dstIndex += wordCount + 1;
98         wordCount /= 2;
99         dst[start] = (byte)( wordCount & 0xFF );
100
101         byteCount = writeBytesWireFormat( dst, dstIndex + 2 );
102         dst[dstIndex++] = (byte)( byteCount & 0xFF );
103         dst[dstIndex++] = (byte)(( byteCount >> 8 ) & 0xFF );
104         dstIndex += byteCount;
105
106         /* Normally, without intervention everything would batch
107          * with everything else. If the below clause evaluates true
108          * the andx command will not be written and therefore the
109          * response will not read a batched command and therefore
110          * the 'received' member of the response object will not
111          * be set to true indicating the send and sendTransaction
112          * methods that the next part should be sent. This is a
113          * very indirect and simple batching control mechanism.
114          */

115
116         if( andx == null || USE_BATCHING == false ||
117                                 batchLevel >= getBatchLimit( andx.command )) {
118             andxCommand = (byte)0xFF;
119             andx = null;
120
121             dst[start + ANDX_COMMAND_OFFSET] = (byte)0xFF;
122             dst[start + ANDX_RESERVED_OFFSET] = (byte)0x00;
123             dst[start + ANDX_OFFSET_OFFSET] = (byte)0x00;
124             dst[start + ANDX_OFFSET_OFFSET + 1] = (byte)0x00;
125
126             // andx not used; return
127
return dstIndex - start;
128         }
129
130         /* The message provided to batch has a batchLimit that is
131          * higher than the current batchLevel so we will now encode
132          * that chained message. Before doing so we must increment
133          * the batchLevel of the andx message in case it itself is an
134          * andx message and needs to perform the same check as above.
135          */

136
137         andx.batchLevel = batchLevel + 1;
138
139
140         dst[start + ANDX_COMMAND_OFFSET] = andxCommand;
141         dst[start + ANDX_RESERVED_OFFSET] = (byte)0x00;
142         andxOffset = dstIndex - headerStart;
143         writeInt2( andxOffset, dst, start + ANDX_OFFSET_OFFSET );
144
145         andx.useUnicode = useUnicode;
146         if( andx instanceof AndXServerMessageBlock ) {
147
148             /*
149              * A word about communicating header info to andx smbs
150              *
151              * This is where we recursively invoke the provided andx smb
152              * object to write it's parameter words and bytes to our outgoing
153              * array. Incedentally when these andx smbs are created they are not
154              * necessarily populated with header data because they're not writing
155              * the header, only their body. But for whatever reason one might wish
156              * to populate fields if the writeXxx operation needs this header data
157              * for whatever reason. I copy over the uid here so it appears correct
158              * in logging output. Logging of andx segments of messages inadvertantly
159              * print header information because of the way toString always makes a
160              * super.toString() call(see toString() at the end of all smbs classes).
161              */

162
163             andx.uid = uid;
164             dstIndex += ((AndXServerMessageBlock)andx).writeAndXWireFormat( dst, dstIndex );
165         } else {
166             // the andx smb is not of type andx so lets just write it here and
167
// were done.
168
int andxStart = dstIndex;
169             andx.wordCount = andx.writeParameterWordsWireFormat( dst, dstIndex );
170             dstIndex += andx.wordCount + 1;
171             andx.wordCount /= 2;
172             dst[andxStart] = (byte)( andx.wordCount & 0xFF );
173     
174             andx.byteCount = andx.writeBytesWireFormat( dst, dstIndex + 2 );
175             dst[dstIndex++] = (byte)( andx.byteCount & 0xFF );
176             dst[dstIndex++] = (byte)(( andx.byteCount >> 8 ) & 0xFF );
177             dstIndex += andx.byteCount;
178         }
179
180         return dstIndex - start;
181     }
182     int readAndXWireFormat( byte[] buffer, int bufferIndex ) {
183         int start = bufferIndex;
184
185         wordCount = buffer[bufferIndex++];
186
187         if( wordCount != 0 ) {
188             /*
189              * these fields are common to all andx commands
190              * so let's populate them here
191              */

192
193             andxCommand = buffer[bufferIndex]; bufferIndex += 2;
194             andxOffset = readInt2( buffer, bufferIndex ); bufferIndex += 2;
195
196             if( andxOffset == 0 ) { /* Snap server workaround */
197                 andxCommand = (byte)0xFF;
198             }
199
200             /*
201              * no point in calling readParameterWordsWireFormat if there are no more
202              * parameter words. besides, win98 doesn't return "OptionalSupport" field
203              */

204  
205             if( wordCount > 2 ) {
206                 bufferIndex += readParameterWordsWireFormat( buffer, bufferIndex );
207             }
208         }
209
210         byteCount = readInt2( buffer, bufferIndex ); bufferIndex += 2;
211
212         if (byteCount != 0) {
213             int n;
214             n = readBytesWireFormat( buffer, bufferIndex );
215             bufferIndex += byteCount;
216         }
217
218         /*
219          * if there is an andx and it itself is an andx then just recur by
220          * calling this method for it. otherwise just read it's parameter words
221          * and bytes as usual. Note how we can't just call andx.readWireFormat
222          * because there's no header.
223          */

224
225         if( errorCode != 0 || andxCommand == (byte)0xFF ) {
226             andxCommand = (byte)0xFF;
227             andx = null;
228         } else if( andx == null ) {
229             andxCommand = (byte)0xFF;
230             throw new RuntimeException JavaDoc( "no andx command supplied with response" );
231         } else {
232
233             /*
234              * Set bufferIndex according to andxOffset
235              */

236
237             bufferIndex = headerStart + andxOffset;
238
239             andx.headerStart = headerStart;
240             andx.command = andxCommand;
241             andx.errorCode = errorCode;
242             andx.flags = flags;
243             andx.flags2 = flags2;
244             andx.tid = tid;
245             andx.pid = pid;
246             andx.uid = uid;
247             andx.mid = mid;
248             andx.useUnicode = useUnicode;
249
250             if( andx instanceof AndXServerMessageBlock ) {
251                 bufferIndex += ((AndXServerMessageBlock)andx).readAndXWireFormat(
252                                                 buffer, bufferIndex );
253             } else {
254
255                 /*
256                  * Just a plain smb. Read it as normal.
257                  */

258
259                 buffer[bufferIndex++] = (byte)( andx.wordCount & 0xFF );
260
261                 if( andx.wordCount != 0 ) {
262                     /*
263                      * no point in calling readParameterWordsWireFormat if there are no more
264                      * parameter words. besides, win98 doesn't return "OptionalSupport" field
265                      */

266
267                     if( andx.wordCount > 2 ) {
268                         bufferIndex += andx.readParameterWordsWireFormat( buffer, bufferIndex );
269                     }
270                 }
271
272                 andx.byteCount = readInt2( buffer, bufferIndex );
273                 bufferIndex += 2;
274
275                 if( andx.byteCount != 0 ) {
276                     andx.readBytesWireFormat( buffer, bufferIndex );
277                     bufferIndex += andx.byteCount;
278                 }
279             }
280             andx.received = true;
281         }
282
283         return bufferIndex - start;
284     }
285     public String JavaDoc toString() {
286         return new String JavaDoc( super.toString() +
287             ",andxCommand=0x" + Hexdump.toHexString( andxCommand, 2 ) +
288             ",andxOffset=" + andxOffset );
289     }
290 }
291
Popular Tags