1 16 package org.apache.commons.net.tftp; 17 18 import java.io.IOException ; 19 import java.io.InputStream ; 20 import java.io.InterruptedIOException ; 21 import java.io.OutputStream ; 22 import java.net.InetAddress ; 23 import java.net.SocketException ; 24 import java.net.UnknownHostException ; 25 import org.apache.commons.net.io.FromNetASCIIOutputStream; 26 import org.apache.commons.net.io.ToNetASCIIInputStream; 27 28 54 55 public class TFTPClient extends TFTP 56 { 57 62 public static final int DEFAULT_MAX_TIMEOUTS = 5; 63 64 65 private int __maxTimeouts; 66 67 72 public TFTPClient() 73 { 74 __maxTimeouts = DEFAULT_MAX_TIMEOUTS; 75 } 76 77 87 public void setMaxTimeouts(int numTimeouts) 88 { 89 if (numTimeouts < 1) 90 __maxTimeouts = 1; 91 else 92 __maxTimeouts = numTimeouts; 93 } 94 95 101 public int getMaxTimeouts() 102 { 103 return __maxTimeouts; 104 } 105 106 107 123 public int receiveFile(String filename, int mode, OutputStream output, 124 InetAddress host, int port) throws IOException 125 { 126 int bytesRead, timeouts, lastBlock, block, hostPort, dataLength; 127 TFTPPacket sent, received = null; 128 TFTPErrorPacket error; 129 TFTPDataPacket data; 130 TFTPAckPacket ack = new TFTPAckPacket(host, port, 0); 131 132 beginBufferedOps(); 133 134 dataLength = lastBlock = hostPort = bytesRead = 0; 135 block = 1; 136 137 if (mode == TFTP.ASCII_MODE) 138 output = new FromNetASCIIOutputStream(output); 139 140 sent = 141 new TFTPReadRequestPacket(host, port, filename, mode); 142 143 _sendPacket: 144 do 145 { 146 bufferedSend(sent); 147 148 _receivePacket: 149 while (true) 150 { 151 timeouts = 0; 152 while (timeouts < __maxTimeouts) 153 { 154 try 155 { 156 received = bufferedReceive(); 157 break; 158 } 159 catch (SocketException e) 160 { 161 if (++timeouts >= __maxTimeouts) 162 { 163 endBufferedOps(); 164 throw new IOException ("Connection timed out."); 165 } 166 continue; 167 } 168 catch (InterruptedIOException e) 169 { 170 if (++timeouts >= __maxTimeouts) 171 { 172 endBufferedOps(); 173 throw new IOException ("Connection timed out."); 174 } 175 continue; 176 } 177 catch (TFTPPacketException e) 178 { 179 endBufferedOps(); 180 throw new IOException ("Bad packet: " + e.getMessage()); 181 } 182 } 183 184 if (lastBlock == 0) 187 { 188 hostPort = received.getPort(); 189 ack.setPort(hostPort); 190 if(!host.equals(received.getAddress())) 191 { 192 host = received.getAddress(); 193 ack.setAddress(host); 194 sent.setAddress(host); 195 } 196 } 197 198 if (host.equals(received.getAddress()) && 201 received.getPort() == hostPort) 202 { 203 204 switch (received.getType()) 205 { 206 case TFTPPacket.ERROR: 207 error = (TFTPErrorPacket)received; 208 endBufferedOps(); 209 throw new IOException ("Error code " + error.getError() + 210 " received: " + error.getMessage()); 211 case TFTPPacket.DATA: 212 data = (TFTPDataPacket)received; 213 dataLength = data.getDataLength(); 214 215 lastBlock = data.getBlockNumber(); 216 217 if (lastBlock == block) 218 { 219 try 220 { 221 output.write(data.getData(), data.getDataOffset(), 222 dataLength); 223 } 224 catch (IOException e) 225 { 226 error = new TFTPErrorPacket(host, hostPort, 227 TFTPErrorPacket.OUT_OF_SPACE, 228 "File write failed."); 229 bufferedSend(error); 230 endBufferedOps(); 231 throw e; 232 } 233 ++block; 234 break _receivePacket; 235 } 236 else 237 { 238 discardPackets(); 239 240 if (lastBlock == (block - 1)) 241 continue _sendPacket; 243 continue _receivePacket; } 245 247 default: 248 endBufferedOps(); 249 throw new IOException ("Received unexpected packet type."); 250 } 251 } 252 else 253 { 254 error = new TFTPErrorPacket(received.getAddress(), 255 received.getPort(), 256 TFTPErrorPacket.UNKNOWN_TID, 257 "Unexpected host or port."); 258 bufferedSend(error); 259 continue _sendPacket; 260 } 261 262 } 266 267 ack.setBlockNumber(lastBlock); 268 sent = ack; 269 bytesRead += dataLength; 270 } 272 while (dataLength == TFTPPacket.SEGMENT_SIZE); 273 274 bufferedSend(sent); 275 endBufferedOps(); 276 277 return bytesRead; 278 } 279 280 281 298 public int receiveFile(String filename, int mode, OutputStream output, 299 String hostname, int port) 300 throws UnknownHostException , IOException 301 { 302 return receiveFile(filename, mode, output, InetAddress.getByName(hostname), 303 port); 304 } 305 306 307 317 public int receiveFile(String filename, int mode, OutputStream output, 318 InetAddress host) 319 throws IOException 320 { 321 return receiveFile(filename, mode, output, host, DEFAULT_PORT); 322 } 323 324 335 public int receiveFile(String filename, int mode, OutputStream output, 336 String hostname) 337 throws UnknownHostException , IOException 338 { 339 return receiveFile(filename, mode, output, InetAddress.getByName(hostname), 340 DEFAULT_PORT); 341 } 342 343 344 360 public void sendFile(String filename, int mode, InputStream input, 361 InetAddress host, int port) throws IOException 362 { 363 int bytesRead, timeouts, lastBlock, block, hostPort, dataLength, offset; 364 TFTPPacket sent, received = null; 365 TFTPErrorPacket error; 366 TFTPDataPacket data = 367 new TFTPDataPacket(host, port, 0, _sendBuffer, 4, 0); 368 ; 369 TFTPAckPacket ack; 370 371 beginBufferedOps(); 372 373 dataLength = lastBlock = hostPort = bytesRead = 0; 374 block = 0; 375 boolean lastAckWait = false; 376 377 if (mode == TFTP.ASCII_MODE) 378 input = new ToNetASCIIInputStream(input); 379 380 sent = 381 new TFTPWriteRequestPacket(host, port, filename, mode); 382 383 _sendPacket: 384 do 385 { 386 bufferedSend(sent); 387 388 _receivePacket: 389 while (true) 390 { 391 timeouts = 0; 392 while (timeouts < __maxTimeouts) 393 { 394 try 395 { 396 received = bufferedReceive(); 397 break; 398 } 399 catch (SocketException e) 400 { 401 if (++timeouts >= __maxTimeouts) 402 { 403 endBufferedOps(); 404 throw new IOException ("Connection timed out."); 405 } 406 continue; 407 } 408 catch (InterruptedIOException e) 409 { 410 if (++timeouts >= __maxTimeouts) 411 { 412 endBufferedOps(); 413 throw new IOException ("Connection timed out."); 414 } 415 continue; 416 } 417 catch (TFTPPacketException e) 418 { 419 endBufferedOps(); 420 throw new IOException ("Bad packet: " + e.getMessage()); 421 } 422 } 423 424 if (lastBlock == 0) 427 { 428 hostPort = received.getPort(); 429 data.setPort(hostPort); 430 if(!host.equals(received.getAddress())) 431 { 432 host = received.getAddress(); 433 data.setAddress(host); 434 sent.setAddress(host); 435 } 436 } 437 438 if (host.equals(received.getAddress()) && 441 received.getPort() == hostPort) 442 { 443 444 switch (received.getType()) 445 { 446 case TFTPPacket.ERROR: 447 error = (TFTPErrorPacket)received; 448 endBufferedOps(); 449 throw new IOException ("Error code " + error.getError() + 450 " received: " + error.getMessage()); 451 case TFTPPacket.ACKNOWLEDGEMENT: 452 ack = (TFTPAckPacket)received; 453 454 lastBlock = ack.getBlockNumber(); 455 456 if (lastBlock == block) 457 { 458 ++block; 459 if (lastAckWait) 460 break _sendPacket; 461 else 462 break _receivePacket; 463 } 464 else 465 { 466 discardPackets(); 467 468 if (lastBlock == (block - 1)) 469 continue _sendPacket; 471 continue _receivePacket; } 473 475 default: 476 endBufferedOps(); 477 throw new IOException ("Received unexpected packet type."); 478 } 479 } 480 else 481 { 482 error = new TFTPErrorPacket(received.getAddress(), 483 received.getPort(), 484 TFTPErrorPacket.UNKNOWN_TID, 485 "Unexpected host or port."); 486 bufferedSend(error); 487 continue _sendPacket; 488 } 489 490 } 494 495 dataLength = TFTPPacket.SEGMENT_SIZE; 496 offset = 4; 497 while (dataLength > 0 && 498 (bytesRead = input.read(_sendBuffer, offset, dataLength)) > 0) 499 { 500 offset += bytesRead; 501 dataLength -= bytesRead; 502 } 503 504 data.setBlockNumber(block); 505 data.setData(_sendBuffer, 4, offset - 4); 506 sent = data; 507 } 508 while (dataLength == 0 || lastAckWait); 509 510 endBufferedOps(); 511 } 512 513 514 531 public void sendFile(String filename, int mode, InputStream input, 532 String hostname, int port) 533 throws UnknownHostException , IOException 534 { 535 sendFile(filename, mode, input, InetAddress.getByName(hostname), port); 536 } 537 538 539 550 public void sendFile(String filename, int mode, InputStream input, 551 InetAddress host) 552 throws IOException 553 { 554 sendFile(filename, mode, input, host, DEFAULT_PORT); 555 } 556 557 568 public void sendFile(String filename, int mode, InputStream input, 569 String hostname) 570 throws UnknownHostException , IOException 571 { 572 sendFile(filename, mode, input, InetAddress.getByName(hostname), 573 DEFAULT_PORT); 574 } 575 } 576 | Popular Tags |