1 17 18 package org.apache.coyote.ajp; 19 20 import java.io.ByteArrayInputStream ; 21 import java.io.IOException ; 22 import java.io.InterruptedIOException ; 23 import java.net.InetAddress ; 24 import java.nio.ByteBuffer ; 25 import java.security.cert.CertificateFactory ; 26 import java.security.cert.X509Certificate ; 27 28 import org.apache.coyote.ActionCode; 29 import org.apache.coyote.ActionHook; 30 import org.apache.coyote.Adapter; 31 import org.apache.coyote.InputBuffer; 32 import org.apache.coyote.OutputBuffer; 33 import org.apache.coyote.Request; 34 import org.apache.coyote.RequestInfo; 35 import org.apache.coyote.Response; 36 import org.apache.tomcat.jni.Socket; 37 import org.apache.tomcat.jni.Status; 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.AprEndpoint; 44 import org.apache.tomcat.util.res.StringManager; 45 46 47 58 public class AjpAprProcessor implements ActionHook { 59 60 61 64 protected static org.apache.commons.logging.Log log = 65 org.apache.commons.logging.LogFactory.getLog(AjpAprProcessor.class); 66 67 70 protected static StringManager sm = 71 StringManager.getManager(Constants.Package); 72 73 74 76 77 public AjpAprProcessor(int packetSize, AprEndpoint 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 if (endpoint.getFirstReadTimeout() > 0) { 94 readTimeout = endpoint.getFirstReadTimeout() * 1000; 95 } else { 96 readTimeout = 100 * 1000; 97 } 98 99 inputBuffer = ByteBuffer.allocateDirect(packetSize * 2); 101 inputBuffer.limit(0); 102 outputBuffer = ByteBuffer.allocateDirect(packetSize * 2); 103 104 int foo = HexUtils.DEC[0]; 106 107 HttpMessages.getMessage(200); 109 110 } 111 112 113 115 116 119 protected Adapter adapter = null; 120 121 122 125 protected Request request = null; 126 127 128 131 protected Response response = null; 132 133 134 139 protected AjpMessage requestHeaderMessage = null; 140 141 142 145 protected AjpMessage responseHeaderMessage = null; 146 147 148 151 protected AjpMessage bodyMessage = null; 152 153 154 157 protected MessageBytes bodyBytes = MessageBytes.newInstance(); 158 159 160 163 protected boolean started = false; 164 165 166 169 protected boolean error = false; 170 171 172 175 protected long socket; 176 177 178 181 protected char[] hostNameC = new char[0]; 182 183 184 187 protected AprEndpoint endpoint; 188 189 190 194 protected long readTimeout; 195 196 197 200 protected MessageBytes tmpMB = MessageBytes.newInstance(); 201 202 203 206 protected MessageBytes certificates = MessageBytes.newInstance(); 207 208 209 212 protected boolean endOfStream = false; 213 214 215 218 protected boolean empty = true; 219 220 221 224 protected boolean first = true; 225 226 227 230 protected boolean replay = false; 231 232 233 236 protected boolean finished = false; 237 238 239 242 protected ByteBuffer outputBuffer = null; 243 244 245 248 protected ByteBuffer inputBuffer = null; 249 250 251 254 protected static final ByteBuffer getBodyMessageBuffer; 255 256 257 260 protected static final ByteBuffer pongMessageBuffer; 261 262 263 266 protected static final byte[] endMessageArray; 267 268 271 protected static final ByteBuffer flushMessageBuffer; 272 273 274 276 277 static { 278 279 AjpMessage getBodyMessage = new AjpMessage(16); 281 getBodyMessage.reset(); 282 getBodyMessage.appendByte(Constants.JK_AJP13_GET_BODY_CHUNK); 283 getBodyMessage.appendInt(Constants.MAX_READ_SIZE); 284 getBodyMessage.end(); 285 getBodyMessageBuffer = 286 ByteBuffer.allocateDirect(getBodyMessage.getLen()); 287 getBodyMessageBuffer.put(getBodyMessage.getBuffer(), 0, 288 getBodyMessage.getLen()); 289 290 AjpMessage pongMessage = new AjpMessage(16); 292 pongMessage.reset(); 293 pongMessage.appendByte(Constants.JK_AJP13_CPONG_REPLY); 294 pongMessage.end(); 295 pongMessageBuffer = ByteBuffer.allocateDirect(pongMessage.getLen()); 296 pongMessageBuffer.put(pongMessage.getBuffer(), 0, 297 pongMessage.getLen()); 298 299 AjpMessage endMessage = new AjpMessage(16); 301 endMessage.reset(); 302 endMessage.appendByte(Constants.JK_AJP13_END_RESPONSE); 303 endMessage.appendByte(1); 304 endMessage.end(); 305 endMessageArray = new byte[endMessage.getLen()]; 306 System.arraycopy(endMessage.getBuffer(), 0, endMessageArray, 0, 307 endMessage.getLen()); 308 309 AjpMessage flushMessage = new AjpMessage(16); 311 flushMessage.reset(); 312 flushMessage.appendByte(Constants.JK_AJP13_SEND_BODY_CHUNK); 313 flushMessage.appendInt(0); 314 flushMessage.appendByte(0); 315 flushMessage.end(); 316 flushMessageBuffer = 317 ByteBuffer.allocateDirect(flushMessage.getLen()); 318 flushMessageBuffer.put(flushMessage.getBuffer(), 0, 319 flushMessage.getLen()); 320 321 } 322 323 324 326 327 330 protected boolean tomcatAuthentication = true; 331 public boolean getTomcatAuthentication() { return tomcatAuthentication; } 332 public void setTomcatAuthentication(boolean tomcatAuthentication) { this.tomcatAuthentication = tomcatAuthentication; } 333 334 335 338 protected String requiredSecret = null; 339 public void setRequiredSecret(String requiredSecret) { this.requiredSecret = requiredSecret; } 340 341 342 344 345 349 public Request getRequest() { 350 return request; 351 } 352 353 354 360 public boolean process(long socket) 361 throws IOException { 362 RequestInfo rp = request.getRequestProcessor(); 363 rp.setStage(org.apache.coyote.Constants.STAGE_PARSE); 364 365 this.socket = socket; 367 Socket.setrbb(this.socket, inputBuffer); 368 Socket.setsbb(this.socket, outputBuffer); 369 370 error = false; 372 373 int limit = 0; 374 if (endpoint.getFirstReadTimeout() > 0) { 375 limit = endpoint.getMaxThreads() / 2; 376 } 377 378 boolean openSocket = true; 379 boolean keptAlive = false; 380 381 while (started && !error) { 382 383 try { 385 if (!readMessage(requestHeaderMessage, true, 387 keptAlive && (endpoint.getCurrentThreadsBusy() > limit))) { 388 rp.setStage(org.apache.coyote.Constants.STAGE_ENDED); 392 break; 393 } 394 int type = requestHeaderMessage.getByte(); 397 if (type == Constants.JK_AJP13_CPING_REQUEST) { 398 if (Socket.sendb(socket, pongMessageBuffer, 0, 399 pongMessageBuffer.position()) < 0) { 400 error = true; 401 } 402 continue; 403 } else if(type != Constants.JK_AJP13_FORWARD_REQUEST) { 404 if(log.isDebugEnabled()) { 406 log.debug("Unexpected message: "+type); 407 } 408 continue; 409 } 410 411 keptAlive = true; 412 request.setStartTime(System.currentTimeMillis()); 413 } catch (IOException e) { 414 error = true; 415 break; 416 } catch (Throwable t) { 417 log.debug(sm.getString("ajpprocessor.header.error"), t); 418 response.setStatus(400); 420 error = true; 421 } 422 423 rp.setStage(org.apache.coyote.Constants.STAGE_PREPARE); 425 try { 426 prepareRequest(); 427 } catch (Throwable t) { 428 log.debug(sm.getString("ajpprocessor.request.prepare"), t); 429 response.setStatus(400); 431 error = true; 432 } 433 434 if (!error) { 436 try { 437 rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE); 438 adapter.service(request, response); 439 } catch (InterruptedIOException e) { 440 error = true; 441 } catch (Throwable t) { 442 log.error(sm.getString("ajpprocessor.request.process"), t); 443 response.setStatus(500); 445 error = true; 446 } 447 } 448 449 if (!finished) { 451 try { 452 finish(); 453 } catch (Throwable t) { 454 error = true; 455 } 456 } 457 458 if (error) { 461 response.setStatus(500); 462 } 463 request.updateCounters(); 464 465 rp.setStage(org.apache.coyote.Constants.STAGE_KEEPALIVE); 466 recycle(); 467 468 } 469 470 if (!error) { 472 endpoint.getPoller().add(socket); 473 } else { 474 openSocket = false; 475 } 476 477 rp.setStage(org.apache.coyote.Constants.STAGE_ENDED); 478 recycle(); 479 480 return openSocket; 481 482 } 483 484 485 487 488 494 public void action(ActionCode actionCode, Object param) { 495 496 if (actionCode == ActionCode.ACTION_COMMIT) { 497 498 if (response.isCommitted()) 499 return; 500 501 try { 503 prepareResponse(); 504 } catch (IOException e) { 505 error = true; 507 } 508 509 } else if (actionCode == ActionCode.ACTION_CLIENT_FLUSH) { 510 511 if (!response.isCommitted()) { 512 try { 514 prepareResponse(); 515 } catch (IOException e) { 516 error = true; 518 return; 519 } 520 } 521 522 try { 523 flush(); 524 if (Socket.sendb(socket, flushMessageBuffer, 0, 526 flushMessageBuffer.position()) < 0) { 527 error = true; 528 } 529 } catch (IOException e) { 530 error = true; 532 } 533 534 } else if (actionCode == ActionCode.ACTION_CLOSE) { 535 537 540 try { 541 finish(); 542 } catch (IOException e) { 543 error = true; 545 } 546 547 } else if (actionCode == ActionCode.ACTION_START) { 548 549 started = true; 550 551 } else if (actionCode == ActionCode.ACTION_STOP) { 552 553 started = false; 554 555 } else if (actionCode == ActionCode.ACTION_REQ_SSL_ATTRIBUTE ) { 556 557 if (!certificates.isNull()) { 558 ByteChunk certData = certificates.getByteChunk(); 559 X509Certificate jsseCerts[] = null; 560 ByteArrayInputStream bais = 561 new ByteArrayInputStream (certData.getBytes(), 562 certData.getStart(), 563 certData.getLength()); 564 try { 566 CertificateFactory cf = 567 CertificateFactory.getInstance("X.509"); 568 X509Certificate cert = (X509Certificate ) 569 cf.generateCertificate(bais); 570 jsseCerts = new X509Certificate [1]; 571 jsseCerts[0] = cert; 572 request.setAttribute(AprEndpoint.CERTIFICATE_KEY, jsseCerts); 573 } catch (java.security.cert.CertificateException e) { 574 log.error(sm.getString("ajpprocessor.certs.fail"), e); 575 return; 576 } 577 } 578 579 } else if (actionCode == ActionCode.ACTION_REQ_HOST_ATTRIBUTE) { 580 581 if (request.remoteHost().isNull()) { 583 try { 584 request.remoteHost().setString(InetAddress.getByName 585 (request.remoteAddr().toString()).getHostName()); 586 } catch (IOException iex) { 587 } 589 } 590 591 } else if (actionCode == ActionCode.ACTION_REQ_LOCAL_ADDR_ATTRIBUTE) { 592 593 request.localAddr().setString(request.localName().toString()); 595 596 } else if (actionCode == ActionCode.ACTION_REQ_SET_BODY_REPLAY) { 597 598 ByteChunk bc = (ByteChunk) param; 600 bodyBytes.setBytes(bc.getBytes(), bc.getStart(), bc.getLength()); 601 request.setContentLength(bc.getLength()); 602 first = false; 603 empty = false; 604 replay = true; 605 606 } 607 608 609 } 610 611 612 614 615 620 public void setAdapter(Adapter adapter) { 621 this.adapter = adapter; 622 } 623 624 625 630 public Adapter getAdapter() { 631 return adapter; 632 } 633 634 635 637 638 641 protected void prepareRequest() { 642 643 byte methodCode = requestHeaderMessage.getByte(); 645 if (methodCode != Constants.SC_M_JK_STORED) { 646 String methodName = Constants.methodTransArray[(int)methodCode - 1]; 647 request.method().setString(methodName); 648 } 649 650 requestHeaderMessage.getBytes(request.protocol()); 651 requestHeaderMessage.getBytes(request.requestURI()); 652 653 requestHeaderMessage.getBytes(request.remoteAddr()); 654 requestHeaderMessage.getBytes(request.remoteHost()); 655 requestHeaderMessage.getBytes(request.localName()); 656 request.setLocalPort(requestHeaderMessage.getInt()); 657 658 boolean isSSL = requestHeaderMessage.getByte() != 0; 659 if (isSSL) { 660 request.scheme().setString("https"); 661 } 662 663 MimeHeaders headers = request.getMimeHeaders(); 665 666 int hCount = requestHeaderMessage.getInt(); 667 for(int i = 0 ; i < hCount ; i++) { 668 String hName = null; 669 670 int isc = requestHeaderMessage.peekInt(); 674 int hId = isc & 0xFF; 675 676 MessageBytes vMB = null; 677 isc &= 0xFF00; 678 if(0xA000 == isc) { 679 requestHeaderMessage.getInt(); hName = Constants.headerTransArray[hId - 1]; 681 vMB = headers.addValue(hName); 682 } else { 683 hId = -1; 690 requestHeaderMessage.getBytes(tmpMB); 691 ByteChunk bc = tmpMB.getByteChunk(); 692 vMB = headers.addValue(bc.getBuffer(), 693 bc.getStart(), bc.getLength()); 694 } 695 696 requestHeaderMessage.getBytes(vMB); 697 698 if (hId == Constants.SC_REQ_CONTENT_LENGTH || 699 (hId == -1 && tmpMB.equalsIgnoreCase("Content-Length"))) { 700 request.setContentLength( vMB.getInt() ); 702 } else if (hId == Constants.SC_REQ_CONTENT_TYPE || 703 (hId == -1 && tmpMB.equalsIgnoreCase("Content-Type"))) { 704 ByteChunk bchunk = vMB.getByteChunk(); 706 request.contentType().setBytes(bchunk.getBytes(), 707 bchunk.getOffset(), 708 bchunk.getLength()); 709 } 710 } 711 712 boolean secret = false; 714 byte attributeCode; 715 while ((attributeCode = requestHeaderMessage.getByte()) 716 != Constants.SC_A_ARE_DONE) { 717 718 switch (attributeCode) { 719 720 case Constants.SC_A_REQ_ATTRIBUTE : 721 requestHeaderMessage.getBytes(tmpMB); 722 String n = tmpMB.toString(); 723 requestHeaderMessage.getBytes(tmpMB); 724 String v = tmpMB.toString(); 725 request.setAttribute(n, v); 726 break; 727 728 case Constants.SC_A_CONTEXT : 729 requestHeaderMessage.getBytes(tmpMB); 730 break; 732 733 case Constants.SC_A_SERVLET_PATH : 734 requestHeaderMessage.getBytes(tmpMB); 735 break; 737 738 case Constants.SC_A_REMOTE_USER : 739 if (tomcatAuthentication) { 740 requestHeaderMessage.getBytes(tmpMB); 742 } else { 743 requestHeaderMessage.getBytes(request.getRemoteUser()); 744 } 745 break; 746 747 case Constants.SC_A_AUTH_TYPE : 748 if (tomcatAuthentication) { 749 requestHeaderMessage.getBytes(tmpMB); 751 } else { 752 requestHeaderMessage.getBytes(request.getAuthType()); 753 } 754 break; 755 756 case Constants.SC_A_QUERY_STRING : 757 requestHeaderMessage.getBytes(request.queryString()); 758 break; 759 760 case Constants.SC_A_JVM_ROUTE : 761 requestHeaderMessage.getBytes(request.instanceId()); 762 break; 763 764 case Constants.SC_A_SSL_CERT : 765 request.scheme().setString("https"); 766 requestHeaderMessage.getBytes(certificates); 768 break; 769 770 case Constants.SC_A_SSL_CIPHER : 771 request.scheme().setString("https"); 772 requestHeaderMessage.getBytes(tmpMB); 773 request.setAttribute(AprEndpoint.CIPHER_SUITE_KEY, 774 tmpMB.toString()); 775 break; 776 777 case Constants.SC_A_SSL_SESSION : 778 request.scheme().setString("https"); 779 requestHeaderMessage.getBytes(tmpMB); 780 request.setAttribute(AprEndpoint.SESSION_ID_KEY, 781 tmpMB.toString()); 782 break; 783 784 case Constants.SC_A_SSL_KEY_SIZE : 785 request.setAttribute(AprEndpoint.KEY_SIZE_KEY, 786 new Integer (requestHeaderMessage.getInt())); 787 break; 788 789 case Constants.SC_A_STORED_METHOD: 790 requestHeaderMessage.getBytes(request.method()); 791 break; 792 793 case Constants.SC_A_SECRET: 794 requestHeaderMessage.getBytes(tmpMB); 795 if (requiredSecret != null) { 796 secret = true; 797 if (!tmpMB.equals(requiredSecret)) { 798 response.setStatus(403); 799 error = true; 800 } 801 } 802 break; 803 804 default: 805 break; 807 808 } 809 810 } 811 812 if ((requiredSecret != null) && !secret) { 814 response.setStatus(403); 815 error = true; 816 } 817 818 ByteChunk uriBC = request.requestURI().getByteChunk(); 820 if (uriBC.startsWithIgnoreCase("http", 0)) { 821 822 int pos = uriBC.indexOf("://", 0, 3, 4); 823 int uriBCStart = uriBC.getStart(); 824 int slashPos = -1; 825 if (pos != -1) { 826 byte[] uriB = uriBC.getBytes(); 827 slashPos = uriBC.indexOf('/', pos + 3); 828 if (slashPos == -1) { 829 slashPos = uriBC.getLength(); 830 request.requestURI().setBytes 832 (uriB, uriBCStart + pos + 1, 1); 833 } else { 834 request.requestURI().setBytes 835 (uriB, uriBCStart + slashPos, 836 uriBC.getLength() - slashPos); 837 } 838 MessageBytes hostMB = headers.setValue("host"); 839 hostMB.setBytes(uriB, uriBCStart + pos + 3, 840 slashPos - pos - 3); 841 } 842 843 } 844 845 MessageBytes valueMB = request.getMimeHeaders().getValue("host"); 846 parseHost(valueMB); 847 848 } 849 850 851 854 public void parseHost(MessageBytes valueMB) { 855 856 if (valueMB == null || (valueMB != null && valueMB.isNull()) ) { 857 request.setServerPort(endpoint.getPort()); 861 return; 862 } 863 864 ByteChunk valueBC = valueMB.getByteChunk(); 865 byte[] valueB = valueBC.getBytes(); 866 int valueL = valueBC.getLength(); 867 int valueS = valueBC.getStart(); 868 int colonPos = -1; 869 if (hostNameC.length < valueL) { 870 hostNameC = new char[valueL]; 871 } 872 873 boolean ipv6 = (valueB[valueS] == '['); 874 boolean bracketClosed = false; 875 for (int i = 0; i < valueL; i++) { 876 char b = (char) valueB[i + valueS]; 877 hostNameC[i] = b; 878 if (b == ']') { 879 bracketClosed = true; 880 } else if (b == ':') { 881 if (!ipv6 || bracketClosed) { 882 colonPos = i; 883 break; 884 } 885 } 886 } 887 888 if (colonPos < 0) { 889 if (request.scheme().equalsIgnoreCase("https")) { 890 request.setServerPort(443); 892 } else { 893 request.setServerPort(80); 895 } 896 request.serverName().setChars(hostNameC, 0, valueL); 897 } else { 898 899 request.serverName().setChars(hostNameC, 0, colonPos); 900 901 int port = 0; 902 int mult = 1; 903 for (int i = valueL - 1; i > colonPos; i--) { 904 int charValue = HexUtils.DEC[(int) valueB[i + valueS]]; 905 if (charValue == -1) { 906 error = true; 908 response.setStatus(400); 910 break; 911 } 912 port = port + (charValue * mult); 913 mult = 10 * mult; 914 } 915 request.setServerPort(port); 916 917 } 918 919 } 920 921 922 926 protected void prepareResponse() 927 throws IOException { 928 929 response.setCommitted(true); 930 931 responseHeaderMessage.reset(); 932 responseHeaderMessage.appendByte(Constants.JK_AJP13_SEND_HEADERS); 933 934 responseHeaderMessage.appendInt(response.getStatus()); 936 String message = response.getMessage(); 937 if (message == null){ 938 message = HttpMessages.getMessage(response.getStatus()); 939 } else { 940 message = message.replace('\n', ' ').replace('\r', ' '); 941 } 942 tmpMB.setString(message); 943 responseHeaderMessage.appendBytes(tmpMB); 944 945 MimeHeaders headers = response.getMimeHeaders(); 947 String contentType = response.getContentType(); 948 if (contentType != null) { 949 headers.setValue("Content-Type").setString(contentType); 950 } 951 String contentLanguage = response.getContentLanguage(); 952 if (contentLanguage != null) { 953 headers.setValue("Content-Language").setString(contentLanguage); 954 } 955 int contentLength = response.getContentLength(); 956 if (contentLength >= 0) { 957 headers.setValue("Content-Length").setInt(contentLength); 958 } 959 960 int numHeaders = headers.size(); 962 responseHeaderMessage.appendInt(numHeaders); 963 for (int i = 0; i < numHeaders; i++) { 964 MessageBytes hN = headers.getName(i); 965 responseHeaderMessage.appendBytes(hN); 966 MessageBytes hV=headers.getValue(i); 967 responseHeaderMessage.appendBytes(hV); 968 } 969 970 responseHeaderMessage.end(); 972 outputBuffer.put(responseHeaderMessage.getBuffer(), 0, responseHeaderMessage.getLen()); 973 974 } 975 976 977 980 protected void finish() 981 throws IOException { 982 983 if (!response.isCommitted()) { 984 try { 986 prepareResponse(); 987 } catch (IOException e) { 988 error = true; 990 } 991 } 992 993 if (finished) 994 return; 995 996 finished = true; 997 998 if (outputBuffer.position() + endMessageArray.length > outputBuffer.capacity()) { 1000 flush(); 1001 } 1002 outputBuffer.put(endMessageArray); 1003 flush(); 1004 1005 } 1006 1007 1008 1012 protected boolean read(int n) 1013 throws IOException { 1014 1015 if (inputBuffer.capacity() - inputBuffer.limit() <= 1016 n - inputBuffer.remaining()) { 1017 inputBuffer.compact(); 1018 inputBuffer.limit(inputBuffer.position()); 1019 inputBuffer.position(0); 1020 } 1021 while (inputBuffer.remaining() < n) { 1022 int nRead = Socket.recvbb 1023 (socket, inputBuffer.limit(), 1024 inputBuffer.capacity() - inputBuffer.limit()); 1025 if (nRead > 0) { 1026 inputBuffer.limit(inputBuffer.limit() + nRead); 1027 } else { 1028 throw new IOException (sm.getString("ajpprotocol.failedread")); 1029 } 1030 } 1031 1032 return true; 1033 1034 } 1035 1036 1037 1041 protected boolean readt(int n, boolean useAvailableData) 1042 throws IOException { 1043 1044 if (useAvailableData && inputBuffer.remaining() == 0) { 1045 return false; 1046 } 1047 if (inputBuffer.capacity() - inputBuffer.limit() <= 1048 n - inputBuffer.remaining()) { 1049 inputBuffer.compact(); 1050 inputBuffer.limit(inputBuffer.position()); 1051 inputBuffer.position(0); 1052 } 1053 while (inputBuffer.remaining() < n) { 1054 int nRead = Socket.recvbbt 1055 (socket, inputBuffer.limit(), 1056 inputBuffer.capacity() - inputBuffer.limit(), readTimeout); 1057 if (nRead > 0) { 1058 inputBuffer.limit(inputBuffer.limit() + nRead); 1059 } else { 1060 if ((-nRead) == Status.ETIMEDOUT || (-nRead) == Status.TIMEUP) { 1061 return false; 1062 } else { 1063 throw new IOException (sm.getString("ajpprotocol.failedread")); 1064 } 1065 } 1066 } 1067 1068 return true; 1069 1070 } 1071 1072 1073 1077 public boolean receive() throws IOException { 1078 1079 first = false; 1080 bodyMessage.reset(); 1081 readMessage(bodyMessage, false, false); 1082 1083 if (bodyMessage.getLen() == 0) { 1085 return false; 1088 } 1089 int blen = bodyMessage.peekInt(); 1090 if (blen == 0) { 1091 return false; 1092 } 1093 1094 bodyMessage.getBytes(bodyBytes); 1095 empty = false; 1096 return true; 1097 } 1098 1099 1105 private boolean refillReadBuffer() throws IOException { 1106 if (replay) { 1110 endOfStream = true; } 1112 if (endOfStream) { 1113 return false; 1114 } 1115 1116 Socket.sendb(socket, getBodyMessageBuffer, 0, 1118 getBodyMessageBuffer.position()); 1119 1120 boolean moreData = receive(); 1121 if( !moreData ) { 1122 endOfStream = true; 1123 } 1124 return moreData; 1125 } 1126 1127 1128 1137 protected boolean readMessage(AjpMessage message, boolean first, 1138 boolean useAvailableData) 1139 throws IOException { 1140 1141 byte[] buf = message.getBuffer(); 1142 int headerLength = message.getHeaderLength(); 1143 1144 if (first) { 1145 if (!readt(headerLength, useAvailableData)) { 1146 return false; 1147 } 1148 } else { 1149 read(headerLength); 1150 } 1151 inputBuffer.get(message.getBuffer(), 0, headerLength); 1152 message.processHeader(); 1153 read(message.getLen()); 1154 inputBuffer.get(message.getBuffer(), headerLength, message.getLen()); 1155 1156 return true; 1157 1158 } 1159 1160 1161 1164 public void recycle() { 1165 1166 first = true; 1168 endOfStream = false; 1169 empty = true; 1170 replay = false; 1171 finished = false; 1172 request.recycle(); 1173 response.recycle(); 1174 certificates.recycle(); 1175 1176 inputBuffer.clear(); 1177 inputBuffer.limit(0); 1178 outputBuffer.clear(); 1179 1180 } 1181 1182 1183 1186 protected void flush() 1187 throws IOException { 1188 if (outputBuffer.position() > 0) { 1189 if (Socket.sendbb(socket, 0, outputBuffer.position()) < 0) { 1190 throw new IOException (); 1191 } 1192 outputBuffer.clear(); 1193 } 1194 } 1195 1196 1197 1199 1200 1204 protected class SocketInputBuffer 1205 implements InputBuffer { 1206 1207 1208 1211 public int doRead(ByteChunk chunk, Request req ) 1212 throws IOException { 1213 1214 if (endOfStream) { 1215 return -1; 1216 } 1217 if (first && req.getContentLength() > 0) { 1218 if (!receive()) { 1220 return 0; 1221 } 1222 } else if (empty) { 1223 if (!refillReadBuffer()) { 1224 return -1; 1225 } 1226 } 1227 ByteChunk bc = bodyBytes.getByteChunk(); 1228 chunk.setBytes(bc.getBuffer(), bc.getStart(), bc.getLength()); 1229 empty = true; 1230 return chunk.getLength(); 1231 1232 } 1233 1234 } 1235 1236 1237 1239 1240 1244 protected class SocketOutputBuffer 1245 implements OutputBuffer { 1246 1247 1248 1251 public int doWrite(ByteChunk chunk, Response res) 1252 throws IOException { 1253 1254 if (!response.isCommitted()) { 1255 try { 1257 prepareResponse(); 1258 } catch (IOException e) { 1259 error = true; 1261 } 1262 } 1263 1264 int len = chunk.getLength(); 1265 int chunkSize = Constants.MAX_SEND_SIZE; 1267 int off = 0; 1268 while (len > 0) { 1269 int thisTime = len; 1270 if (thisTime > chunkSize) { 1271 thisTime = chunkSize; 1272 } 1273 len -= thisTime; 1274 if (outputBuffer.position() + thisTime + 1275 Constants.H_SIZE + 4 > outputBuffer.capacity()) { 1276 flush(); 1277 } 1278 outputBuffer.put((byte) 0x41); 1279 outputBuffer.put((byte) 0x42); 1280 outputBuffer.putShort((short) (thisTime + 4)); 1281 outputBuffer.put(Constants.JK_AJP13_SEND_BODY_CHUNK); 1282 outputBuffer.putShort((short) thisTime); 1283 outputBuffer.put(chunk.getBytes(), chunk.getOffset() + off, thisTime); 1284 outputBuffer.put((byte) 0x00); 1285 off += thisTime; 1286 } 1287 1288 return chunk.getLength(); 1289 1290 } 1291 1292 1293 } 1294 1295 1296} 1297 | Popular Tags |