KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > rero > dcc > Send


1 /*
2     jerk.irc.dcc.ChatClient [ created - 1/2/02 ]
3
4     Author: Raphael Mudge (rsmudge@mtu.edu)
5     
6     Description:
7     handles the details of talking in a DCC connection, nothing to do
8     with actually establishing the connection. Talks to a JerkEngine
9     reference.
10
11     Documentation:
12     n/a
13
14     Changelog:
15        
16 */

17
18 package rero.dcc;
19
20 import java.util.*;
21
22 import java.net.*;
23 import java.io.*;
24
25 import rero.ircfw.*;
26 import rero.ircfw.interfaces.*;
27
28 public class Send extends ProtocolDCC
29 {
30     protected static int PACKET_SIZE = 4096;
31
32     protected File dumpFrom;
33     protected FileInputStream fileStream;
34
35     protected long sentSize;
36     protected long ackSize;
37     protected long finalSize;
38     protected long startSize; // an offset of where we started from, so resumes don't throw off the download stats
39

40     public boolean resume(long size)
41     {
42        if (size < dumpFrom.length())
43        {
44           sentSize = size;
45           startSize = size;
46
47           return true;
48        }
49
50        return false;
51     }
52
53     /**
54      * Create a ready to rock and roll receive socket. It is assumed that the File object is either cleared
55      * or ready to be resumed. An overwrite command should delete the file first and then start dumping to it.
56      * Hopefully this is a safe way to go. Eh?
57      */

58     public Send(String JavaDoc _nickname, File _dumpFrom)
59     {
60        nickname = _nickname;
61        dumpFrom = _dumpFrom;
62
63        finalSize = _dumpFrom.length();
64        ackSize = 0;
65        sentSize = 0;
66
67        startSize = 0;
68
69        eventData = new HashMap();
70     }
71
72     /** return the total number of bytes that have been sent */
73     public long getBytesSent()
74     {
75        return sentSize;
76     }
77
78     /** return the total number of bytes that have been acknowledged by the user */
79     public long getAcknowledgedSize()
80     {
81        return ackSize;
82     }
83
84     /** return the File we are sending to the user */
85     public File getFile()
86     {
87        return dumpFrom;
88     }
89
90     /** return the number of bytes that we started out with (0 normally, however in the case of a resume this number could be
91         anything from 0 up to nearly the size of the file */

92     public long getStartOffset()
93     {
94        return startSize;
95     }
96
97     /** return the estimated time remaning in seconds */
98     public long getTimeRemaining()
99     {
100        long totalSizeLeft = getFile().length() - getBytesSent();
101        long transferRate = (long)getTransferRate();
102
103        if (transferRate == 0)
104            transferRate = 1000;
105
106        return totalSizeLeft / transferRate;
107     }
108
109     /** return the number of bytes transferred per second */
110     public int getTransferRate()
111     {
112        if (getTotalTime() < 1000)
113             return 1000;
114
115        return (int)( (getBytesSent() - getStartOffset()) / (getTotalTime() / 1000));
116     }
117
118     public int getTypeOfDCC()
119     {
120        return DCC_SEND;
121     }
122
123     public void run()
124     {
125        if (socket == null || !socket.isConnected())
126        {
127           return;
128        }
129
130        try
131        {
132           socket.setSoTimeout(DCC_TIMEOUT);
133        }
134        catch (Exception JavaDoc ex)
135        {
136           ex.printStackTrace();
137        }
138
139        fireEvent("SEND_START", null);
140
141 // dispatcher.dispatchEvent(eventData);
142

143        DataInputStream istream = null;
144        OutputStream ostream = null;
145
146        byte[] data = new byte[PACKET_SIZE]; // send packets in 4k chunks
147

148        try
149        {
150           fileStream = new FileInputStream(dumpFrom);
151           fileStream.skip(sentSize);
152
153           istream = new DataInputStream(socket.getInputStream());
154           ostream = socket.getOutputStream();
155    
156           //
157
// pump the file out as fast as we can, check the acknowledgements when we're done.
158
//
159

160           int thisRead;
161
162           while (socket.isConnected() && sentSize < finalSize)
163           {
164              if ( (finalSize - sentSize) < PACKET_SIZE )
165              {
166                 thisRead = fileStream.read(data, 0, (int) (finalSize - sentSize) );
167              }
168              else
169              {
170                 thisRead = fileStream.read(data, 0, PACKET_SIZE);
171              }
172
173              if (thisRead > 0)
174              {
175                 ostream.write(data, 0, thisRead);
176                 ostream.flush();
177                 sentSize += thisRead;
178
179                 // System.out.println("Sent: " + sentSize + " bytes of " + finalSize);
180
}
181
182              if (istream.available() >= 4)
183              {
184                 ackSize = 0;
185                 ackSize += istream.readUnsignedByte() << 24L;
186                 ackSize += istream.readUnsignedByte() << 16L;
187                 ackSize += istream.readUnsignedByte() << 8L;
188                 ackSize += istream.readUnsignedByte() << 0L;
189
190                 // System.out.println("Ackd: " + ackSize + " bytes");
191

192                 idleTime = System.currentTimeMillis();
193              }
194           }
195
196           while (socket.isConnected() && ackSize < finalSize && getIdleTime() < 10000)
197           {
198              if (istream.available() >= 4)
199              {
200                 ackSize = 0;
201                 ackSize += istream.readUnsignedByte() << 24L;
202                 ackSize += istream.readUnsignedByte() << 16L;
203                 ackSize += istream.readUnsignedByte() << 8L;
204                 ackSize += istream.readUnsignedByte() << 0L;
205
206                 // System.out.println("Ackd: " + ackSize + " bytes");
207

208                 idleTime = System.currentTimeMillis();
209              }
210              else
211              {
212                 Thread.sleep(500);
213              }
214           }
215        }
216        catch (Exception JavaDoc ex)
217        {
218           if (sentSize != finalSize)
219           {
220              ex.printStackTrace();
221              fireError(ex.getMessage());
222              return;
223           }
224        }
225
226        try
227        {
228           fileStream.close();
229        }
230        catch (Exception JavaDoc ex)
231        {
232           ex.printStackTrace();
233        }
234
235        if (sentSize == finalSize)
236        {
237           fireEvent("SEND_COMPLETE", null);
238        }
239        else
240        {
241           fireError("incomplete");
242        }
243     }
244
245     public void fireError(String JavaDoc description)
246     {
247        eventData.put(FrameworkConstants.$NICK$, getNickname());
248        eventData.put(FrameworkConstants.$EVENT$, "SEND_FAILED");
249        eventData.put(FrameworkConstants.$DATA$, getNickname() + " " + description);
250        eventData.put(FrameworkConstants.$PARMS$, description);
251        eventData.put("$this", this.toString());
252
253        dispatcher.dispatchEvent(eventData);
254     }
255
256     public void fireEvent(String JavaDoc event, String JavaDoc description)
257     {
258        eventData.put(FrameworkConstants.$NICK$, getNickname());
259        eventData.put(FrameworkConstants.$EVENT$, event);
260        eventData.put(FrameworkConstants.$DATA$, getNickname() + " " + description);
261        eventData.put(FrameworkConstants.$PARMS$, description);
262
263        eventData.put("$this", this.toString());
264
265        dispatcher.dispatchEvent(eventData);
266     }
267 }
268
Popular Tags