TransPacket.java 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745
  1. /*
  2. * Copyright (C) 2006-2010 Alfresco Software Limited.
  3. *
  4. * This file is part of Alfresco
  5. *
  6. * Alfresco is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU Lesser General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Alfresco is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public License
  17. * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. package org.alfresco.jlan.client;
  20. import java.io.*;
  21. import org.alfresco.jlan.debug.Debug;
  22. import org.alfresco.jlan.netbios.RFCNetBIOSProtocol;
  23. import org.alfresco.jlan.smb.PacketType;
  24. import org.alfresco.jlan.smb.SMBException;
  25. import org.alfresco.jlan.smb.TransactBuffer;
  26. import org.alfresco.jlan.util.DataBuffer;
  27. import org.alfresco.jlan.util.DataPacker;
  28. /**
  29. * SMB transact packet class
  30. *
  31. * @author gkspencer
  32. */
  33. public class TransPacket extends SMBPacket {
  34. // Define the number of standard parameters sent/received
  35. protected static final int StandardParams = 14;
  36. protected static final int RxStandardParams = 10;
  37. // Offset to the setup paramaters, not including the sub-function
  38. protected static final int SetupOffset = PARAMWORDS + (StandardParams * 2) + 2;
  39. // Transact name, not used for transact 2
  40. protected String m_transName;
  41. // Parameter count for this transaction
  42. protected int m_paramCnt;
  43. /**
  44. * Class constructor
  45. *
  46. * @param buf Buffer that contains the SMB transaction packet.
  47. */
  48. public TransPacket(byte[] buf) {
  49. super(buf);
  50. }
  51. /**
  52. * Class constructor
  53. *
  54. * @param siz Size of packet to allocate.
  55. */
  56. public TransPacket(int siz) {
  57. super(siz);
  58. }
  59. /**
  60. * Return the data block size
  61. *
  62. * @return Data block size in bytes
  63. */
  64. public final int getDataLength() {
  65. return getParameter(6);
  66. }
  67. /**
  68. * Return the data block offset
  69. *
  70. * @return Data block offset within the SMB packet.
  71. */
  72. public final int getDataOffset() {
  73. return getParameter(7) + RFCNetBIOSProtocol.HEADER_LEN;
  74. }
  75. /**
  76. * Unpack the parameter block into the supplied array.
  77. *
  78. * @param prmblk Array to unpack the parameter block words into.
  79. */
  80. public final void getParameterBlock(short[] prmblk)
  81. throws java.lang.ArrayIndexOutOfBoundsException {
  82. // Determine how many parameters are to be unpacked, check if the user
  83. // buffer is long enough
  84. int prmcnt = getParameter(3) / 2; // convert to number of words
  85. if ( prmblk.length < prmcnt)
  86. throw new java.lang.ArrayIndexOutOfBoundsException();
  87. // Get the offset to the parameter words, add the NetBIOS header length
  88. // to the offset.
  89. int pos = getParameter(4) + RFCNetBIOSProtocol.HEADER_LEN;
  90. // Unpack the parameter words
  91. byte[] buf = getBuffer();
  92. for (int idx = 0; idx < prmcnt; idx++) {
  93. // Unpack the current parameter word
  94. prmblk[idx] = (short) DataPacker.getIntelShort(buf, pos);
  95. pos += 2;
  96. }
  97. // Debug mode
  98. if ( Debug.EnableInfo && Session.hasDebugOption(Session.DBGDumpPacket)) {
  99. Debug.println("Transaction parameter dump - " + prmcnt + " params :-");
  100. for (int i = 0; i < prmcnt; i++)
  101. Debug.println(" " + i + ". = " + prmblk[i] + ", 0x" + Integer.toHexString(prmblk[i]));
  102. }
  103. }
  104. /**
  105. * Perform a transaction request and receive the response data
  106. *
  107. * @param sess Session
  108. * @param tbuf TransactBuffer
  109. * @return TransactBuffer
  110. * @exception IOException
  111. * @exception SMBException
  112. */
  113. public final TransactBuffer doTransaction(Session sess, TransactBuffer tbuf)
  114. throws IOException, SMBException {
  115. // Initialize the transaction request packet
  116. int mid = sess.getNextMultiplexId();
  117. if ( tbuf.hasName())
  118. setCommand(PacketType.Transaction);
  119. else
  120. setCommand(PacketType.Transaction2);
  121. setFlags(sess.getDefaultFlags());
  122. setFlags2(sess.getDefaultFlags2());
  123. setMultiplexId(mid);
  124. setTreeId(sess.getTreeId());
  125. setUserId(sess.getUserId());
  126. // Get the individual buffers from the transact buffer
  127. tbuf.setEndOfBuffer();
  128. DataBuffer setupBuf = tbuf.getSetupBuffer();
  129. DataBuffer paramBuf = tbuf.getParameterBuffer();
  130. DataBuffer dataBuf = tbuf.getDataBuffer();
  131. // Set the parameter count, add the function code setup parameter
  132. if ( tbuf.hasSetupBuffer())
  133. setParameterCount(StandardParams + setupBuf.getLengthInWords() + 1);
  134. else
  135. setParameterCount(StandardParams + 1);
  136. // Clear the parameters
  137. for (int i = 0; i < getParameterCount(); i++)
  138. setParameter(i, 0);
  139. // Get the total parameter/data block lengths
  140. int totParamLen = paramBuf != null ? paramBuf.getLength() : 0;
  141. int totDataLen = dataBuf != null ? dataBuf.getLength() : 0;
  142. // Initialize the parameters
  143. setTotalParameterCount(totParamLen);
  144. setTotalDataCount(totDataLen);
  145. setMaximumParameterReturn(tbuf.getReturnParameterLimit());
  146. setMaximumDataReturn(tbuf.getReturnDataLimit());
  147. // Pack the transaction name for Transaction2
  148. int availBuf = getAvailableLength();
  149. int pos = getByteOffset();
  150. if ( tbuf.hasName()) {
  151. // Pack the transaction name string
  152. pos = DataPacker.putString(tbuf.getName(), getBuffer(), pos, false);
  153. // Update the available buffer space
  154. availBuf -= tbuf.getName().length();
  155. }
  156. // Check if the transaction parameter block and data block will fit within a single request
  157. // packet
  158. int plen = totParamLen;
  159. int dlen = totDataLen;
  160. if ( (plen + dlen) > availBuf) {
  161. // Calculate the parameter/data block sizes to send in the first request packet
  162. if ( plen > 0) {
  163. // Check if the parameter block can fit into the packet
  164. if ( plen <= availBuf) {
  165. // Pack all of the parameter block and fill the remaining buffer with the data
  166. // block
  167. if ( dlen > 0)
  168. dlen = availBuf - plen;
  169. }
  170. else {
  171. // Split the parameter/data space in the packet
  172. plen = availBuf / 2;
  173. dlen = plen;
  174. }
  175. }
  176. else if ( dlen > availBuf) {
  177. // Fill the packet with the first section of the data block
  178. dlen = availBuf;
  179. }
  180. }
  181. // Set the parameter/data block counts for this packet
  182. setParameterBlockCount(plen);
  183. setParameterBlockOffset(0);
  184. setDataBlockCount(dlen);
  185. setDataBlockOffset(0);
  186. setSetupCount(setupBuf != null ? setupBuf.getLengthInWords() : 1);
  187. setSetupParameter(0, tbuf.getFunction());
  188. // Pack the setup bytes
  189. if ( setupBuf != null)
  190. setupBuf.copyData(getBuffer(), SetupOffset);
  191. // Pack the parameter block
  192. pos = DataPacker.wordAlign(pos);
  193. setPosition(pos);
  194. // Set the parameter block offset, from the start of the SMB packet
  195. setParameterBlockOffset(pos);
  196. int packLen = -1;
  197. if ( paramBuf != null) {
  198. // Pack the parameter block
  199. packLen = paramBuf.copyData(getBuffer(), pos, plen);
  200. // Update the buffer position for the data block
  201. pos = DataPacker.wordAlign(pos + packLen);
  202. setPosition(pos);
  203. }
  204. // Set the data block offset
  205. setDataBlockOffset(pos);
  206. // Pack the data block
  207. if ( dataBuf != null) {
  208. // Pack the data block
  209. packLen = dataBuf.copyData(getBuffer(), pos, dlen);
  210. // Update the end of buffer position
  211. setPosition(pos + packLen);
  212. }
  213. // Set the byte count for the SMB packet
  214. setByteCount();
  215. // Send/receive the transaction
  216. TransactBuffer respBuf = null;
  217. try {
  218. // Indicate that we are in a transaction, for SMB signing
  219. sess.setTransactionMID(mid);
  220. // Send the start of the transaction request
  221. SendSMB(sess);
  222. // If the transaction has been split over several requests the server will send an
  223. // interim response
  224. if ( (paramBuf != null && paramBuf.getAvailableLength() > 0) || (dataBuf != null && dataBuf.getAvailableLength() > 0)) {
  225. // Receive the interim response SMB
  226. ReceiveSMB(sess);
  227. }
  228. // Get the available parameter/data block buffer space for the secondary packet
  229. availBuf = getAvailableLength();
  230. // Loop until all parameter/data block data has been sent to the server
  231. while ((paramBuf != null && paramBuf.getAvailableLength() > 0)
  232. || (dataBuf != null && dataBuf.getAvailableLength() > 0)) {
  233. // Setup the transaction secondary packet to send the remaining parameter/data
  234. // blocks
  235. setCommand(tbuf.isType() == PacketType.Transaction ? PacketType.TransactionSecond : PacketType.Transaction2Second);
  236. setFlags(sess.getDefaultFlags());
  237. setFlags2(sess.getDefaultFlags2());
  238. setParameterCount(8);
  239. setTotalParameterCount(totParamLen);
  240. setTotalDataCount(totDataLen);
  241. // Set a new multiple id for each secondary packet
  242. setMultiplexId(sess.getNextMultiplexId());
  243. // Get the remaining parameter/data block lengths
  244. plen = paramBuf != null ? paramBuf.getAvailableLength() : 0;
  245. dlen = dataBuf != null ? dataBuf.getAvailableLength() : 0;
  246. if ( (plen + dlen) > availBuf) {
  247. // Calculate the parameter/data block sizes to send in the first request packet
  248. if ( plen > 0) {
  249. // Check if the remaining parameter block can fit into the packet
  250. if ( plen <= availBuf) {
  251. // Pack all of the parameter block and fill the remaining buffer with
  252. // the data block
  253. if ( dlen > 0)
  254. dlen = availBuf - plen;
  255. }
  256. else {
  257. // Split the parameter/data space in the packet
  258. plen = availBuf / 2;
  259. dlen = plen;
  260. }
  261. }
  262. else if ( dlen > availBuf) {
  263. // Fill the packet with the first section of the data block
  264. dlen = availBuf;
  265. }
  266. }
  267. // Pack the parameter block data, if any
  268. resetBytePointerAlign();
  269. packLen = -1;
  270. pos = getPosition();
  271. if ( plen > 0 && paramBuf != null) {
  272. // Set the parameter block offset, from the start of the SMB packet
  273. setParameterBlockOffset(pos);
  274. // Pack the parameter block
  275. packLen = paramBuf.copyData(getBuffer(), pos, plen);
  276. // Update the buffer position for the data block
  277. pos = DataPacker.wordAlign(pos + packLen);
  278. setPosition(pos);
  279. }
  280. // Pack the data block, if any
  281. if ( dlen > 0 && dataBuf != null) {
  282. // Set the data block offset
  283. setDataBlockOffset(pos);
  284. // Pack the data block
  285. packLen = dataBuf.copyData(getBuffer(), pos, dlen);
  286. // Update the end of buffer position
  287. setPosition(pos + packLen);
  288. }
  289. // Set the byte count for the SMB packet to set the overall length
  290. setByteCount();
  291. // Send the transaction secondary request, there is no response sent until all of
  292. // the transaction
  293. // parameter/data blocks have been sent and the server processes the transaction
  294. SendSMB(sess);
  295. }
  296. // Set the packet type so that the receive processing filters the correct packet
  297. setCommand(tbuf.hasName() ? PacketType.Transaction : PacketType.Transaction2);
  298. // Receive the start of the transaction response
  299. ReceiveSMB(sess, false);
  300. // Check if the response is an error, there may be a warning to indicate that the reply
  301. // buffer is too short
  302. if ( isValidResponse() == false) // || warning_status
  303. checkForError();
  304. // Get the total return parameter block and data block lengths, and allocate the
  305. // response transaction buffer
  306. totParamLen = getTotalParameterCount();
  307. totDataLen = getTotalDataCount();
  308. int setupLen = (getParameterCount() - RxStandardParams) * 2;
  309. respBuf = new TransactBuffer(setupLen, totParamLen, totDataLen);
  310. respBuf.setUnicode(isUnicode());
  311. // Get the individual buffers from the transact buffer
  312. setupBuf = respBuf.getSetupBuffer();
  313. paramBuf = respBuf.getParameterBuffer();
  314. dataBuf = respBuf.getDataBuffer();
  315. // Copy the return setup parameters, if any
  316. if ( setupLen > 0)
  317. setupBuf.appendData(getBuffer(), SetupOffset, setupLen);
  318. // DEBUG
  319. if ( Debug.EnableInfo && Session.hasDebug())
  320. Debug.println("Receive transaction totParamLen=" + totParamLen + ", totDataLen=" + totDataLen);
  321. // Copy the parameter/data sections to the response transaction buffer and receive
  322. // additional response SMBs until all of the response has been processed
  323. while ((paramBuf != null && paramBuf.getUsedLength() < totParamLen)
  324. || (dataBuf != null && dataBuf.getUsedLength() < totDataLen)) {
  325. // Copy the parameter data from the packet to the response buffer
  326. plen = getParameterBlockCount();
  327. if ( plen > 0 && paramBuf != null) {
  328. // Copy the parameter block section to the response buffer
  329. paramBuf.appendData(getBuffer(), getParameterBlockOffset(), plen);
  330. // DEBUG
  331. if ( Debug.EnableInfo && Session.hasDebug())
  332. Debug.println(" Receive param plen=" + plen + ", poff=" + getParameterBlockOffset());
  333. }
  334. // Copy the data from the packet to the response buffer
  335. dlen = getDataBlockCount();
  336. if ( dlen > 0 && dataBuf != null) {
  337. // Copy the data block section to the response buffer
  338. dataBuf.appendData(getBuffer(), getDataBlockOffset(), dlen);
  339. // DEBUG
  340. if ( Debug.EnableInfo && Session.hasDebug())
  341. Debug.println(" Receive data dlen=" + dlen + ", doff=" + getDataBlockOffset());
  342. }
  343. // Check if we have received all the parameter/data block data
  344. if ( (paramBuf != null && paramBuf.getUsedLength() < totParamLen)
  345. || (dataBuf != null && dataBuf.getUsedLength() < totDataLen)) {
  346. // DEBUG
  347. if ( Debug.EnableInfo && Session.hasDebug())
  348. Debug.println(" Reading secondary trans pkt ...");
  349. // Read another packet of transaction response data
  350. ReceiveSMB(sess, false);
  351. // Check the receive status
  352. if ( isValidResponse() == false)
  353. checkForError();
  354. // Get the total parameter/data block lengths as they can change
  355. totParamLen = getTotalParameterCount();
  356. totDataLen = getTotalDataCount();
  357. }
  358. }
  359. // DEBUG
  360. if ( Debug.EnableInfo && Session.hasDebug())
  361. Debug.println(" Finished reading trans data respBuf=" + respBuf);
  362. // Reset the receive data buffers to read the data
  363. if ( respBuf != null)
  364. respBuf.setEndOfBuffer();
  365. }
  366. finally {
  367. // Indicate that the transaction is complete, for SMB signing
  368. sess.setTransactionMID(Session.NO_TRANSACTION);
  369. }
  370. // Return the response transaction buffer
  371. return respBuf;
  372. }
  373. /**
  374. * Return the total parameter block length
  375. *
  376. * @return int
  377. */
  378. public final int getTotalParameterCount() {
  379. return getParameter(0);
  380. }
  381. /**
  382. * Return the total data block length
  383. *
  384. * @return int
  385. */
  386. public final int getTotalDataCount() {
  387. return getParameter(1);
  388. }
  389. /**
  390. * Return the parameter block length for the current packet
  391. *
  392. * @return int
  393. */
  394. public final int getParameterBlockCount() {
  395. if ( isResponse())
  396. return getParameter(3);
  397. else if ( isType() == PacketType.Transaction || isType() == PacketType.Transaction2)
  398. return getParameter(9);
  399. else
  400. return getParameter(2);
  401. }
  402. /**
  403. * Return the parameter block offset for the current packet
  404. *
  405. * @return int
  406. */
  407. public final int getParameterBlockOffset() {
  408. int off = -1;
  409. if ( isResponse())
  410. off = getParameter(4);
  411. else if ( isType() == PacketType.Transaction || isType() == PacketType.Transaction2)
  412. off = getParameter(10);
  413. else
  414. return getParameter(3);
  415. return off + RFCNetBIOSProtocol.HEADER_LEN;
  416. }
  417. /**
  418. * Return the data block length for the current packet
  419. *
  420. * @return int
  421. */
  422. public final int getDataBlockCount() {
  423. if ( isResponse())
  424. return getParameter(6);
  425. if ( isType() == PacketType.Transaction || isType() == PacketType.Transaction2)
  426. return getParameter(11);
  427. else
  428. return getParameter(5);
  429. }
  430. /**
  431. * Return the data block offset for the current packet
  432. *
  433. * @return int
  434. */
  435. public final int getDataBlockOffset() {
  436. int off = -1;
  437. if ( isResponse())
  438. off = getParameter(7);
  439. else if ( isType() == PacketType.Transaction || isType() == PacketType.Transaction2)
  440. off = getParameter(12);
  441. else
  442. off = getParameter(6);
  443. return off + RFCNetBIOSProtocol.HEADER_LEN;
  444. }
  445. /**
  446. * Set the specific setup parameter within the SMB packet.
  447. *
  448. * @param idx Setup parameter index.
  449. * @param val Setup parameter value.
  450. */
  451. public final void setSetupParameter(int idx, int val) {
  452. setParameter(StandardParams + idx, val);
  453. }
  454. /**
  455. * Set the transaction name for normal transactions
  456. *
  457. * @param tname Transaction name string
  458. */
  459. public final void setTransactionName(String tname) {
  460. m_transName = tname;
  461. }
  462. /**
  463. * Set the total parameter block length parameter
  464. *
  465. * @param len int
  466. */
  467. public final void setTotalParameterCount(int len) {
  468. setParameter(0, len);
  469. }
  470. /**
  471. * Set the total data block length parameter
  472. *
  473. * @param len int
  474. */
  475. public final void setTotalDataCount(int len) {
  476. setParameter(1, len);
  477. }
  478. /**
  479. * Set the maximum return parameter block length parameter
  480. *
  481. * @param len int
  482. */
  483. public final void setMaximumParameterReturn(int len) {
  484. setParameter(2, len);
  485. }
  486. /**
  487. * Set the maximum return data block length parameter
  488. *
  489. * @param len int
  490. */
  491. public final void setMaximumDataReturn(int len) {
  492. setParameter(3, len);
  493. }
  494. /**
  495. * Set the parameter block section length parameter
  496. *
  497. * @param len int
  498. */
  499. public final void setParameterBlockCount(int len) {
  500. setParameter(9, len);
  501. }
  502. /**
  503. * Set the parameter block section offset parameter
  504. *
  505. * @param off int
  506. */
  507. public final void setParameterBlockOffset(int off) {
  508. setParameter(10, off != 0 ? off - RFCNetBIOSProtocol.HEADER_LEN : 0);
  509. }
  510. /**
  511. * Set the data block section length parameter
  512. *
  513. * @param len int
  514. */
  515. public final void setDataBlockCount(int len) {
  516. setParameter(11, len);
  517. }
  518. /**
  519. * Set the data block section offset parameter
  520. *
  521. * @param off int
  522. */
  523. public final void setDataBlockOffset(int off) {
  524. setParameter(12, off != 0 ? off - RFCNetBIOSProtocol.HEADER_LEN : 0);
  525. }
  526. /**
  527. * Set the setup paramater count
  528. *
  529. * @param cnt int
  530. */
  531. public final void setSetupCount(int cnt) {
  532. setParameter(13, cnt);
  533. }
  534. }