1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.eclipse.jetty.ajp;
15
16 import java.io.IOException;
17 import java.io.UnsupportedEncodingException;
18 import java.util.HashMap;
19
20 import org.eclipse.jetty.http.AbstractGenerator;
21 import org.eclipse.jetty.http.HttpFields;
22 import org.eclipse.jetty.http.HttpGenerator;
23 import org.eclipse.jetty.http.HttpTokens;
24 import org.eclipse.jetty.http.HttpVersions;
25 import org.eclipse.jetty.io.Buffer;
26 import org.eclipse.jetty.io.Buffers;
27 import org.eclipse.jetty.io.ByteArrayBuffer;
28 import org.eclipse.jetty.io.EndPoint;
29 import org.eclipse.jetty.io.EofException;
30 import org.eclipse.jetty.util.StringUtil;
31 import org.eclipse.jetty.util.log.Log;
32 import org.eclipse.jetty.util.log.Logger;
33
34
35
36
37
38 public class Ajp13Generator extends AbstractGenerator
39 {
40 private static final Logger LOG = Log.getLogger(Ajp13Generator.class);
41
42 private static HashMap __headerHash = new HashMap();
43
44 static
45 {
46 byte[] xA001 =
47 { (byte) 0xA0, (byte) 0x01 };
48 byte[] xA002 =
49 { (byte) 0xA0, (byte) 0x02 };
50 byte[] xA003 =
51 { (byte) 0xA0, (byte) 0x03 };
52 byte[] xA004 =
53 { (byte) 0xA0, (byte) 0x04 };
54 byte[] xA005 =
55 { (byte) 0xA0, (byte) 0x05 };
56 byte[] xA006 =
57 { (byte) 0xA0, (byte) 0x06 };
58 byte[] xA007 =
59 { (byte) 0xA0, (byte) 0x07 };
60 byte[] xA008 =
61 { (byte) 0xA0, (byte) 0x08 };
62 byte[] xA009 =
63 { (byte) 0xA0, (byte) 0x09 };
64 byte[] xA00A =
65 { (byte) 0xA0, (byte) 0x0A };
66 byte[] xA00B =
67 { (byte) 0xA0, (byte) 0x0B };
68 __headerHash.put("Content-Type", xA001);
69 __headerHash.put("Content-Language", xA002);
70 __headerHash.put("Content-Length", xA003);
71 __headerHash.put("Date", xA004);
72 __headerHash.put("Last-Modified", xA005);
73 __headerHash.put("Location", xA006);
74 __headerHash.put("Set-Cookie", xA007);
75 __headerHash.put("Set-Cookie2", xA008);
76 __headerHash.put("Servlet-Engine", xA009);
77 __headerHash.put("Status", xA00A);
78 __headerHash.put("WWW-Authenticate", xA00B);
79
80 }
81
82
83
84
85 private static final byte[] AJP13_CPONG_RESPONSE =
86 { 'A', 'B', 0, 1, 9};
87
88 private static final byte[] AJP13_END_RESPONSE =
89 { 'A', 'B', 0, 2, 5, 1 };
90
91
92
93
94
95 private static final byte[] AJP13_MORE_CONTENT =
96 { 'A', 'B', 0, 3, 6, 31, -7 };
97
98 private static String SERVER = "Server: Jetty(7.x.x)";
99
100 public static void setServerVersion(String version)
101 {
102 SERVER = "Jetty(" + version + ")";
103 }
104
105
106 private boolean _expectMore = false;
107
108 private boolean _needMore = false;
109
110 private boolean _needEOC = false;
111
112 private boolean _bufferPrepared = false;
113
114
115 public Ajp13Generator(Buffers buffers, EndPoint io)
116 {
117 super(buffers, io);
118 }
119
120
121 @Override
122 public boolean isRequest()
123 {
124 return false;
125 }
126
127
128 @Override
129 public boolean isResponse()
130 {
131 return true;
132 }
133
134 @Override
135 public void reset(boolean returnBuffers)
136 {
137 super.reset(returnBuffers);
138
139 _needEOC = false;
140 _needMore = false;
141 _expectMore = false;
142 _bufferPrepared = false;
143 _last=false;
144
145
146
147 _state = STATE_HEADER;
148
149 _status = 0;
150 _version = HttpVersions.HTTP_1_1_ORDINAL;
151 _reason = null;
152 _method = null;
153 _uri = null;
154
155 _contentWritten = 0;
156 _contentLength = HttpTokens.UNKNOWN_CONTENT;
157 _last = false;
158 _head = false;
159 _noContent = false;
160 _persistent = true;
161
162
163
164 _header = null;
165 _buffer = null;
166 _content = null;
167
168 }
169
170
171 @Override
172 public int getContentBufferSize()
173 {
174 try
175 {
176 initContent();
177 }
178 catch(IOException e)
179 {
180 throw new RuntimeException(e);
181 }
182 return super.getContentBufferSize()-7;
183 }
184
185
186 @Override
187 public void increaseContentBufferSize(int contentBufferSize)
188 {
189
190 }
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207 public void addContent(Buffer content, boolean last) throws IOException
208 {
209 if (_noContent)
210 {
211 content.clear();
212 return;
213 }
214
215 if (content.isImmutable())
216 throw new IllegalArgumentException("immutable");
217
218 if (_last || _state == STATE_END)
219 {
220 LOG.debug("Ignoring extra content {}", content);
221 content.clear();
222 return;
223 }
224 _last = last;
225
226 if(!_endp.isOpen())
227 {
228 _state = STATE_END;
229 return;
230 }
231
232
233 if (_content != null && _content.length() > 0)
234 {
235
236 flushBuffer();
237 if (_content != null && _content.length() > 0)
238 throw new IllegalStateException("FULL");
239 }
240
241 _content = content;
242
243 _contentWritten += content.length();
244
245
246 if (_head)
247 {
248
249 content.clear();
250 _content = null;
251 }
252 else
253 {
254
255 initContent();
256
257 int len = 0;
258 len = _buffer.put(_content);
259
260
261 if (len > 0 && _buffer.space() == 0)
262 {
263 len--;
264 _buffer.setPutIndex(_buffer.putIndex() - 1);
265 }
266
267 _content.skip(len);
268
269 if (_content.length() == 0)
270 _content = null;
271 }
272 }
273
274
275
276
277
278
279
280
281
282
283 public boolean addContent(byte b) throws IOException
284 {
285
286 if (_noContent)
287 return false;
288
289 if (_last || _state == STATE_END)
290 throw new IllegalStateException("Closed");
291
292
293 if(!_endp.isOpen())
294 {
295 _state = STATE_END;
296 return false;
297 }
298
299
300 if (_content != null && _content.length() > 0)
301 {
302 flushBuffer();
303 if (_content != null && _content.length() > 0)
304 throw new IllegalStateException("FULL");
305 }
306
307 _contentWritten++;
308
309
310 if (_head)
311 return false;
312
313
314 initContent();
315
316
317
318 _buffer.put(b);
319
320 return _buffer.space() <= 1;
321 }
322
323
324
325
326
327
328
329
330
331 @Override
332 public int prepareUncheckedAddContent() throws IOException
333 {
334 if (_noContent)
335 return -1;
336
337 if (_last || _state == STATE_END)
338 throw new IllegalStateException("Closed");
339
340
341 if(!_endp.isOpen())
342 {
343 _state = STATE_END;
344 return -1;
345 }
346
347
348 Buffer content = _content;
349 if (content != null && content.length() > 0)
350 {
351 flushBuffer();
352 if (content != null && content.length() > 0)
353 throw new IllegalStateException("FULL");
354 }
355
356
357 initContent();
358
359 _contentWritten -= _buffer.length();
360
361
362 if (_head)
363 return Integer.MAX_VALUE;
364
365 return _buffer.space() - 1;
366 }
367
368
369 @Override
370 public void completeHeader(HttpFields fields, boolean allContentAdded) throws IOException
371 {
372 if (_state != STATE_HEADER)
373 return;
374
375 if (_last && !allContentAdded)
376 throw new IllegalStateException("last?");
377 _last = _last | allContentAdded;
378
379 boolean has_server = false;
380 if (_persistent==null)
381 _persistent=(_version > HttpVersions.HTTP_1_0_ORDINAL);
382
383
384 if (_header == null)
385 _header = _buffers.getHeader();
386
387 Buffer tmpbuf = _buffer;
388 _buffer = _header;
389
390 try
391 {
392
393 _buffer.put((byte) 'A');
394 _buffer.put((byte) 'B');
395 addInt(0);
396 _buffer.put((byte) 0x4);
397 addInt(_status);
398 if (_reason == null)
399 _reason=HttpGenerator.getReasonBuffer(_status);
400 if (_reason == null)
401 _reason = new ByteArrayBuffer(Integer.toString(_status));
402 addBuffer(_reason);
403
404 if (_status == 100 || _status == 204 || _status == 304)
405 {
406 _noContent = true;
407 _content = null;
408 }
409
410
411
412 int field_index = _buffer.putIndex();
413 addInt(0);
414
415 int num_fields = 0;
416
417 if (fields != null)
418 {
419
420 int s=fields.size();
421 for (int f=0;f<s;f++)
422 {
423 HttpFields.Field field = fields.getField(f);
424 if (field==null)
425 continue;
426 num_fields++;
427
428 byte[] codes = (byte[]) __headerHash.get(field.getName());
429 if (codes != null)
430 {
431 _buffer.put(codes);
432 }
433 else
434 {
435 addString(field.getName());
436 }
437 addString(field.getValue());
438 }
439 }
440
441 if (!has_server && _status > 100 && getSendServerVersion())
442 {
443 num_fields++;
444 addString("Server");
445 addString(SERVER);
446 }
447
448
449
450
451 int tmp = _buffer.putIndex();
452 _buffer.setPutIndex(field_index);
453 addInt(num_fields);
454 _buffer.setPutIndex(tmp);
455
456
457
458
459 int payloadSize = _buffer.length() - 4;
460
461
462
463 addInt(2, payloadSize);
464 }
465 finally
466 {
467 _buffer = tmpbuf;
468 }
469
470
471 _state = STATE_CONTENT;
472
473 }
474
475
476
477
478
479
480
481 @Override
482 public void complete() throws IOException
483 {
484 if (_state == STATE_END)
485 return;
486
487 super.complete();
488
489 if (_state < STATE_FLUSHING)
490 {
491 _state = STATE_FLUSHING;
492 _needEOC = true;
493 }
494
495 flushBuffer();
496 }
497
498
499 @Override
500 public long flushBuffer() throws IOException
501 {
502 try
503 {
504 if (_state == STATE_HEADER && !_expectMore)
505 throw new IllegalStateException("State==HEADER");
506 prepareBuffers();
507
508 if (_endp == null)
509 {
510
511
512
513
514
515
516 if (!_expectMore && _needEOC && _buffer != null)
517 {
518 _buffer.put(AJP13_END_RESPONSE);
519 }
520 _needEOC = false;
521 return 0;
522 }
523
524
525
526 int total = 0;
527 long last_len = -1;
528 Flushing: while (true)
529 {
530 int len = -1;
531 int to_flush = ((_header != null && _header.length() > 0) ? 4 : 0) | ((_buffer != null && _buffer.length() > 0) ? 2 : 0);
532
533
534 switch (to_flush)
535 {
536 case 7:
537 throw new IllegalStateException();
538
539
540 case 6:
541 len = _endp.flush(_header, _buffer, null);
542
543 break;
544 case 5:
545 throw new IllegalStateException();
546
547
548 case 4:
549 len = _endp.flush(_header);
550 break;
551 case 3:
552 throw new IllegalStateException();
553
554
555 case 2:
556 len = _endp.flush(_buffer);
557
558 break;
559 case 1:
560 throw new IllegalStateException();
561
562
563 case 0:
564 {
565
566 if (_header != null)
567 _header.clear();
568
569 _bufferPrepared = false;
570
571 if (_buffer != null)
572 {
573 _buffer.clear();
574
575
576
577 _buffer.setPutIndex(7);
578 _buffer.setGetIndex(7);
579
580
581
582
583
584 if (_content != null && _content.length() < _buffer.space() && _state != STATE_FLUSHING)
585 {
586
587 _buffer.put(_content);
588 _content.clear();
589 _content = null;
590 break Flushing;
591 }
592
593 }
594
595
596
597
598 if (!_expectMore && !_needEOC && (_content == null || _content.length() == 0))
599 {
600 if (_state == STATE_FLUSHING)
601 _state = STATE_END;
602
603
604
605
606
607
608
609 break Flushing;
610 }
611
612
613 prepareBuffers();
614 }
615 }
616
617
618
619 if (len <= 0)
620 {
621 if (last_len <= 0)
622 break Flushing;
623 break;
624 }
625 last_len = len;
626 total += len;
627 }
628
629 return total;
630 }
631 catch (IOException e)
632 {
633 LOG.ignore(e);
634 throw (e instanceof EofException) ? e : new EofException(e);
635 }
636
637 }
638
639
640 private void prepareBuffers()
641 {
642 if (!_bufferPrepared)
643 {
644
645
646 if (_content != null && _content.length() > 0 && _buffer != null && _buffer.space() > 0)
647 {
648
649 int len = _buffer.put(_content);
650
651
652 if (len > 0 && _buffer.space() == 0)
653 {
654 len--;
655 _buffer.setPutIndex(_buffer.putIndex() - 1);
656 }
657 _content.skip(len);
658
659 if (_content.length() == 0)
660 _content = null;
661
662 if (_buffer.length() == 0)
663 {
664 _content = null;
665 }
666 }
667
668
669 if (_buffer != null)
670 {
671
672 int payloadSize = _buffer.length();
673
674
675
676
677
678
679 if (payloadSize > 0)
680 {
681 _bufferPrepared = true;
682
683 _buffer.put((byte) 0);
684 int put = _buffer.putIndex();
685 _buffer.setGetIndex(0);
686 _buffer.setPutIndex(0);
687 _buffer.put((byte) 'A');
688 _buffer.put((byte) 'B');
689 addInt(payloadSize + 4);
690 _buffer.put((byte) 3);
691 addInt(payloadSize);
692 _buffer.setPutIndex(put);
693 }
694 }
695
696 if (_needMore)
697 {
698
699 if (_header == null)
700 {
701 _header = _buffers.getHeader();
702 }
703
704 if (_buffer == null && _header != null && _header.space() >= AJP13_MORE_CONTENT.length)
705 {
706 _header.put(AJP13_MORE_CONTENT);
707 _needMore = false;
708 }
709 else if (_buffer != null && _buffer.space() >= AJP13_MORE_CONTENT.length)
710 {
711
712
713 _buffer.put(AJP13_MORE_CONTENT);
714 _needMore = false;
715 _bufferPrepared = true;
716 }
717
718 }
719
720 if (!_expectMore && _needEOC)
721 {
722 if (_buffer == null && _header.space() >= AJP13_END_RESPONSE.length)
723 {
724
725 _header.put(AJP13_END_RESPONSE);
726 _needEOC = false;
727 }
728 else if (_buffer != null && _buffer.space() >= AJP13_END_RESPONSE.length)
729 {
730
731
732
733 _buffer.put(AJP13_END_RESPONSE);
734 _needEOC = false;
735 _bufferPrepared = true;
736 }
737 }
738 }
739 }
740
741
742 @Override
743 public boolean isComplete()
744 {
745 return !_expectMore && _state == STATE_END;
746 }
747
748
749 private void initContent() throws IOException
750 {
751 if (_buffer == null)
752 {
753 _buffer = _buffers.getBuffer();
754 _buffer.setPutIndex(7);
755 _buffer.setGetIndex(7);
756 }
757 }
758
759
760 private void addInt(int i)
761 {
762 _buffer.put((byte) ((i >> 8) & 0xFF));
763 _buffer.put((byte) (i & 0xFF));
764 }
765
766
767 private void addInt(int startIndex, int i)
768 {
769 _buffer.poke(startIndex, (byte) ((i >> 8) & 0xFF));
770 _buffer.poke((startIndex + 1), (byte) (i & 0xFF));
771 }
772
773
774 private void addString(String str) throws UnsupportedEncodingException
775 {
776 if (str == null)
777 {
778 addInt(0xFFFF);
779 return;
780 }
781
782
783
784 byte[] b = str.getBytes(StringUtil.__ISO_8859_1);
785
786 addInt(b.length);
787
788 _buffer.put(b);
789 _buffer.put((byte) 0);
790 }
791
792
793 private void addBuffer(Buffer b)
794 {
795 if (b == null)
796 {
797 addInt(0xFFFF);
798 return;
799 }
800
801 addInt(b.length());
802 _buffer.put(b);
803 _buffer.put((byte) 0);
804 }
805
806
807 public void getBodyChunk() throws IOException
808 {
809 _needMore = true;
810 _expectMore = true;
811 flushBuffer();
812 }
813
814
815 public void gotBody()
816 {
817 _needMore = false;
818 _expectMore = false;
819 }
820
821
822
823 public void sendCPong() throws IOException
824 {
825
826 Buffer buff = _buffers.getBuffer();
827 buff.put(AJP13_CPONG_RESPONSE);
828
829
830 do
831 {
832 _endp.flush(buff);
833 }
834 while(buff.length() >0);
835 _buffers.returnBuffer(buff);
836
837 reset(true);
838
839 }
840
841
842
843 }