KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > alfresco > filesys > smb > server > SMBSrvTransPacket


1 /*
2  * Copyright (C) 2005 Alfresco, Inc.
3  *
4  * Licensed under the Mozilla Public License version 1.1
5  * with a permitted attribution clause. You may obtain a
6  * copy of the License at
7  *
8  * http://www.alfresco.org/legal/license.txt
9  *
10  * Unless required by applicable law or agreed to in writing,
11  * software distributed under the License is distributed on an
12  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13  * either express or implied. See the License for the specific
14  * language governing permissions and limitations under the
15  * License.
16  */

17 package org.alfresco.filesys.smb.server;
18
19 import java.io.IOException JavaDoc;
20
21 import org.alfresco.filesys.netbios.RFCNetBIOSProtocol;
22 import org.alfresco.filesys.smb.PacketType;
23 import org.alfresco.filesys.smb.TransactBuffer;
24 import org.alfresco.filesys.util.DataBuffer;
25 import org.alfresco.filesys.util.DataPacker;
26
27 /**
28  * SMB server transact packet class
29  */

30 class SMBSrvTransPacket extends SMBTransPacket
31 {
32
33     // Define the number of standard parameters for a server response
34

35     private static final int StandardParamsResponse = 10;
36
37     // Offset to the setup response paramaters
38

39     protected static final int SetupOffsetResponse = PARAMWORDS + (StandardParamsResponse * 2);
40
41     /**
42      * Construct an SMB transaction packet
43      *
44      * @param buf Buffer that contains the SMB transaction packet.
45      */

46
47     public SMBSrvTransPacket(byte[] buf)
48     {
49         super(buf);
50     }
51
52     /**
53      * Construct an SMB transaction packet
54      *
55      * @param siz Size of packet to allocate.
56      */

57
58     public SMBSrvTransPacket(int siz)
59     {
60         super(siz);
61
62         // Set the multiplex id for this transaction
63

64         setMultiplexId(getNextMultiplexId());
65     }
66
67     /**
68      * Initialize the transact reply parameters.
69      *
70      * @param pkt Reply SMB packet.
71      * @param prmCnt Count of returned parameter bytes.
72      * @param prmPos Starting offset to the parameter block.
73      * @param dataCnt Count of returned data bytes.
74      * @param dataPos Starting offset to the data block.
75      */

76     public final static void initTransactReply(SMBSrvPacket pkt, int prmCnt, int prmPos, int dataCnt, int dataPos)
77     {
78
79         // Set the total parameter words
80

81         pkt.setParameterCount(10);
82
83         // Set the total parameter/data bytes
84

85         pkt.setParameter(0, prmCnt);
86         pkt.setParameter(1, dataCnt);
87
88         // Clear the reserved parameter
89

90         pkt.setParameter(2, 0);
91
92         // Set the parameter byte count/offset for this packet
93

94         pkt.setParameter(3, prmCnt);
95         pkt.setParameter(4, prmPos - RFCNetBIOSProtocol.HEADER_LEN);
96
97         // Set the parameter displacement
98

99         pkt.setParameter(5, 0);
100
101         // Set the data byte count/offset for this packet
102

103         pkt.setParameter(6, dataCnt);
104         pkt.setParameter(7, dataPos - RFCNetBIOSProtocol.HEADER_LEN);
105
106         // Set the data displacement
107

108         pkt.setParameter(8, 0);
109
110         // Set up word count
111

112         pkt.setParameter(9, 0);
113     }
114
115     /**
116      * Calculate the data item size from the data descriptor string.
117      *
118      * @param desc java.lang.String
119      * @return int
120      */

121     protected final static int CalculateDataItemSize(String JavaDoc desc)
122     {
123
124         // Scan the data descriptor string and calculate the data item size
125

126         int len = 0;
127         int pos = 0;
128
129         while (pos < desc.length())
130         {
131
132             // Get the current data item type
133

134             char dtype = desc.charAt(pos++);
135             int dlen = 1;
136
137             // Check if a data length has been specified
138

139             if (pos < desc.length() && Character.isDigit(desc.charAt(pos)))
140             {
141
142                 // Convert the data length string
143

144                 int numlen = 1;
145                 int numpos = pos + 1;
146                 while (numpos < desc.length() && Character.isDigit(desc.charAt(numpos++)))
147                     numlen++;
148
149                 // Set the data length
150

151                 dlen = Integer.parseInt(desc.substring(pos, pos + numlen));
152
153                 // Update the descriptor string position
154

155                 pos = numpos - 1;
156             }
157
158             // Convert the current data item
159

160             switch (dtype)
161             {
162
163             // Word (16 bit) data type
164

165             case 'W':
166                 len += 2;
167                 break;
168
169             // Integer (32 bit) data type
170

171             case 'D':
172                 len += 4;
173                 break;
174
175             // Byte data type, may be multiple bytes if 'B<n>'
176

177             case 'B':
178                 len += dlen;
179                 break;
180
181             // Null terminated string data type, offset into buffer only
182

183             case 'z':
184                 len += 4;
185                 break;
186
187             // Skip 'n' bytes in the buffer
188

189             case '.':
190                 len += dlen;
191                 break;
192
193             // Integer (32 bit) data type converted to a date/time value
194

195             case 'T':
196                 len += 4;
197                 break;
198
199             } // end switch data type
200

201         } // end while descriptor string
202

203         // Return the data length of each item
204

205         return len;
206     }
207
208     /**
209      * Return the offset to the data block within the SMB packet. The data block is word aligned
210      * within the byte buffer area of the SMB packet. This method must be called after the parameter
211      * count has been set.
212      *
213      * @param prmLen Parameter block length, in bytes.
214      * @return int Offset to the data block area.
215      */

216     public final int getDataBlockOffset(int prmLen)
217     {
218
219         // Get the position of the parameter block
220

221         int pos = getParameterBlockOffset() + prmLen;
222         if ((pos & 0x01) != 0)
223             pos++;
224         return pos;
225     }
226
227     /**
228      * Return the data block offset.
229      *
230      * @return int Offset to data block within packet.
231      */

232     public final int getRxDataBlock()
233     {
234         return getParameter(12) + RFCNetBIOSProtocol.HEADER_LEN;
235     }
236
237     /**
238      * Return the received transaction data block length.
239      *
240      * @return int
241      */

242     public final int getRxDataBlockLength()
243     {
244         return getParameter(11);
245     }
246
247     /**
248      * Get the required transact parameter word (16 bit).
249      *
250      * @param prmIdx int
251      * @return int
252      */

253     public final int getRxParameter(int prmIdx)
254     {
255
256         // Get the parameter block offset
257

258         int pos = getRxParameterBlock();
259
260         // Get the required transact parameter word.
261

262         pos += prmIdx * 2; // 16 bit words
263
return DataPacker.getIntelShort(getBuffer(), pos);
264     }
265
266     /**
267      * Return the position of the parameter block within the received packet.
268      *
269      * @param prmblk Array to unpack the parameter block words into.
270      */

271
272     public final int getRxParameterBlock()
273     {
274
275         // Get the offset to the parameter words, add the NetBIOS header length
276
// to the offset.
277

278         return getParameter(10) + RFCNetBIOSProtocol.HEADER_LEN;
279     }
280
281     /**
282      * Return the received transaction parameter block length.
283      *
284      * @return int
285      */

286     public final int getRxParameterBlockLength()
287     {
288         return getParameter(9);
289     }
290
291     /**
292      * Return the received transaction setup parameter count.
293      *
294      * @return int
295      */

296     public final int getRxParameterCount()
297     {
298         return getParameterCount() - STD_PARAMS;
299     }
300
301     /**
302      * Get the required transact parameter int value (32-bit).
303      *
304      * @param prmIdx int
305      * @return int
306      */

307     public final int getRxParameterInt(int prmIdx)
308     {
309
310         // Get the parameter block offset
311

312         int pos = getRxParameterBlock();
313
314         // Get the required transact parameter word.
315

316         pos += prmIdx * 2; // 16 bit words
317
return DataPacker.getIntelInt(getBuffer(), pos);
318     }
319
320     /**
321      * Get the required transact parameter string.
322      *
323      * @param pos Offset to the string within the parameter block.
324      * @param uni Unicode if true, else ASCII
325      * @return int
326      */

327     public final String JavaDoc getRxParameterString(int pos, boolean uni)
328     {
329
330         // Get the parameter block offset
331

332         pos += getRxParameterBlock();
333
334         // Get the transact parameter string
335

336         byte[] buf = getBuffer();
337         int len = (buf[pos++] & 0x00FF);
338         return DataPacker.getString(buf, pos, len, uni);
339     }
340
341     /**
342      * Get the required transact parameter string.
343      *
344      * @param pos Offset to the string within the parameter block.
345      * @param len Length of the string.
346      * @param uni Unicode if true, else ASCII
347      * @return int
348      */

349     public final String JavaDoc getRxParameterString(int pos, int len, boolean uni)
350     {
351
352         // Get the parameter block offset
353

354         pos += getRxParameterBlock();
355
356         // Get the transact parameter string
357

358         byte[] buf = getBuffer();
359         return DataPacker.getString(buf, pos, len, uni);
360     }
361
362     /**
363      * Return the received transaction name.
364      *
365      * @return java.lang.String
366      */

367     public final String JavaDoc getRxTransactName()
368     {
369
370         // Check if the transaction has a name
371

372         if (getCommand() == PacketType.Transaction2)
373             return "";
374
375         // Unpack the transaction name string
376

377         int pos = getByteOffset();
378         return DataPacker.getString(getBuffer(), pos, getByteCount());
379     }
380
381     /**
382      * Return the setup parameter count
383      *
384      * @return int
385      */

386     public final int getSetupCount()
387     {
388         return getParameter(13) & 0xFF;
389     }
390
391     /**
392      * Return the buffer offset to the setup parameters
393      *
394      * @return int
395      */

396     public final int getSetupOffset()
397     {
398         return WORDCNT + 29; // 14 setup words + word count byte
399
}
400
401     /**
402      * Return the specified transaction setup parameter.
403      *
404      * @param idx Setup parameter index.
405      * @return int
406      */

407
408     public final int getSetupParameter(int idx)
409     {
410
411         // Check if the setup parameter index is valid
412

413         if (idx >= getRxParameterCount())
414             throw new java.lang.ArrayIndexOutOfBoundsException JavaDoc();
415
416         // Get the setup parameter
417

418         return getParameter(idx + STD_PARAMS);
419     }
420
421     /**
422      * Return the maximum return paramater byte count
423      *
424      * @return int
425      */

426     public final int getMaximumReturnParameterCount()
427     {
428         return getParameter(2);
429     }
430
431     /**
432      * Return the maximum return data byte count
433      *
434      * @return int
435      */

436     public final int getMaximumReturnDataCount()
437     {
438         return getParameter(3);
439     }
440
441     /**
442      * Return the maximum return setup count
443      *
444      * @return int
445      */

446     public final int getMaximumReturnSetupCount()
447     {
448         return getParameter(4);
449     }
450
451     /**
452      * Return the specified transaction setup parameter 32bit value.
453      *
454      * @param idx Setup parameter index.
455      * @return int
456      */

457
458     public final int getSetupParameterInt(int idx)
459     {
460
461         // Check if the setup parameter index is valid
462

463         if (idx >= getRxParameterCount())
464             throw new java.lang.ArrayIndexOutOfBoundsException JavaDoc();
465
466         // Get the setup parameter
467

468         return getParameterLong(idx + STD_PARAMS);
469     }
470
471     /**
472      * Set the total parameter block length, in bytes
473      *
474      * @param cnt int
475      */

476     public final void setTotalParameterCount(int cnt)
477     {
478         setParameter(0, cnt);
479     }
480
481     /**
482      * Set the total data block length, in bytes
483      *
484      * @param cnt int
485      */

486     public final void setTotalDataCount(int cnt)
487     {
488         setParameter(1, cnt);
489     }
490
491     /**
492      * Set the parameter block count for this packet
493      *
494      * @param len int
495      */

496     public final void setParameterBlockCount(int len)
497     {
498         setParameter(3, len);
499     }
500
501     /**
502      * Set the parameter block offset
503      *
504      * @param off int
505      */

506     public final void setParameterBlockOffset(int off)
507     {
508         setParameter(4, off != 0 ? off - RFCNetBIOSProtocol.HEADER_LEN : 0);
509     }
510
511     /**
512      * Set the parameter block displacement within the total parameter block
513      *
514      * @param disp int
515      */

516     public final void setParameterBlockDisplacement(int disp)
517     {
518         setParameter(5, disp);
519     }
520
521     /**
522      * Set the data block count for this packet
523      *
524      * @param len int
525      */

526     public final void setDataBlockCount(int len)
527     {
528         setParameter(6, len);
529     }
530
531     /**
532      * Set the data block offset, from the start of the packet
533      *
534      * @param off int
535      */

536     public final void setDataBlockOffset(int off)
537     {
538         setParameter(7, off != 0 ? off - RFCNetBIOSProtocol.HEADER_LEN : 0);
539     }
540
541     /**
542      * Set the data block displacement within the total data block
543      *
544      * @param disp int
545      */

546     public final void setDataBlockDisplacement(int disp)
547     {
548         setParameter(8, disp);
549     }
550
551     /**
552      * Send one or more transaction response SMBs to the client
553      *
554      * @param sess SMBSrvSession
555      * @param tbuf TransactBuffer
556      * @exception java.io.IOException If an I/O error occurs.
557      */

558     protected final void doTransactionResponse(SMBSrvSession sess, TransactBuffer tbuf) throws IOException JavaDoc
559     {
560
561         // Initialize the transaction response packet
562

563         setCommand(tbuf.isType());
564
565         // Get the individual buffers from the transact buffer
566

567         tbuf.setEndOfBuffer();
568
569         DataBuffer setupBuf = tbuf.getSetupBuffer();
570         DataBuffer paramBuf = tbuf.getParameterBuffer();
571         DataBuffer dataBuf = tbuf.getDataBuffer();
572
573         // Set the parameter count
574

575         if (tbuf.hasSetupBuffer())
576             setParameterCount(StandardParamsResponse + setupBuf.getLengthInWords());
577         else
578             setParameterCount(StandardParamsResponse);
579
580         // Clear the parameters
581

582         for (int i = 0; i < getParameterCount(); i++)
583             setParameter(i, 0);
584
585         // Get the total parameter/data block lengths
586

587         int totParamLen = paramBuf != null ? paramBuf.getLength() : 0;
588         int totDataLen = dataBuf != null ? dataBuf.getLength() : 0;
589
590         // Initialize the parameters
591

592         setTotalParameterCount(totParamLen);
593         setTotalDataCount(totDataLen);
594
595         // Get the available data space within the packet
596

597         int availBuf = getAvailableLength();
598         int clientLen = getAvailableLength(sess.getClientMaximumBufferSize());
599         if (availBuf > clientLen)
600             availBuf = clientLen;
601
602         // Check if the transaction parameter block and data block will fit within a single request
603
// packet
604

605         int plen = totParamLen;
606         int dlen = totDataLen;
607
608         if ((plen + dlen) > availBuf)
609         {
610
611             // Calculate the parameter/data block sizes to send in the first request packet
612

613             if (plen > 0)
614             {
615
616                 // Check if the parameter block can fit into the packet
617

618                 if (plen <= availBuf)
619                 {
620
621                     // Pack all of the parameter block and fill the remaining buffer with the data
622
// block
623

624                     if (dlen > 0)
625                         dlen = availBuf - plen;
626                 }
627                 else
628                 {
629
630                     // Split the parameter/data space in the packet
631

632                     plen = availBuf / 2;
633                     dlen = plen;
634                 }
635             }
636             else if (dlen > availBuf)
637             {
638
639                 // Fill the packet with the first section of the data block
640

641                 dlen = availBuf;
642             }
643         }
644
645         // Set the parameter/data block counts for this packet
646

647         setParameterBlockCount(plen);
648         setDataBlockCount(dlen);
649
650         // Pack the setup bytes
651

652         if (setupBuf != null)
653             setupBuf.copyData(getBuffer(), SetupOffsetResponse);
654
655         // Pack the parameter block
656

657         int pos = DataPacker.wordAlign(getByteOffset());
658         setPosition(pos);
659
660         // Set the parameter block offset, from the start of the SMB packet
661

662         setParameterBlockCount(plen);
663         setParameterBlockOffset(pos);
664
665         int packLen = -1;
666
667         if (paramBuf != null)
668         {
669
670             // Pack the parameter block
671

672             packLen = paramBuf.copyData(getBuffer(), pos, plen);
673
674             // Update the buffer position for the data block
675

676             pos = DataPacker.longwordAlign(pos + packLen);
677             setPosition(pos);
678         }
679
680         // Set the data block offset
681

682         setDataBlockCount(dlen);
683         setDataBlockOffset(pos);
684
685         // Pack the data block
686

687         if (dataBuf != null)
688         {
689
690             // Pack the data block
691

692             packLen = dataBuf.copyData(getBuffer(), pos, dlen);
693
694             // Update the end of buffer position
695

696             setPosition(pos + packLen);
697         }
698
699         // Set the byte count for the SMB packet
700

701         setByteCount();
702
703         // Send the start of the transaction request
704

705         sess.sendResponseSMB(this);
706
707         // Get the available parameter/data block buffer space for the secondary packet
708

709         availBuf = getAvailableLength();
710         if (availBuf > clientLen)
711             availBuf = clientLen;
712
713         // Loop until all parameter/data block data has been sent to the server
714

715         TransactBuffer rxBuf = null;
716
717         while ((paramBuf != null && paramBuf.getAvailableLength() > 0)
718                 || (dataBuf != null && dataBuf.getAvailableLength() > 0))
719         {
720
721             // Setup the NT transaction secondary packet to send the remaining parameter/data blocks
722

723             setCommand(tbuf.isType());
724
725             // Get the remaining parameter/data block lengths
726

727             plen = paramBuf != null ? paramBuf.getAvailableLength() : 0;
728             dlen = dataBuf != null ? dataBuf.getAvailableLength() : 0;
729
730             if ((plen + dlen) > availBuf)
731             {
732
733                 // Calculate the parameter/data block sizes to send in the first request packet
734

735                 if (plen > 0)
736                 {
737
738                     // Check if the remaining parameter block can fit into the packet
739

740                     if (plen <= availBuf)
741                     {
742
743                         // Pack all of the parameter block and fill the remaining buffer with the
744
// data block
745

746                         if (dlen > 0)
747                             dlen = availBuf - plen;
748                     }
749                     else
750                     {
751
752                         // Split the parameter/data space in the packet
753

754                         plen = availBuf / 2;
755                         dlen = plen;
756                     }
757                 }
758                 else if (dlen > availBuf)
759                 {
760
761                     // Fill the packet with the first section of the data block
762

763                     dlen = availBuf;
764                 }
765             }
766
767             // Pack the parameter block data, if any
768

769             resetBytePointerAlign();
770
771             packLen = -1;
772             pos = getPosition();
773
774             if (plen > 0 && paramBuf != null)
775             {
776
777                 // Set the parameter block offset, from the start of the SMB packet
778

779                 setParameterBlockOffset(pos);
780                 setParameterBlockCount(plen);
781                 setParameterBlockDisplacement(paramBuf.getDisplacement());
782
783                 // Pack the parameter block
784

785                 packLen = paramBuf.copyData(getBuffer(), pos, plen);
786
787                 // Update the buffer position for the data block
788

789                 pos = DataPacker.wordAlign(pos + packLen);
790                 setPosition(pos);
791             }
792             else
793             {
794
795                 // No parameter data, clear the count/offset
796

797                 setParameterBlockCount(0);
798                 setParameterBlockOffset(pos);
799             }
800
801             // Pack the data block, if any
802

803             if (dlen > 0 && dataBuf != null)
804             {
805
806                 // Set the data block offset
807

808                 setDataBlockOffset(pos);
809                 setDataBlockCount(dlen);
810                 setDataBlockDisplacement(dataBuf.getDisplacement());
811
812                 // Pack the data block
813

814                 packLen = dataBuf.copyData(getBuffer(), pos, dlen);
815
816                 // Update the end of buffer position
817

818                 setPosition(pos + packLen);
819             }
820             else
821             {
822
823                 // No data, clear the count/offset
824

825                 setDataBlockCount(0);
826                 setDataBlockOffset(pos);
827             }
828
829             // Set the byte count for the SMB packet to set the overall length
830

831             setByteCount();
832
833             // Send the transaction response packet
834

835             sess.sendResponseSMB(this);
836         }
837     }
838 }
Popular Tags