View Javadoc
1   /*
2    * Copyright 2020 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    * https://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  package io.netty.handler.pcap;
17  
18  import io.netty.buffer.ByteBuf;
19  import io.netty.util.internal.logging.InternalLogger;
20  import io.netty.util.internal.logging.InternalLoggerFactory;
21  
22  import java.io.Closeable;
23  import java.io.IOException;
24  import java.io.OutputStream;
25  
26  final class PcapWriter implements Closeable {
27  
28      /**
29       * Logger
30       */
31      private static final InternalLogger logger = InternalLoggerFactory.getInstance(PcapWriter.class);
32  
33      /**
34       * {@link OutputStream} where we'll write Pcap data.
35       */
36      private final OutputStream outputStream;
37  
38      /**
39       * Set to {@code true} if {@link #outputStream} is closed.
40       */
41      private boolean isClosed;
42  
43      /**
44       * This uses {@link OutputStream} for writing Pcap.
45       * Pcap Global Header is not written on construction.
46       */
47      PcapWriter(OutputStream outputStream) {
48          this.outputStream = outputStream;
49      }
50  
51      /**
52       * This uses {@link OutputStream} for writing Pcap.
53       * Pcap Global Header is also written on construction.
54       *
55       * @throws IOException If {@link OutputStream#write(byte[])} throws an exception
56       */
57      PcapWriter(OutputStream outputStream, ByteBuf byteBuf) throws IOException {
58          this.outputStream = outputStream;
59  
60          PcapHeaders.writeGlobalHeader(byteBuf);
61          byteBuf.readBytes(outputStream, byteBuf.readableBytes());
62      }
63  
64      /**
65       * Write Packet in Pcap OutputStream.
66       *
67       * @param packetHeaderBuf Packer Header {@link ByteBuf}
68       * @param packet          Packet
69       * @throws IOException If {@link OutputStream#write(byte[])} throws an exception
70       */
71      void writePacket(ByteBuf packetHeaderBuf, ByteBuf packet) throws IOException {
72          if (isClosed) {
73              logger.debug("Pcap Write attempted on closed PcapWriter");
74          }
75  
76          long timestamp = System.currentTimeMillis();
77  
78          PcapHeaders.writePacketHeader(
79                  packetHeaderBuf,
80                  (int) (timestamp / 1000L),
81                  (int) (timestamp % 1000L * 1000L),
82                  packet.readableBytes(),
83                  packet.readableBytes()
84          );
85  
86          packetHeaderBuf.readBytes(outputStream, packetHeaderBuf.readableBytes());
87          packet.readBytes(outputStream, packet.readableBytes());
88      }
89  
90      @Override
91      public void close() throws IOException {
92          if (isClosed) {
93              logger.debug("PcapWriter is already closed");
94          } else {
95              isClosed = true;
96              outputStream.flush();
97              outputStream.close();
98              logger.debug("PcapWriter is now closed");
99          }
100     }
101 }