Add DCC receiver.
[xudocci.git] / src / main / java / net / pterodactylus / irc / DccReceiver.java
1 /*
2  * XdccDownloader - DccReceiver.java - Copyright © 2013 David Roden
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 package net.pterodactylus.irc;
19
20 import java.io.IOException;
21 import java.io.InputStream;
22 import java.io.OutputStream;
23 import java.net.InetAddress;
24 import java.net.Socket;
25 import java.util.logging.Level;
26 import java.util.logging.Logger;
27
28 import net.pterodactylus.irc.event.DccSendReceived;
29
30 import com.google.common.util.concurrent.AbstractExecutionThreadService;
31
32 /**
33  * Service that receives a file offered by a {@link DccSendReceived}.
34  *
35  * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
36  */
37 public class DccReceiver extends AbstractExecutionThreadService {
38
39         /** The logger. */
40         private static final Logger logger = Logger.getLogger(DccReceiver.class.getName());
41
42         /** The address to connect to. */
43         private final InetAddress inetAddress;
44
45         /** The port number to connect to. */
46         private final int port;
47
48         /** The name of the file being offered. */
49         private final String filename;
50
51         /** The size of the file being offered. */
52         private final long size;
53
54         /** The output stream to write the file to. */
55         private final OutputStream outputStream;
56
57         /** The number of bytes already written. */
58         private long progress;
59
60         /**
61          * Creates a new DCC receiver.
62          *
63          * @param inetAddress
64          *              The address to connect to
65          * @param port
66          *              The port number to connect to
67          * @param filename
68          *              The name of the file being downloaded
69          * @param size
70          *              The size of the file being downloaded, or {@code -1} if the size is not
71          *              known
72          * @param outputStream
73          *              The output stream to write the file to
74          */
75         public DccReceiver(InetAddress inetAddress, int port, String filename, long size, OutputStream outputStream) {
76                 this.inetAddress = inetAddress;
77                 this.port = port;
78                 this.filename = filename;
79                 this.size = size;
80                 this.outputStream = outputStream;
81         }
82
83         //
84         // ACCESSORS
85         //
86
87         /**
88          * Returns the name of the file being downloaded. The name is not used by the
89          * DCC receiver, it only serves as a kind of identifier.
90          *
91          * @return The name of the file being downloaded
92          */
93         public String filename() {
94                 return filename;
95         }
96
97         /**
98          * Returns the size of the file being downloaded. If the size of the file is
99          * not known, {@code -1} is returned.
100          *
101          * @return The size of the file being downloaded, or {@code -1} if the size is
102          *         not known
103          */
104         public long size() {
105                 return size;
106         }
107
108         /**
109          * Returns the number of bytes that have already been downloaded.
110          *
111          * @return The number of bytes that have already been downloaded
112          */
113         public long progress() {
114                 return progress;
115         }
116
117         //
118         // ABSTRACTEXECUTIONTHREADSERVICE METHODS
119         //
120
121         @Override
122         protected void run() throws Exception {
123                 Socket socket = null;
124                 try {
125                         socket = new Socket(inetAddress, port);
126                         InputStream socketInputStream = socket.getInputStream();
127                         byte[] buffer = new byte[65536];
128                         while (true) {
129                                 int r = socketInputStream.read(buffer);
130                                 if (r == -1) {
131                                         /* yay, eof! */
132                                         break;
133                                 }
134                                 outputStream.write(buffer, 0, r);
135                                 progress += r;
136                         }
137                 } catch (IOException ioe1) {
138                         logger.log(Level.WARNING, "I/O error while receiving DCC!", ioe1);
139                 } finally {
140                         socket.close();
141                 }
142         }
143
144 }