1 17 18 19 package org.apache.coyote.http11; 20 21 import java.io.EOFException ; 22 import java.io.IOException ; 23 import java.nio.channels.Selector ; 24 25 import org.apache.coyote.InputBuffer; 26 import org.apache.coyote.Request; 27 import org.apache.tomcat.util.buf.ByteChunk; 28 import org.apache.tomcat.util.buf.MessageBytes; 29 import org.apache.tomcat.util.http.MimeHeaders; 30 import org.apache.tomcat.util.net.NioChannel; 31 import org.apache.tomcat.util.net.NioSelectorPool; 32 import org.apache.tomcat.util.res.StringManager; 33 34 41 public class InternalNioInputBuffer implements InputBuffer { 42 43 44 46 enum HeaderParseStatus {DONE, HAVE_MORE_HEADERS, NEED_MORE_DATA} 47 enum HeaderParsePosition {HEADER_START, HEADER_NAME, HEADER_VALUE, HEADER_MULTI_LINE} 48 50 51 54 public InternalNioInputBuffer(Request request, int headerBufferSize, 55 long readTimeout) { 56 57 this.request = request; 58 headers = request.getMimeHeaders(); 59 60 buf = new byte[headerBufferSize]; 61 67 inputStreamInputBuffer = new SocketInputBuffer(); 68 69 filterLibrary = new InputFilter[0]; 70 activeFilters = new InputFilter[0]; 71 lastActiveFilter = -1; 72 73 parsingHeader = true; 74 parsingRequestLine = true; 75 headerParsePos = HeaderParsePosition.HEADER_START; 76 headerData.recycle(); 77 swallowInput = true; 78 79 if (readTimeout < 0) { 80 this.readTimeout = -1; 81 } else { 82 this.readTimeout = readTimeout; 83 } 84 85 } 86 87 88 90 91 94 protected static StringManager sm = 95 StringManager.getManager(Constants.Package); 96 97 98 100 101 104 protected Request request; 105 106 107 110 protected MimeHeaders headers; 111 112 113 116 protected boolean parsingHeader; 117 protected boolean parsingRequestLine; 118 protected HeaderParsePosition headerParsePos; 119 120 121 124 protected boolean swallowInput; 125 126 127 130 protected byte[] buf; 131 132 133 136 protected int lastValid; 137 138 139 142 protected int pos; 143 144 145 149 protected int end; 150 151 152 153 156 protected NioChannel socket; 157 158 161 protected NioSelectorPool pool; 162 163 164 167 protected InputBuffer inputStreamInputBuffer; 168 169 170 174 protected InputFilter[] filterLibrary; 175 176 177 180 protected InputFilter[] activeFilters; 181 182 183 186 protected int lastActiveFilter; 187 188 189 193 protected long readTimeout; 194 195 197 198 201 public void setSocket(NioChannel socket) { 202 this.socket = socket; 203 } 204 205 208 public NioChannel getSocket() { 209 return socket; 210 } 211 212 public void setSelectorPool(NioSelectorPool pool) { 213 this.pool = pool; 214 } 215 216 public NioSelectorPool getSelectorPool() { 217 return pool; 218 } 219 220 221 224 public void addFilter(InputFilter filter) { 225 226 InputFilter[] newFilterLibrary = 227 new InputFilter[filterLibrary.length + 1]; 228 for (int i = 0; i < filterLibrary.length; i++) { 229 newFilterLibrary[i] = filterLibrary[i]; 230 } 231 newFilterLibrary[filterLibrary.length] = filter; 232 filterLibrary = newFilterLibrary; 233 234 activeFilters = new InputFilter[filterLibrary.length]; 235 236 } 237 238 239 242 public InputFilter[] getFilters() { 243 244 return filterLibrary; 245 246 } 247 248 249 252 public void clearFilters() { 253 254 filterLibrary = new InputFilter[0]; 255 lastActiveFilter = -1; 256 257 } 258 259 260 263 public void addActiveFilter(InputFilter filter) { 264 265 if (lastActiveFilter == -1) { 266 filter.setBuffer(inputStreamInputBuffer); 267 } else { 268 for (int i = 0; i <= lastActiveFilter; i++) { 269 if (activeFilters[i] == filter) 270 return; 271 } 272 filter.setBuffer(activeFilters[lastActiveFilter]); 273 } 274 275 activeFilters[++lastActiveFilter] = filter; 276 277 filter.setRequest(request); 278 279 } 280 281 282 285 public void setSwallowInput(boolean swallowInput) { 286 this.swallowInput = swallowInput; 287 } 288 289 291 292 296 public void recycle() { 297 298 request.recycle(); 300 301 socket = null; 302 lastValid = 0; 303 pos = 0; 304 lastActiveFilter = -1; 305 parsingHeader = true; 306 headerParsePos = HeaderParsePosition.HEADER_START; 307 parsingRequestLine = true; 308 headerData.recycle(); 309 swallowInput = true; 310 311 } 312 313 314 320 public void nextRequest() { 321 322 request.recycle(); 324 325 if (lastValid - pos > 0) { 328 int npos = 0; 329 int opos = pos; 330 while (lastValid - opos > opos - npos) { 331 System.arraycopy(buf, opos, buf, npos, opos - npos); 332 npos += pos; 333 opos += pos; 334 } 335 System.arraycopy(buf, opos, buf, npos, lastValid - opos); 336 } 337 338 for (int i = 0; i <= lastActiveFilter; i++) { 340 activeFilters[i].recycle(); 341 } 342 343 lastValid = lastValid - pos; 345 pos = 0; 346 lastActiveFilter = -1; 347 parsingHeader = true; 348 headerParsePos = HeaderParsePosition.HEADER_START; 349 parsingRequestLine = true; 350 headerData.recycle(); 351 swallowInput = true; 352 353 } 354 355 356 361 public void endRequest() 362 throws IOException { 363 364 if (swallowInput && (lastActiveFilter != -1)) { 365 int extraBytes = (int) activeFilters[lastActiveFilter].end(); 366 pos = pos - extraBytes; 367 } 368 369 } 370 371 372 383 public boolean parseRequestLine(boolean useAvailableData) 384 throws IOException { 385 386 if ( !parsingRequestLine ) return true; 388 389 int start = 0; 390 391 395 byte chr = 0; 396 do { 397 398 if (pos >= lastValid) { 400 if (useAvailableData) { 401 return false; 402 } 403 if (readTimeout == -1) { 404 if (!fill(false,true)) throw new EOFException (sm.getString("iib.eof.error")); 406 } else { 407 if ( !readSocket(true, false) ) return false; 409 } 410 } 411 412 chr = buf[pos++]; 413 414 } while ((chr == Constants.CR) || (chr == Constants.LF)); 415 416 pos--; 417 418 start = pos; 420 421 if (pos >= lastValid) { 422 if (useAvailableData) { 423 return false; 424 } 425 if (readTimeout == -1) { 426 if (!fill(false,false)) return false; 428 } else { 429 if ( !readSocket(true, false) ) return false; 431 } 432 } 433 434 439 boolean space = false; 440 441 while (!space) { 442 443 if (pos >= lastValid) { 445 if (!fill(true,false)) return false; 447 } 448 449 if (buf[pos] == Constants.SP) { 450 space = true; 451 request.method().setBytes(buf, start, pos - start); 452 } 453 454 pos++; 455 456 } 457 458 start = pos; 460 int end = 0; 461 int questionPos = -1; 462 463 467 space = false; 468 boolean eol = false; 469 470 while (!space) { 471 472 if (pos >= lastValid) { 474 if (!fill(true,false)) return false; 476 } 477 478 if (buf[pos] == Constants.SP) { 479 space = true; 480 end = pos; 481 } else if ((buf[pos] == Constants.CR) 482 || (buf[pos] == Constants.LF)) { 483 eol = true; 485 space = true; 486 end = pos; 487 } else if ((buf[pos] == Constants.QUESTION) 488 && (questionPos == -1)) { 489 questionPos = pos; 490 } 491 492 pos++; 493 494 } 495 496 request.unparsedURI().setBytes(buf, start, end - start); 497 if (questionPos >= 0) { 498 request.queryString().setBytes(buf, questionPos + 1, 499 end - questionPos - 1); 500 request.requestURI().setBytes(buf, start, questionPos - start); 501 } else { 502 request.requestURI().setBytes(buf, start, end - start); 503 } 504 505 start = pos; 507 end = 0; 508 509 514 while (!eol) { 515 516 if (pos >= lastValid) { 518 if (!fill(true,false)) return false; 520 } 521 522 if (buf[pos] == Constants.CR) { 523 end = pos; 524 } else if (buf[pos] == Constants.LF) { 525 if (end == 0) 526 end = pos; 527 eol = true; 528 } 529 530 pos++; 531 532 } 533 534 if ((end - start) > 0) { 535 request.protocol().setBytes(buf, start, end - start); 536 } else { 537 request.protocol().setString(""); 538 } 539 parsingRequestLine = false; 540 return true; 541 542 } 543 544 private void expand(int newsize) { 545 if ( newsize > buf.length ) { 546 byte[] tmp = new byte[newsize]; 547 System.arraycopy(buf,0,tmp,0,buf.length); 548 buf = tmp; 549 tmp = null; 550 } 551 } 552 560 private boolean readSocket(boolean timeout, boolean block) throws IOException { 561 int nRead = 0; 562 long rto = timeout?this.readTimeout:-1; 563 socket.getBufHandler().getReadBuffer().clear(); 564 if ( block ) { 565 Selector selector = null; 566 try { selector = getSelectorPool().get(); }catch ( IOException x ) {} 567 try { 568 nRead = getSelectorPool().read(socket.getBufHandler().getReadBuffer(),socket,selector,rto); 569 } catch ( EOFException eof ) { 570 nRead = -1; 571 } finally { 572 if ( selector != null ) getSelectorPool().put(selector); 573 } 574 } else { 575 nRead = socket.read(socket.getBufHandler().getReadBuffer()); 576 } 577 if (nRead > 0) { 578 socket.getBufHandler().getReadBuffer().flip(); 579 socket.getBufHandler().getReadBuffer().limit(nRead); 580 expand(nRead + pos); 581 socket.getBufHandler().getReadBuffer().get(buf, pos, nRead); 582 lastValid = pos + nRead; 583 return true; 584 } else if (nRead == -1) { 585 throw new EOFException (sm.getString("iib.eof.error")); 587 } else { 588 return false; 589 } 590 } 591 592 595 public boolean parseHeaders() 596 throws IOException { 597 HeaderParseStatus status = HeaderParseStatus.HAVE_MORE_HEADERS; 598 599 do { 600 status = parseHeader(); 601 } while ( status == HeaderParseStatus.HAVE_MORE_HEADERS ); 602 if (status == HeaderParseStatus.DONE) { 603 parsingHeader = false; 604 end = pos; 605 return true; 606 } else { 607 return false; 608 } 609 } 610 611 612 618 public HeaderParseStatus parseHeader() 619 throws IOException { 620 621 625 byte chr = 0; 626 while (headerParsePos == HeaderParsePosition.HEADER_START) { 627 628 if (pos >= lastValid) { 630 if (!fill(true,false)) { headerParsePos = HeaderParsePosition.HEADER_START; 632 return HeaderParseStatus.NEED_MORE_DATA; 633 } 634 } 635 636 chr = buf[pos]; 637 638 if ((chr == Constants.CR) || (chr == Constants.LF)) { 639 if (chr == Constants.LF) { 640 pos++; 641 return HeaderParseStatus.DONE; 642 } 643 } else { 644 break; 645 } 646 647 pos++; 648 649 } 650 651 if ( headerParsePos == HeaderParsePosition.HEADER_START ) { 652 headerData.start = pos; 654 headerParsePos = HeaderParsePosition.HEADER_NAME; 655 } 656 657 662 663 664 while (headerParsePos == HeaderParsePosition.HEADER_NAME) { 665 666 if (pos >= lastValid) { 668 if (!fill(true,false)) { return HeaderParseStatus.NEED_MORE_DATA; 670 } 671 } 672 673 if (buf[pos] == Constants.COLON) { 674 headerParsePos = HeaderParsePosition.HEADER_VALUE; 675 headerData.headerValue = headers.addValue(buf, headerData.start, pos - headerData.start); 676 } 677 chr = buf[pos]; 678 if ((chr >= Constants.A) && (chr <= Constants.Z)) { 679 buf[pos] = (byte) (chr - Constants.LC_OFFSET); 680 } 681 682 pos++; 683 if ( headerParsePos == HeaderParsePosition.HEADER_VALUE ) { 684 headerData.start = pos; 686 headerData.realPos = pos; 687 } 688 } 689 690 691 695 boolean eol = false; 696 697 while (headerParsePos == HeaderParsePosition.HEADER_VALUE || 698 headerParsePos == HeaderParsePosition.HEADER_MULTI_LINE) { 699 if ( headerParsePos == HeaderParsePosition.HEADER_VALUE ) { 700 701 boolean space = true; 702 703 while (space) { 705 706 if (pos >= lastValid) { 708 if (!fill(true,false)) { return HeaderParseStatus.NEED_MORE_DATA; 711 } 712 } 713 714 if ((buf[pos] == Constants.SP) || (buf[pos] == Constants.HT)) { 715 pos++; 716 } else { 717 space = false; 718 } 719 720 } 721 722 headerData.lastSignificantChar = headerData.realPos; 723 724 while (!eol) { 726 727 if (pos >= lastValid) { 729 if (!fill(true,false)) { return HeaderParseStatus.NEED_MORE_DATA; 732 } 733 734 } 735 736 if (buf[pos] == Constants.CR) { 737 } else if (buf[pos] == Constants.LF) { 738 eol = true; 739 } else if (buf[pos] == Constants.SP) { 740 buf[headerData.realPos] = buf[pos]; 741 headerData.realPos++; 742 } else { 743 buf[headerData.realPos] = buf[pos]; 744 headerData.realPos++; 745 headerData.lastSignificantChar = headerData.realPos; 746 } 747 748 pos++; 749 750 } 751 752 headerData.realPos = headerData.lastSignificantChar; 753 754 headerParsePos = HeaderParsePosition.HEADER_MULTI_LINE; 757 } 758 if (pos >= lastValid) { 760 if (!fill(true,false)) { 762 return HeaderParseStatus.NEED_MORE_DATA; 764 } 765 } 766 767 chr = buf[pos]; 768 if ( headerParsePos == HeaderParsePosition.HEADER_MULTI_LINE ) { 769 if ( (chr != Constants.SP) && (chr != Constants.HT)) { 770 headerParsePos = HeaderParsePosition.HEADER_START; 771 } else { 772 eol = false; 773 buf[headerData.realPos] = chr; 776 headerData.realPos++; 777 } 778 } 779 } 780 headerData.headerValue.setBytes(buf, headerData.start, headerData.realPos - headerData.start); 782 headerData.recycle(); 783 return HeaderParseStatus.HAVE_MORE_HEADERS; 784 } 785 786 protected HeaderParseData headerData = new HeaderParseData(); 787 public static class HeaderParseData { 788 int start = 0; 789 int realPos = 0; 790 int lastSignificantChar = 0; 791 MessageBytes headerValue = null; 792 public void recycle() { 793 start = 0; 794 realPos = 0; 795 lastSignificantChar = 0; 796 headerValue = null; 797 } 798 } 799 800 801 803 804 807 public int doRead(ByteChunk chunk, Request req) 808 throws IOException { 809 810 if (lastActiveFilter == -1) 811 return inputStreamInputBuffer.doRead(chunk, req); 812 else 813 return activeFilters[lastActiveFilter].doRead(chunk,req); 814 815 } 816 817 818 820 825 protected boolean fill(boolean timeout, boolean block) 826 throws IOException , EOFException { 827 828 boolean read = false; 829 830 if (parsingHeader) { 831 832 if (lastValid == buf.length) { 833 throw new IOException 834 (sm.getString("iib.requestheadertoolarge.error")); 835 } 836 837 read = readSocket(timeout,block); 839 } else { 840 841 if (buf.length - end < 4500) { 842 buf = new byte[buf.length]; 846 end = 0; 847 } 848 pos = end; 849 lastValid = pos; 850 read = readSocket(timeout, block); 852 } 853 return read; 854 } 855 856 857 859 860 864 protected class SocketInputBuffer 865 implements InputBuffer { 866 867 868 871 public int doRead(ByteChunk chunk, Request req ) 872 throws IOException { 873 874 if (pos >= lastValid) { 875 if (!fill(true,true)) return -1; 877 } 878 879 int length = lastValid - pos; 880 chunk.setBytes(buf, pos, length); 881 pos = lastValid; 882 883 return (length); 884 885 } 886 887 888 } 889 890 891 } 892 | Popular Tags |