PageRenderTime 42ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/nginx-tomcat8/src/java/org/apache/coyote/http11/InternalNginxOutputBuffer.java

https://gitlab.com/nginx-modules/nginx-clojure
Java | 155 lines | 115 code | 27 blank | 13 comment | 14 complexity | 9ac3fb07d5011c7ed670ee949c040830 MD5 | raw file
  1. /**
  2. * Copyright (C) Zhang,Yuexiang (xfeep)
  3. *
  4. *For reuse some classes from tomcat8 we have to use this package
  5. */
  6. package org.apache.coyote.http11;
  7. import java.io.IOException;
  8. import java.nio.ByteBuffer;
  9. import java.nio.channels.Selector;
  10. import nginx.clojure.NginxHttpServerChannel;
  11. import org.apache.coyote.OutputBuffer;
  12. import org.apache.coyote.Response;
  13. import org.apache.coyote.http11.AbstractOutputBuffer;
  14. import org.apache.coyote.http11.Constants;
  15. import org.apache.tomcat.util.buf.ByteChunk;
  16. import org.apache.tomcat.util.net.AbstractEndpoint;
  17. import org.apache.tomcat.util.net.NioEndpoint;
  18. import org.apache.tomcat.util.net.SocketWrapper;
  19. public class InternalNginxOutputBuffer extends AbstractOutputBuffer<NginxChannel> {
  20. protected NginxChannel socket;
  21. protected volatile boolean flipped = false;
  22. protected InternalNginxOutputBuffer(Response response, int headerBufferSize) {
  23. super(response, headerBufferSize);
  24. outputStreamOutputBuffer = new HttpChannelOutputBuffer();
  25. }
  26. @Override
  27. public void init(SocketWrapper<NginxChannel> socketWrapper,
  28. AbstractEndpoint<NginxChannel> endpoint)
  29. throws IOException {
  30. socket = socketWrapper.getSocket();
  31. }
  32. public void addActiveFilter(OutputFilter filter) {
  33. //by default socket.ignoreNginxFilter is true we will use nginx filter instead of tomcat filter
  34. if (socket.ignoreNginxFilter) {
  35. super.addActiveFilter(filter);
  36. }
  37. }
  38. @Override
  39. public void sendAck() throws IOException {
  40. if (!committed) {
  41. socket.getBufHandler().getWriteBuffer().put(
  42. Constants.ACK_BYTES, 0, Constants.ACK_BYTES.length);
  43. int result = writeToSocket(socket.getBufHandler().getWriteBuffer(), true, true);
  44. if (result < 0) {
  45. throw new IOException(sm.getString("iob.failedwrite.ack"));
  46. }
  47. }
  48. }
  49. protected synchronized int writeToSocket(byte[] buf, int pos, int len) throws IOException {
  50. try {
  51. socket.getIOChannel().send(buf, pos, len, true, false);
  52. }catch(RuntimeException e) {
  53. throw new IOException(e.getMessage(), e);
  54. }
  55. return len;
  56. }
  57. protected synchronized int writeToSocket(ByteBuffer bytebuffer, boolean block, boolean flip) throws IOException {
  58. if ( flip ) {
  59. bytebuffer.flip();
  60. flipped = true;
  61. }
  62. int written = bytebuffer.remaining();
  63. NginxEndpoint.KeyAttachment att = (NginxEndpoint.KeyAttachment)socket.getAttachment();
  64. if ( att == null ) throw new IOException("Key must be cancelled");
  65. socket.getIOChannel().send(bytebuffer, true, false);
  66. if ( block || bytebuffer.remaining()==0) {
  67. //blocking writes must empty the buffer
  68. //and if remaining==0 then we did empty it
  69. bytebuffer.clear();
  70. flipped = false;
  71. }
  72. // If there is data left in the buffer the socket will be registered for
  73. // write further up the stack. This is to ensure the socket is only
  74. // registered for write once as both container and user code can trigger
  75. // write registration.
  76. return written;
  77. }
  78. @Override
  79. protected void commit() throws IOException {
  80. // The response is now committed
  81. committed = true;
  82. response.setCommitted(true);
  83. if (pos > 0 && (!socket.isSendFile() || socket.getIOChannel().isIgnoreFilter())) {
  84. socket.getIOChannel().sendHeader(headerBuffer, 0, pos, true, false);
  85. }
  86. }
  87. @Override
  88. public void endRequest() throws IOException {
  89. if (finished) {
  90. return;
  91. }
  92. super.endRequest();
  93. if (!socket.isSendFile() || socket.getIOChannel().isIgnoreFilter()) {
  94. socket.close();
  95. }
  96. }
  97. @Override
  98. protected boolean hasMoreDataToFlush() {
  99. return false;
  100. }
  101. @Override
  102. protected void registerWriteInterest() throws IOException {
  103. }
  104. @Override
  105. protected boolean flushBuffer(boolean block) throws IOException {
  106. try {
  107. socket.getIOChannel().flush();
  108. }catch(RuntimeException e) {
  109. throw new IOException(e.getMessage(), e);
  110. }
  111. return false;
  112. }
  113. protected class HttpChannelOutputBuffer implements OutputBuffer {
  114. public HttpChannelOutputBuffer() {
  115. }
  116. @Override
  117. public long getBytesWritten() {
  118. return byteCount;
  119. }
  120. @Override
  121. public int doWrite(ByteChunk chunk, Response response)
  122. throws IOException {
  123. int c = writeToSocket(chunk.getBuffer(), chunk.getStart(), chunk.getLength());
  124. byteCount += c;
  125. return c;
  126. }
  127. }
  128. }