1 17 18 package org.apache.coyote.ajp; 19 20 import java.io.ByteArrayInputStream ; 21 import java.io.IOException ; 22 import java.io.InputStream ; 23 import java.io.InterruptedIOException ; 24 import java.io.OutputStream ; 25 import java.net.InetAddress ; 26 import java.net.Socket ; 27 import java.security.cert.CertificateFactory ; 28 import java.security.cert.X509Certificate ; 29 30 import org.apache.coyote.ActionCode; 31 import org.apache.coyote.ActionHook; 32 import org.apache.coyote.Adapter; 33 import org.apache.coyote.InputBuffer; 34 import org.apache.coyote.OutputBuffer; 35 import org.apache.coyote.Request; 36 import org.apache.coyote.RequestInfo; 37 import org.apache.coyote.Response; 38 import org.apache.tomcat.util.buf.ByteChunk; 39 import org.apache.tomcat.util.buf.HexUtils; 40 import org.apache.tomcat.util.buf.MessageBytes; 41 import org.apache.tomcat.util.http.HttpMessages; 42 import org.apache.tomcat.util.http.MimeHeaders; 43 import org.apache.tomcat.util.net.JIoEndpoint; 44 import org.apache.tomcat.util.res.StringManager; 45 46 47 58 public class AjpProcessor implements ActionHook { 59 60 61 64 protected static org.apache.commons.logging.Log log 65 = org.apache.commons.logging.LogFactory.getLog(AjpProcessor.class); 66 67 70 protected static StringManager sm = 71 StringManager.getManager(Constants.Package); 72 73 74 76 77 public AjpProcessor(int packetSize, JIoEndpoint endpoint) { 78 79 this.endpoint = endpoint; 80 81 request = new Request(); 82 request.setInputBuffer(new SocketInputBuffer()); 83 84 response = new Response(); 85 response.setHook(this); 86 response.setOutputBuffer(new SocketOutputBuffer()); 87 request.setResponse(response); 88 89 requestHeaderMessage = new AjpMessage(packetSize); 90 responseHeaderMessage = new AjpMessage(packetSize); 91 bodyMessage = new AjpMessage(packetSize); 92 93 int foo = HexUtils.DEC[0]; 95 96 HttpMessages.getMessage(200); 98 99 } 100 101 102 104 105 108 protected Adapter adapter = null; 109 110 111 114 protected Request request = null; 115 116 117 120 protected Response response = null; 121 122 123 128 protected AjpMessage requestHeaderMessage = null; 129 130 131 134 protected AjpMessage responseHeaderMessage = null; 135 136 137 140 protected AjpMessage bodyMessage = null; 141 142 143 146 protected MessageBytes bodyBytes = MessageBytes.newInstance(); 147 148 149 152 protected boolean started = false; 153 154 155 158 protected boolean error = false; 159 160 161 164 protected Socket socket; 165 166 167 170 protected InputStream input; 171 172 173 176 protected OutputStream output; 177 178 179 182 protected char[] hostNameC = new char[0]; 183 184 185 188 protected JIoEndpoint endpoint; 189 190 191 195 protected long readTimeout; 196 197 198 201 protected MessageBytes tmpMB = MessageBytes.newInstance(); 202 203 204 207 protected MessageBytes certificates = MessageBytes.newInstance(); 208 209 210 213 protected boolean endOfStream = false; 214 215 216 219 protected boolean empty = true; 220 221 222 225 protected boolean first = true; 226 227 228 231 protected boolean replay = false; 232 233 234 237 protected boolean finished = false; 238 239 240 243 protected static final byte[] getBodyMessageArray; 244 245 246 249 protected static final byte[] pongMessageArray; 250 251 252 255 protected static final byte[] endMessageArray; 256 257 260 protected static final byte[] flushMessageArray; 261 262 263 265 266 static { 267 268 270 AjpMessage getBodyMessage = new AjpMessage(16); 271 getBodyMessage.reset(); 272 getBodyMessage.appendByte(Constants.JK_AJP13_GET_BODY_CHUNK); 273 getBodyMessage.appendInt(Constants.MAX_READ_SIZE); 274 getBodyMessage.end(); 275 getBodyMessageArray = new byte[getBodyMessage.getLen()]; 276 System.arraycopy(getBodyMessage.getBuffer(), 0, getBodyMessageArray, 277 0, getBodyMessage.getLen()); 278 279 AjpMessage pongMessage = new AjpMessage(16); 281 pongMessage.reset(); 282 pongMessage.appendByte(Constants.JK_AJP13_CPONG_REPLY); 283 pongMessage.end(); 284 pongMessageArray = new byte[pongMessage.getLen()]; 285 System.arraycopy(pongMessage.getBuffer(), 0, pongMessageArray, 286 0, pongMessage.getLen()); 287 288 AjpMessage endMessage = new AjpMessage(16); 290 endMessage.reset(); 291 endMessage.appendByte(Constants.JK_AJP13_END_RESPONSE); 292 endMessage.appendByte(1); 293 endMessage.end(); 294 endMessageArray = new byte[endMessage.getLen()]; 295 System.arraycopy(endMessage.getBuffer(), 0, endMessageArray, 0, 296 endMessage.getLen()); 297 298 AjpMessage flushMessage = new AjpMessage(16); 300 flushMessage.reset(); 301 flushMessage.appendByte(Constants.JK_AJP13_SEND_BODY_CHUNK); 302 flushMessage.appendInt(0); 303 flushMessage.appendByte(0); 304 flushMessage.end(); 305 flushMessageArray = new byte[flushMessage.getLen()]; 306 System.arraycopy(flushMessage.getBuffer(), 0, flushMessageArray, 0, 307 flushMessage.getLen()); 308 309 } 310 311 312 314 315 318 protected boolean tomcatAuthentication = true; 319 public boolean getTomcatAuthentication() { return tomcatAuthentication; } 320 public void setTomcatAuthentication(boolean tomcatAuthentication) { this.tomcatAuthentication = tomcatAuthentication; } 321 322 323 326 protected String requiredSecret = null; 327 public void setRequiredSecret(String requiredSecret) { this.requiredSecret = requiredSecret; } 328 329 330 332 333 337 public Request getRequest() { 338 return request; 339 } 340 341 342 348 public boolean process(Socket socket) 349 throws IOException { 350 RequestInfo rp = request.getRequestProcessor(); 351 rp.setStage(org.apache.coyote.Constants.STAGE_PARSE); 352 353 this.socket = socket; 355 input = socket.getInputStream(); 356 output = socket.getOutputStream(); 357 358 error = false; 360 361 while (started && !error) { 362 363 try { 365 if (!readMessage(requestHeaderMessage)) { 367 rp.setStage(org.apache.coyote.Constants.STAGE_ENDED); 369 break; 370 } 371 int type = requestHeaderMessage.getByte(); 374 if (type == Constants.JK_AJP13_CPING_REQUEST) { 375 try { 376 output.write(pongMessageArray); 377 } catch (IOException e) { 378 error = true; 379 } 380 continue; 381 } else if(type != Constants.JK_AJP13_FORWARD_REQUEST) { 382 if(log.isDebugEnabled()) { 384 log.debug("Unexpected message: "+type); 385 } 386 continue; 387 } 388 389 request.setStartTime(System.currentTimeMillis()); 390 } catch (IOException e) { 391 error = true; 392 break; 393 } catch (Throwable t) { 394 log.debug(sm.getString("ajpprocessor.header.error"), t); 395 response.setStatus(400); 397 error = true; 398 } 399 400 rp.setStage(org.apache.coyote.Constants.STAGE_PREPARE); 402 try { 403 prepareRequest(); 404 } catch (Throwable t) { 405 log.debug(sm.getString("ajpprocessor.request.prepare"), t); 406 response.setStatus(400); 408 error = true; 409 } 410 411 if (!error) { 413 try { 414 rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE); 415 adapter.service(request, response); 416 } catch (InterruptedIOException e) { 417 error = true; 418 } catch (Throwable t) { 419 log.error(sm.getString("ajpprocessor.request.process"), t); 420 response.setStatus(500); 422 error = true; 423 } 424 } 425 426 if (!finished) { 428 try { 429 finish(); 430 } catch (Throwable t) { 431 error = true; 432 } 433 } 434 435 if (error) { 438 response.setStatus(500); 439 } 440 request.updateCounters(); 441 442 rp.setStage(org.apache.coyote.Constants.STAGE_KEEPALIVE); 443 recycle(); 444 445 } 446 447 rp.setStage(org.apache.coyote.Constants.STAGE_ENDED); 448 recycle(); 449 input = null; 450 output = null; 451 452 return true; 453 454 } 455 456 457 459 460 466 public void action(ActionCode actionCode, Object param) { 467 468 if (actionCode == ActionCode.ACTION_COMMIT) { 469 470 if (response.isCommitted()) 471 return; 472 473 try { 475 prepareResponse(); 476 } catch (IOException e) { 477 error = true; 479 } 480 481 } else if (actionCode == ActionCode.ACTION_CLIENT_FLUSH) { 482 483 if (!response.isCommitted()) { 484 try { 486 prepareResponse(); 487 } catch (IOException e) { 488 error = true; 490 return; 491 } 492 } 493 494 try { 495 flush(); 496 } catch (IOException e) { 497 error = true; 499 } 500 501 } else if (actionCode == ActionCode.ACTION_CLOSE) { 502 504 507 try { 508 finish(); 509 } catch (IOException e) { 510 error = true; 512 } 513 514 } else if (actionCode == ActionCode.ACTION_START) { 515 516 started = true; 517 518 } else if (actionCode == ActionCode.ACTION_STOP) { 519 520 started = false; 521 522 } else if (actionCode == ActionCode.ACTION_REQ_SSL_ATTRIBUTE ) { 523 524 if (!certificates.isNull()) { 525 ByteChunk certData = certificates.getByteChunk(); 526 X509Certificate jsseCerts[] = null; 527 ByteArrayInputStream bais = 528 new ByteArrayInputStream (certData.getBytes(), 529 certData.getStart(), 530 certData.getLength()); 531 try { 533 CertificateFactory cf = 534 CertificateFactory.getInstance("X.509"); 535 X509Certificate cert = (X509Certificate ) 536 cf.generateCertificate(bais); 537 jsseCerts = new X509Certificate [1]; 538 jsseCerts[0] = cert; 539 request.setAttribute(JIoEndpoint.CERTIFICATE_KEY, jsseCerts); 540 } catch (java.security.cert.CertificateException e) { 541 log.error(sm.getString("ajpprocessor.certs.fail"), e); 542 return; 543 } 544 } 545 546 } else if (actionCode == ActionCode.ACTION_REQ_HOST_ATTRIBUTE) { 547 548 if (request.remoteHost().isNull()) { 550 try { 551 request.remoteHost().setString(InetAddress.getByName 552 (request.remoteAddr().toString()).getHostName()); 553 } catch (IOException iex) { 554 } 556 } 557 558 } else if (actionCode == ActionCode.ACTION_REQ_LOCAL_ADDR_ATTRIBUTE) { 559 560 request.localAddr().setString(request.localName().toString()); 562 563 } else if (actionCode == ActionCode.ACTION_REQ_SET_BODY_REPLAY) { 564 565 ByteChunk bc = (ByteChunk) param; 567 bodyBytes.setBytes(bc.getBytes(), bc.getStart(), bc.getLength()); 568 request.setContentLength(bc.getLength()); 569 first = false; 570 empty = false; 571 replay = true; 572 573 } 574 575 576 } 577 578 579 581 582 587 public void setAdapter(Adapter adapter) { 588 this.adapter = adapter; 589 } 590 591 592 597 public Adapter getAdapter() { 598 return adapter; 599 } 600 601 602 604 605 608 protected void prepareRequest() { 609 610 byte methodCode = requestHeaderMessage.getByte(); 612 if (methodCode != Constants.SC_M_JK_STORED) { 613 String methodName = Constants.methodTransArray[(int)methodCode - 1]; 614 request.method().setString(methodName); 615 } 616 617 requestHeaderMessage.getBytes(request.protocol()); 618 requestHeaderMessage.getBytes(request.requestURI()); 619 620 requestHeaderMessage.getBytes(request.remoteAddr()); 621 requestHeaderMessage.getBytes(request.remoteHost()); 622 requestHeaderMessage.getBytes(request.localName()); 623 request.setLocalPort(requestHeaderMessage.getInt()); 624 625 boolean isSSL = requestHeaderMessage.getByte() != 0; 626 if (isSSL) { 627 request.scheme().setString("https"); 628 } 629 630 MimeHeaders headers = request.getMimeHeaders(); 632 633 int hCount = requestHeaderMessage.getInt(); 634 for(int i = 0 ; i < hCount ; i++) { 635 String hName = null; 636 637 int isc = requestHeaderMessage.peekInt(); 641 int hId = isc & 0xFF; 642 643 MessageBytes vMB = null; 644 isc &= 0xFF00; 645 if(0xA000 == isc) { 646 requestHeaderMessage.getInt(); hName = Constants.headerTransArray[hId - 1]; 648 vMB = headers.addValue(hName); 649 } else { 650 hId = -1; 657 requestHeaderMessage.getBytes(tmpMB); 658 ByteChunk bc = tmpMB.getByteChunk(); 659 vMB = headers.addValue(bc.getBuffer(), 660 bc.getStart(), bc.getLength()); 661 } 662 663 requestHeaderMessage.getBytes(vMB); 664 665 if (hId == Constants.SC_REQ_CONTENT_LENGTH || 666 (hId == -1 && tmpMB.equalsIgnoreCase("Content-Length"))) { 667 request.setContentLength( vMB.getInt() ); 669 } else if (hId == Constants.SC_REQ_CONTENT_TYPE || 670 (hId == -1 && tmpMB.equalsIgnoreCase("Content-Type"))) { 671 ByteChunk bchunk = vMB.getByteChunk(); 673 request.contentType().setBytes(bchunk.getBytes(), 674 bchunk.getOffset(), 675 bchunk.getLength()); 676 } 677 } 678 679 boolean secret = false; 681 byte attributeCode; 682 while ((attributeCode = requestHeaderMessage.getByte()) 683 != Constants.SC_A_ARE_DONE) { 684 685 switch (attributeCode) { 686 687 case Constants.SC_A_REQ_ATTRIBUTE : 688 requestHeaderMessage.getBytes(tmpMB); 689 String n = tmpMB.toString(); 690 requestHeaderMessage.getBytes(tmpMB); 691 String v = tmpMB.toString(); 692 request.setAttribute(n, v); 693 break; 694 695 case Constants.SC_A_CONTEXT : 696 requestHeaderMessage.getBytes(tmpMB); 697 break; 699 700 case Constants.SC_A_SERVLET_PATH : 701 requestHeaderMessage.getBytes(tmpMB); 702 break; 704 705 case Constants.SC_A_REMOTE_USER : 706 if (tomcatAuthentication) { 707 requestHeaderMessage.getBytes(tmpMB); 709 } else { 710 requestHeaderMessage.getBytes(request.getRemoteUser()); 711 } 712 break; 713 714 case Constants.SC_A_AUTH_TYPE : 715 if (tomcatAuthentication) { 716 requestHeaderMessage.getBytes(tmpMB); 718 } else { 719 requestHeaderMessage.getBytes(request.getAuthType()); 720 } 721 break; 722 723 case Constants.SC_A_QUERY_STRING : 724 requestHeaderMessage.getBytes(request.queryString()); 725 break; 726 727 case Constants.SC_A_JVM_ROUTE : 728 requestHeaderMessage.getBytes(request.instanceId()); 729 break; 730 731 case Constants.SC_A_SSL_CERT : 732 request.scheme().setString("https"); 733 requestHeaderMessage.getBytes(certificates); 735 break; 736 737 case Constants.SC_A_SSL_CIPHER : 738 request.scheme().setString("https"); 739 requestHeaderMessage.getBytes(tmpMB); 740 request.setAttribute(JIoEndpoint.CIPHER_SUITE_KEY, 741 tmpMB.toString()); 742 break; 743 744 case Constants.SC_A_SSL_SESSION : 745 request.scheme().setString("https"); 746 requestHeaderMessage.getBytes(tmpMB); 747 request.setAttribute(JIoEndpoint.SESSION_ID_KEY, 748 tmpMB.toString()); 749 break; 750 751 case Constants.SC_A_SSL_KEY_SIZE : 752 request.setAttribute(JIoEndpoint.KEY_SIZE_KEY, 753 new Integer (requestHeaderMessage.getInt())); 754 break; 755 756 case Constants.SC_A_STORED_METHOD: 757 requestHeaderMessage.getBytes(request.method()); 758 break; 759 760 case Constants.SC_A_SECRET: 761 requestHeaderMessage.getBytes(tmpMB); 762 if (requiredSecret != null) { 763 secret = true; 764 if (!tmpMB.equals(requiredSecret)) { 765 response.setStatus(403); 766 error = true; 767 } 768 } 769 break; 770 771 default: 772 break; 774 775 } 776 777 } 778 779 if ((requiredSecret != null) && !secret) { 781 response.setStatus(403); 782 error = true; 783 } 784 785 ByteChunk uriBC = request.requestURI().getByteChunk(); 787 if (uriBC.startsWithIgnoreCase("http", 0)) { 788 789 int pos = uriBC.indexOf("://", 0, 3, 4); 790 int uriBCStart = uriBC.getStart(); 791 int slashPos = -1; 792 if (pos != -1) { 793 byte[] uriB = uriBC.getBytes(); 794 slashPos = uriBC.indexOf('/', pos + 3); 795 if (slashPos == -1) { 796 slashPos = uriBC.getLength(); 797 request.requestURI().setBytes 799 (uriB, uriBCStart + pos + 1, 1); 800 } else { 801 request.requestURI().setBytes 802 (uriB, uriBCStart + slashPos, 803 uriBC.getLength() - slashPos); 804 } 805 MessageBytes hostMB = headers.setValue("host"); 806 hostMB.setBytes(uriB, uriBCStart + pos + 3, 807 slashPos - pos - 3); 808 } 809 810 } 811 812 MessageBytes valueMB = request.getMimeHeaders().getValue("host"); 813 parseHost(valueMB); 814 815 } 816 817 818 821 public void parseHost(MessageBytes valueMB) { 822 823 if (valueMB == null || (valueMB != null && valueMB.isNull()) ) { 824 request.setServerPort(endpoint.getPort()); 828 return; 829 } 830 831 ByteChunk valueBC = valueMB.getByteChunk(); 832 byte[] valueB = valueBC.getBytes(); 833 int valueL = valueBC.getLength(); 834 int valueS = valueBC.getStart(); 835 int colonPos = -1; 836 if (hostNameC.length < valueL) { 837 hostNameC = new char[valueL]; 838 } 839 840 boolean ipv6 = (valueB[valueS] == '['); 841 boolean bracketClosed = false; 842 for (int i = 0; i < valueL; i++) { 843 char b = (char) valueB[i + valueS]; 844 hostNameC[i] = b; 845 if (b == ']') { 846 bracketClosed = true; 847 } else if (b == ':') { 848 if (!ipv6 || bracketClosed) { 849 colonPos = i; 850 break; 851 } 852 } 853 } 854 855 if (colonPos < 0) { 856 if (request.scheme().equalsIgnoreCase("https")) { 857 request.setServerPort(443); 859 } else { 860 request.setServerPort(80); 862 } 863 request.serverName().setChars(hostNameC, 0, valueL); 864 } else { 865 866 request.serverName().setChars(hostNameC, 0, colonPos); 867 868 int port = 0; 869 int mult = 1; 870 for (int i = valueL - 1; i > colonPos; i--) { 871 int charValue = HexUtils.DEC[(int) valueB[i + valueS]]; 872 if (charValue == -1) { 873 error = true; 875 response.setStatus(400); 877 break; 878 } 879 port = port + (charValue * mult); 880 mult = 10 * mult; 881 } 882 request.setServerPort(port); 883 884 } 885 886 } 887 888 889 893 protected void prepareResponse() 894 throws IOException { 895 896 response.setCommitted(true); 897 898 responseHeaderMessage.reset(); 899 responseHeaderMessage.appendByte(Constants.JK_AJP13_SEND_HEADERS); 900 901 responseHeaderMessage.appendInt(response.getStatus()); 903 String message = response.getMessage(); 904 if (message == null){ 905 message = HttpMessages.getMessage(response.getStatus()); 906 } else { 907 message = message.replace('\n', ' ').replace('\r', ' '); 908 } 909 tmpMB.setString(message); 910 responseHeaderMessage.appendBytes(tmpMB); 911 912 MimeHeaders headers = response.getMimeHeaders(); 914 String contentType = response.getContentType(); 915 if (contentType != null) { 916 headers.setValue("Content-Type").setString(contentType); 917 } 918 String contentLanguage = response.getContentLanguage(); 919 if (contentLanguage != null) { 920 headers.setValue("Content-Language").setString(contentLanguage); 921 } 922 int contentLength = response.getContentLength(); 923 if (contentLength >= 0) { 924 headers.setValue("Content-Length").setInt(contentLength); 925 } 926 927 int numHeaders = headers.size(); 929 responseHeaderMessage.appendInt(numHeaders); 930 for (int i = 0; i < numHeaders; i++) { 931 MessageBytes hN = headers.getName(i); 932 responseHeaderMessage.appendBytes(hN); 933 MessageBytes hV=headers.getValue(i); 934 responseHeaderMessage.appendBytes(hV); 935 } 936 937 responseHeaderMessage.end(); 939 output.write(responseHeaderMessage.getBuffer(), 0, responseHeaderMessage.getLen()); 940 941 } 942 943 944 947 protected void finish() 948 throws IOException { 949 950 if (!response.isCommitted()) { 951 try { 953 prepareResponse(); 954 } catch (IOException e) { 955 error = true; 957 } 958 } 959 960 if (finished) 961 return; 962 963 finished = true; 964 965 output.write(endMessageArray); 967 968 } 969 970 971 975 protected boolean read(byte[] buf, int pos, int n) 976 throws IOException { 977 978 int read = 0; 979 int res = 0; 980 while (read < n) { 981 res = input.read(buf, read + pos, n - read); 982 if (res > 0) { 983 read += res; 984 } else { 985 throw new IOException (sm.getString("ajpprotocol.failedread")); 986 } 987 } 988 989 return true; 990 991 } 992 993 994 998 public boolean receive() throws IOException { 999 1000 first = false; 1001 bodyMessage.reset(); 1002 readMessage(bodyMessage); 1003 1004 if (bodyMessage.getLen() == 0) { 1006 return false; 1009 } 1010 int blen = bodyMessage.peekInt(); 1011 if (blen == 0) { 1012 return false; 1013 } 1014 1015 bodyMessage.getBytes(bodyBytes); 1016 empty = false; 1017 return true; 1018 } 1019 1020 1026 private boolean refillReadBuffer() throws IOException { 1027 if (replay) { 1031 endOfStream = true; } 1033 if (endOfStream) { 1034 return false; 1035 } 1036 1037 output.write(getBodyMessageArray); 1039 1040 boolean moreData = receive(); 1041 if( !moreData ) { 1042 endOfStream = true; 1043 } 1044 return moreData; 1045 } 1046 1047 1048 1055 protected boolean readMessage(AjpMessage message) 1056 throws IOException { 1057 1058 byte[] buf = message.getBuffer(); 1059 1060 read(buf, 0, message.getHeaderLength()); 1061 1062 message.processHeader(); 1063 read(buf, message.getHeaderLength(), message.getLen()); 1064 1065 return true; 1066 1067 } 1068 1069 1070 1073 public void recycle() { 1074 1075 first = true; 1077 endOfStream = false; 1078 empty = true; 1079 replay = false; 1080 finished = false; 1081 request.recycle(); 1082 response.recycle(); 1083 certificates.recycle(); 1084 1085 } 1086 1087 1088 1091 protected void flush() 1092 throws IOException { 1093 output.write(flushMessageArray); 1095 } 1096 1097 1098 1100 1101 1105 protected class SocketInputBuffer 1106 implements InputBuffer { 1107 1108 1109 1112 public int doRead(ByteChunk chunk, Request req ) 1113 throws IOException { 1114 1115 if (endOfStream) { 1116 return -1; 1117 } 1118 if (first && req.getContentLength() > 0) { 1119 if (!receive()) { 1121 return 0; 1122 } 1123 } else if (empty) { 1124 if (!refillReadBuffer()) { 1125 return -1; 1126 } 1127 } 1128 ByteChunk bc = bodyBytes.getByteChunk(); 1129 chunk.setBytes(bc.getBuffer(), bc.getStart(), bc.getLength()); 1130 empty = true; 1131 return chunk.getLength(); 1132 1133 } 1134 1135 } 1136 1137 1138 1140 1141 1145 protected class SocketOutputBuffer 1146 implements OutputBuffer { 1147 1148 1149 1152 public int doWrite(ByteChunk chunk, Response res) 1153 throws IOException { 1154 1155 if (!response.isCommitted()) { 1156 try { 1158 prepareResponse(); 1159 } catch (IOException e) { 1160 error = true; 1162 } 1163 } 1164 1165 int len = chunk.getLength(); 1166 int chunkSize = Constants.MAX_SEND_SIZE; 1168 int off = 0; 1169 while (len > 0) { 1170 int thisTime = len; 1171 if (thisTime > chunkSize) { 1172 thisTime = chunkSize; 1173 } 1174 len -= thisTime; 1175 responseHeaderMessage.reset(); 1176 responseHeaderMessage.appendByte(Constants.JK_AJP13_SEND_BODY_CHUNK); 1177 responseHeaderMessage.appendBytes(chunk.getBytes(), chunk.getOffset() + off, thisTime); 1178 responseHeaderMessage.end(); 1179 output.write(responseHeaderMessage.getBuffer(), 0, responseHeaderMessage.getLen()); 1180 1181 off += thisTime; 1182 } 1183 1184 return chunk.getLength(); 1185 1186 } 1187 1188 1189 } 1190 1191 1192} 1193 | Popular Tags |