Mercurial Hosting > luan
comparison src/org/eclipse/jetty/http/HttpGenerator.java @ 1070:a44fc6b53757
fix use of HttpGenerator._buffer
| author | Franklin Schmidt <fschmidt@gmail.com> |
|---|---|
| date | Thu, 10 Nov 2016 01:23:37 -0700 |
| parents | 7dd6ec499000 |
| children | b4ba8a4d5a16 |
comparison
equal
deleted
inserted
replaced
| 1069:7dd6ec499000 | 1070:a44fc6b53757 |
|---|---|
| 176 if (_head) | 176 if (_head) |
| 177 { | 177 { |
| 178 // content.clear(); | 178 // content.clear(); |
| 179 _content = null; | 179 _content = null; |
| 180 } | 180 } |
| 181 else if ((_buffer==null || _buffer.remaining()==0) && _content.hasRemaining() && (_last || isCommitted() && _content.remaining()>1024)) | 181 else if ((_buffer.position()==0) && _content.hasRemaining() && (_last || isCommitted() && _content.remaining()>1024)) |
| 182 { | 182 { |
| 183 _bypass = true; | 183 _bypass = true; |
| 184 } | 184 } |
| 185 else if (!_bufferChunked) | 185 else if (!_bufferChunked) |
| 186 { | 186 { |
| 187 //System.out.println("qqqqqqqqqqqqqqqqqqq c"); | 187 //System.out.println("qqqqqqqqqqqqqqqqqqq c"); |
| 188 // Copy _content to buffer; | 188 // Copy _content to buffer; |
| 189 int len = _buffer.put(_content); | 189 _buffer.putQ(_content); |
| 190 _content.skip(len); | |
| 191 if (!_content.hasRemaining()) | 190 if (!_content.hasRemaining()) |
| 192 _content = null; | 191 _content = null; |
| 193 } | 192 } |
| 194 } | 193 } |
| 195 | 194 |
| 215 flushBuffer(); | 214 flushBuffer(); |
| 216 if (_content != null && _content.hasRemaining() || _bufferChunked) | 215 if (_content != null && _content.hasRemaining() || _bufferChunked) |
| 217 throw new IllegalStateException("FULL"); | 216 throw new IllegalStateException("FULL"); |
| 218 } | 217 } |
| 219 | 218 |
| 220 _contentWritten -= _buffer.remaining(); | 219 _contentWritten -= _buffer.position(); |
| 221 /* | 220 /* |
| 222 // Handle the _content | 221 // Handle the _content |
| 223 if (_head) | 222 if (_head) |
| 224 return Integer.MAX_VALUE; | 223 return Integer.MAX_VALUE; |
| 225 | 224 |
| 228 } | 227 } |
| 229 | 228 |
| 230 public boolean isBufferFull() | 229 public boolean isBufferFull() |
| 231 { | 230 { |
| 232 // Should we flush the buffers? | 231 // Should we flush the buffers? |
| 233 return isBufferFull2() || _bufferChunked || _bypass /* || (_contentLength == HttpTokens.CHUNKED_CONTENT && _buffer != null && _buffer.space() < CHUNK_SPACE)*/; | 232 return isBufferFull2() || _bufferChunked || _bypass /* || (_contentLength == HttpTokens.CHUNKED_CONTENT && _buffer.remaining() < CHUNK_SPACE)*/; |
| 234 } | 233 } |
| 235 | 234 |
| 236 public void send1xx(int code) throws IOException | 235 public void send1xx(int code) throws IOException |
| 237 { | 236 { |
| 238 if (_state != STATE_HEADER) | 237 if (_state != STATE_HEADER) |
| 332 | 331 |
| 333 if (_status<200 && _status>=100 ) | 332 if (_status<200 && _status>=100 ) |
| 334 { | 333 { |
| 335 _noContent = true; | 334 _noContent = true; |
| 336 _content = null; | 335 _content = null; |
| 337 if (_buffer!=null) | 336 _buffer.clear(); |
| 338 _buffer.clearJ(); | |
| 339 // end the header. | 337 // end the header. |
| 340 | 338 |
| 341 if (_status!=101 ) | 339 if (_status!=101 ) |
| 342 { | 340 { |
| 343 _header.putQ(HttpTokens.CRLF); | 341 _header.putQ(HttpTokens.CRLF); |
| 347 } | 345 } |
| 348 else if (_status==204 || _status==304) | 346 else if (_status==204 || _status==304) |
| 349 { | 347 { |
| 350 _noContent = true; | 348 _noContent = true; |
| 351 _content = null; | 349 _content = null; |
| 352 if (_buffer!=null) | 350 _buffer.clear(); |
| 353 _buffer.clearJ(); | |
| 354 } | 351 } |
| 355 } | 352 } |
| 356 | 353 |
| 357 // key field values | 354 // key field values |
| 358 HttpFields.Field content_length = null; | 355 HttpFields.Field content_length = null; |
| 668 //qqq | 665 //qqq |
| 669 case 7: | 666 case 7: |
| 670 throw new IllegalStateException(); // should never happen! | 667 throw new IllegalStateException(); // should never happen! |
| 671 case 6: | 668 case 6: |
| 672 _header.flip(); | 669 _header.flip(); |
| 670 _buffer.flip(); | |
| 673 len = _endp.flush(_header, _buffer, null); | 671 len = _endp.flush(_header, _buffer, null); |
| 674 _header.compact(); | 672 _header.compact(); |
| 673 _buffer.compact(); | |
| 675 break; | 674 break; |
| 676 case 5: | 675 case 5: |
| 677 _header.flip(); | 676 _header.flip(); |
| 678 len = _endp.flush(_header, _content, null); | 677 len = _endp.flush(_header, _content, null); |
| 679 _header.compact(); | 678 _header.compact(); |
| 682 _header.flip(); | 681 _header.flip(); |
| 683 len = _endp.flush(_header); | 682 len = _endp.flush(_header); |
| 684 _header.compact(); | 683 _header.compact(); |
| 685 break; | 684 break; |
| 686 case 3: | 685 case 3: |
| 686 _buffer.flip(); | |
| 687 len = _endp.flush(_buffer, _content, null); | 687 len = _endp.flush(_buffer, _content, null); |
| 688 _buffer.compact(); | |
| 688 break; | 689 break; |
| 689 case 2: | 690 case 2: |
| 691 _buffer.flip(); | |
| 690 len = _endp.flush(_buffer); | 692 len = _endp.flush(_buffer); |
| 693 _buffer.compact(); | |
| 691 break; | 694 break; |
| 692 case 1: | 695 case 1: |
| 693 len = _endp.flush(_content); | 696 len = _endp.flush(_content); |
| 694 break; | 697 break; |
| 695 case 0: | 698 case 0: |
| 696 { | 699 { |
| 697 len=0; | 700 len = 0; |
| 698 // Nothing more we can write now. | 701 // Nothing more we can write now. |
| 699 _header.clear(); | 702 _header.clear(); |
| 700 | 703 |
| 701 _bypass = false; | 704 _bypass = false; |
| 702 _bufferChunked = false; | 705 _bufferChunked = false; |
| 703 | 706 |
| 704 if (_buffer != null) | 707 _buffer.clear(); // ? |
| 708 if (_contentLength == HttpTokens.CHUNKED_CONTENT) | |
| 705 { | 709 { |
| 706 _buffer.clearJ(); | 710 // Special case handling for small left over buffer from |
| 707 if (_contentLength == HttpTokens.CHUNKED_CONTENT) | 711 // an addContent that caused a buffer flush. |
| 712 if (_content != null && _content.remaining() < _buffer.remaining() && _state != STATE_FLUSHING) | |
| 708 { | 713 { |
| 709 // Special case handling for small left over buffer from | 714 _buffer.putQ(_content); |
| 710 // an addContent that caused a buffer flush. | 715 _content = null; |
| 711 if (_content != null && _content.remaining() < _buffer.space() && _state != STATE_FLUSHING) | |
| 712 { | |
| 713 _buffer.put(_content); | |
| 714 _content = null; | |
| 715 } | |
| 716 } | 716 } |
| 717 } | 717 } |
| 718 | 718 |
| 719 // Are we completely finished for now? | 719 // Are we completely finished for now? |
| 720 if (!_needCRLF && !_needEOC && (_content==null || !_content.hasRemaining())) | 720 if (!_needCRLF && !_needEOC && (_content==null || !_content.hasRemaining())) |
| 743 return total; | 743 return total; |
| 744 } | 744 } |
| 745 catch (IOException e) | 745 catch (IOException e) |
| 746 { | 746 { |
| 747 LOG.trace("",e); | 747 LOG.trace("",e); |
| 748 throw (e instanceof EofException) ? e:new EofException(e); | 748 throw (e instanceof EofException) ? e : new EofException(e); |
| 749 } | 749 } |
| 750 } | 750 } |
| 751 | 751 |
| 752 private int flushMask() | 752 private int flushMask() |
| 753 { | 753 { |
| 754 return ((_header.position() > 0)?4:0) | 754 return ((_header.position() > 0)?4:0) |
| 755 | ((_buffer != null && _buffer.remaining() > 0)?2:0) | 755 | ((_buffer.position() > 0)?2:0) |
| 756 | ((_bypass && _content != null && _content.hasRemaining())?1:0); | 756 | ((_bypass && _content != null && _content.hasRemaining())?1:0); |
| 757 } | 757 } |
| 758 | 758 |
| 759 private void prepareBuffers() | 759 private void prepareBuffers() |
| 760 { | 760 { |
| 761 // if we are not flushing an existing chunk | 761 // if we are not flushing an existing chunk |
| 762 if (!_bufferChunked) | 762 if (!_bufferChunked) |
| 763 { | 763 { |
| 764 // Refill buffer if possible | 764 // Refill buffer if possible |
| 765 if (!_bypass && _content != null && _content.hasRemaining() && _buffer != null && _buffer.space() > 0) | 765 if (!_bypass && _content != null && _content.hasRemaining() && _buffer.hasRemaining()) |
| 766 { | 766 { |
| 767 int len = _buffer.put(_content); | 767 _buffer.putQ(_content); |
| 768 _content.skip(len); | |
| 769 if (!_content.hasRemaining()) | 768 if (!_content.hasRemaining()) |
| 770 _content = null; | 769 _content = null; |
| 771 } | 770 } |
| 772 | 771 |
| 773 // Chunk buffer if need be | 772 // Chunk buffer if need be |
| 774 if (_contentLength == HttpTokens.CHUNKED_CONTENT) | 773 if (_contentLength == HttpTokens.CHUNKED_CONTENT) |
| 775 { | 774 { |
| 776 if (_bypass && (_buffer==null||_buffer.remaining()==0) && _content!=null) | 775 if (_bypass && _buffer.position()==0 && _content!=null) |
| 777 { | 776 { |
| 778 // this is a bypass write | 777 // this is a bypass write |
| 779 int size = _content.remaining(); | 778 int size = _content.remaining(); |
| 780 _bufferChunked = true; | 779 _bufferChunked = true; |
| 781 | 780 |
| 791 _header.putQ(HttpTokens.CRLF); | 790 _header.putQ(HttpTokens.CRLF); |
| 792 | 791 |
| 793 // Need a CRLF after the content | 792 // Need a CRLF after the content |
| 794 _needCRLF = true; | 793 _needCRLF = true; |
| 795 } | 794 } |
| 796 else if (_buffer!=null) | 795 else |
| 797 { | 796 { |
| 798 int size = _buffer.remaining(); | 797 int size = _buffer.position(); |
| 799 if (size > 0) | 798 if (size > 0) |
| 800 { | 799 { |
| 801 // Prepare a chunk! | 800 // Prepare a chunk! |
| 802 _bufferChunked = true; | 801 _bufferChunked = true; |
| 803 | 802 |
| 809 } | 808 } |
| 810 BufferUtil.putHexInt(_header, size); | 809 BufferUtil.putHexInt(_header, size); |
| 811 _header.putQ(HttpTokens.CRLF); | 810 _header.putQ(HttpTokens.CRLF); |
| 812 | 811 |
| 813 // Add end chunk trailer. | 812 // Add end chunk trailer. |
| 814 if (_buffer.space() >= 2) | 813 if (_buffer.remaining() >= 2) |
| 815 _buffer.put(HttpTokens.CRLF); | 814 _buffer.putQ(HttpTokens.CRLF); |
| 816 else | 815 else |
| 817 _needCRLF = true; | 816 _needCRLF = true; |
| 818 } | 817 } |
| 819 } | 818 } |
| 820 | 819 |
| 821 // If we need EOC and everything written | 820 // If we need EOC and everything written |
| 822 if (_needEOC && (_content == null || !_content.hasRemaining())) | 821 if (_needEOC && (_content == null || !_content.hasRemaining())) |
| 823 { | 822 { |
| 824 if (_needCRLF) | 823 if (_needCRLF && _buffer.remaining() >= HttpTokens.CRLF.length) { |
| 825 { | 824 _buffer.putQ(HttpTokens.CRLF); |
| 826 if (_buffer == null && _header.remaining() >= HttpTokens.CRLF.length) | 825 _needCRLF = false; |
| 826 } | |
| 827 | |
| 828 if (!_needCRLF && _needEOC && _buffer.remaining() >= LAST_CHUNK.length) { | |
| 829 if (!_head) | |
| 827 { | 830 { |
| 828 _header.putQ(HttpTokens.CRLF); | 831 _buffer.putQ(LAST_CHUNK); |
| 829 _needCRLF = false; | 832 _bufferChunked = true; |
| 830 } | 833 } |
| 831 else if (_buffer!=null && _buffer.space() >= HttpTokens.CRLF.length) | 834 _needEOC = false; |
| 832 { | |
| 833 _buffer.put(HttpTokens.CRLF); | |
| 834 _needCRLF = false; | |
| 835 } | |
| 836 } | |
| 837 | |
| 838 if (!_needCRLF && _needEOC) | |
| 839 { | |
| 840 if (_buffer == null && _header.remaining() >= LAST_CHUNK.length) | |
| 841 { | |
| 842 if (!_head) | |
| 843 { | |
| 844 _header.putQ(LAST_CHUNK); | |
| 845 _bufferChunked=true; | |
| 846 } | |
| 847 _needEOC = false; | |
| 848 } | |
| 849 else if (_buffer!=null && _buffer.space() >= LAST_CHUNK.length) | |
| 850 { | |
| 851 if (!_head) | |
| 852 { | |
| 853 _buffer.put(LAST_CHUNK); | |
| 854 _bufferChunked=true; | |
| 855 } | |
| 856 _needEOC = false; | |
| 857 } | |
| 858 } | 835 } |
| 859 } | 836 } |
| 860 } | 837 } |
| 861 } | 838 } |
| 862 | 839 |
| 867 | 844 |
| 868 @Override | 845 @Override |
| 869 public String toString() | 846 public String toString() |
| 870 { | 847 { |
| 871 JBuffer header = _header; | 848 JBuffer header = _header; |
| 872 JBuffer buffer=_buffer; | 849 JBuffer buffer = _buffer; |
| 873 JBuffer content = _content; | 850 JBuffer content = _content; |
| 874 return String.format("%s{s=%d,h=%d,b=%d,c=%d}", | 851 return String.format("%s{s=%d,h=%d,b=%d,c=%d}", |
| 875 getClass().getSimpleName(), | 852 getClass().getSimpleName(), |
| 876 _state, | 853 _state, |
| 877 header == null ? -1 : header.position(), | 854 header == null ? -1 : header.position(), |
| 878 buffer == null ? -1 : buffer.remaining(), | 855 buffer == null ? -1 : buffer.position(), |
| 879 content == null ? -1 : content.remaining()); | 856 content == null ? -1 : content.remaining()); |
| 880 } | 857 } |
| 881 | 858 |
| 882 | 859 |
| 883 | 860 |
| 928 { | 905 { |
| 929 this._buffers = buffers; | 906 this._buffers = buffers; |
| 930 this._endp = io; | 907 this._endp = io; |
| 931 _header = _buffers.getHeader(); | 908 _header = _buffers.getHeader(); |
| 932 _buffer = _buffers.getBuffer(); | 909 _buffer = _buffers.getBuffer(); |
| 933 _buffer.limit(0); | |
| 934 } | 910 } |
| 935 | 911 |
| 936 public final boolean isOpen() | 912 public final boolean isOpen() |
| 937 { | 913 { |
| 938 return _endp.isOpen(); | 914 return _endp.isOpen(); |
| 946 _last = false; | 922 _last = false; |
| 947 _persistent = null; | 923 _persistent = null; |
| 948 _contentWritten = 0; | 924 _contentWritten = 0; |
| 949 _contentLength = HttpTokens.UNKNOWN_CONTENT; | 925 _contentLength = HttpTokens.UNKNOWN_CONTENT; |
| 950 _content = null; | 926 _content = null; |
| 951 if (_buffer!=null) | 927 _buffer.clear(); |
| 952 _buffer.clearJ(); | |
| 953 } | 928 } |
| 954 | 929 |
| 955 /* ------------------------------------------------------------ */ | 930 /* ------------------------------------------------------------ */ |
| 956 /** | 931 /** |
| 957 * @return Returns the contentBufferSize. | 932 * @return Returns the contentBufferSize. |
| 1050 } | 1025 } |
| 1051 } | 1026 } |
| 1052 | 1027 |
| 1053 public final void completeUncheckedAddContent() | 1028 public final void completeUncheckedAddContent() |
| 1054 { | 1029 { |
| 1055 _contentWritten += _buffer.remaining(); | 1030 _contentWritten += _buffer.position(); |
| 1056 if (_head) | 1031 if (_head) |
| 1057 _buffer.clearJ(); | 1032 _buffer.clear(); |
| 1058 } | 1033 } |
| 1059 | 1034 |
| 1060 private boolean isBufferFull2() | 1035 private boolean isBufferFull2() |
| 1061 { | 1036 { |
| 1062 if (_buffer != null && _buffer.space()==0) | 1037 return !_buffer.hasRemaining() || _content!=null && _content.remaining()>0; |
| 1063 { | |
| 1064 if (_buffer.remaining()==0) | |
| 1065 _buffer.limit(0); | |
| 1066 return _buffer.space()==0; | |
| 1067 } | |
| 1068 | |
| 1069 return _content!=null && _content.remaining()>0; | |
| 1070 } | 1038 } |
| 1071 | 1039 |
| 1072 public final boolean isWritten() | 1040 public final boolean isWritten() |
| 1073 { | 1041 { |
| 1074 return _contentWritten>0; | 1042 return _contentWritten>0; |
| 1097 | 1065 |
| 1098 | 1066 |
| 1099 public final void flush(long maxIdleTime) throws IOException | 1067 public final void flush(long maxIdleTime) throws IOException |
| 1100 { | 1068 { |
| 1101 // block until everything is flushed | 1069 // block until everything is flushed |
| 1102 long now=System.currentTimeMillis(); | 1070 long now = System.currentTimeMillis(); |
| 1103 long end=now+maxIdleTime; | 1071 long end = now+maxIdleTime; |
| 1104 JBuffer content = _content; | 1072 JBuffer content = _content; |
| 1105 JBuffer buffer = _buffer; | 1073 JBuffer buffer = _buffer; |
| 1106 if (content!=null && content.remaining()>0 || buffer!=null && buffer.remaining()>0 || isBufferFull()) | 1074 if (content!=null && content.remaining()>0 || buffer.position()>0 || isBufferFull()) |
| 1107 { | 1075 { |
| 1108 flushBuffer(); | 1076 flushBuffer(); |
| 1109 | 1077 |
| 1110 while (now<end && (content!=null && content.remaining()>0 ||buffer!=null && buffer.remaining()>0) && _endp.isOpen()&& !_endp.isOutputShutdown()) | 1078 while (now<end && (content!=null && content.remaining()>0 || buffer.position()>0) && _endp.isOpen()&& !_endp.isOutputShutdown()) |
| 1111 { | 1079 { |
| 1112 blockForOutput(end-now); | 1080 blockForOutput(end-now); |
| 1113 now=System.currentTimeMillis(); | 1081 now = System.currentTimeMillis(); |
| 1114 } | 1082 } |
| 1115 } | 1083 } |
| 1116 } | 1084 } |
| 1117 | 1085 |
| 1118 /* ------------------------------------------------------------ */ | 1086 /* ------------------------------------------------------------ */ |
