package net.i2p.client.streaming; import java.net.SocketException; import net.i2p.I2PAppContext; import net.i2p.client.SendMessageStatusListener; import net.i2p.data.i2cp.MessageStatusMessage; import net.i2p.util.Translate; /** * An I2P-specific IOException thrown from input and output streams, * with a stored status code to be used for programmatic responses. * * @since 0.9.14 */ public class I2PSocketException extends SocketException { private final int _status; private static final int CUSTOM = -1; private static final String BUNDLE_NAME = "net.i2p.client.streaming.messages"; /** * Router and I2CP status codes are 0 - 511. Start ours at 512. * @since 0.9.19 */ public static final int STATUS_CONNECTION_RESET = 512; /** * Use canned message for this status code. * * Standard codes from the router are 0-255, defined in MessageStatusMessage. * Standard codes from client-side I2CP are 256-511, defined in SendMessageStatusListener. * Standard codes from streaming are 512-767, defined here. * * @param status >= 0 from MessageStatusMessage or SendMessageStatusListener */ public I2PSocketException(int status) { super(); _status = status; } /** * Use message provided */ public I2PSocketException(String message) { super(message); _status = CUSTOM; } /** * For programmatic action based on specific failure code * * @return value from int constructor or -1 for String constructor */ public int getStatus() { return _status; } /** * For programmatic action based on specific failure code * * @return canned message based on status in int constructor or message from String constructor */ @Override public String getMessage() { switch (_status) { case MessageStatusMessage.STATUS_SEND_BEST_EFFORT_FAILURE: case MessageStatusMessage.STATUS_SEND_GUARANTEED_FAILURE: return _x("Message timeout"); case MessageStatusMessage.STATUS_SEND_FAILURE_LOCAL: return _x("Failed delivery to local destination"); case MessageStatusMessage.STATUS_SEND_FAILURE_ROUTER: return _x("Local router failure"); case MessageStatusMessage.STATUS_SEND_FAILURE_NETWORK: return _x("Local network failure"); case MessageStatusMessage.STATUS_SEND_FAILURE_BAD_SESSION: return _x("Session closed"); case MessageStatusMessage.STATUS_SEND_FAILURE_BAD_MESSAGE: return _x("Invalid message"); case MessageStatusMessage.STATUS_SEND_FAILURE_BAD_OPTIONS: return _x("Invalid message options"); case MessageStatusMessage.STATUS_SEND_FAILURE_OVERFLOW: return _x("Buffer overflow"); case MessageStatusMessage.STATUS_SEND_FAILURE_EXPIRED: return _x("Message expired"); case MessageStatusMessage.STATUS_SEND_FAILURE_LOCAL_LEASESET: return _x("Local lease set invalid"); case MessageStatusMessage.STATUS_SEND_FAILURE_NO_TUNNELS: return _x("No local tunnels"); case MessageStatusMessage.STATUS_SEND_FAILURE_UNSUPPORTED_ENCRYPTION: return _x("Unsupported encryption options"); case MessageStatusMessage.STATUS_SEND_FAILURE_DESTINATION: return _x("Invalid destination"); case MessageStatusMessage.STATUS_SEND_FAILURE_BAD_LEASESET: return _x("Local router failure"); case MessageStatusMessage.STATUS_SEND_FAILURE_EXPIRED_LEASESET: return _x("Destination lease set expired"); case MessageStatusMessage.STATUS_SEND_FAILURE_NO_LEASESET: return _x("Destination lease set not found"); case SendMessageStatusListener.STATUS_CANCELLED: return _x("Local destination shutdown"); case STATUS_CONNECTION_RESET: return _x("Connection was reset"); case CUSTOM: return super.getMessage(); default: // Translate this one here, can't do it later return _t("Failure code") + ": " + _status; } } /** * Translated */ @Override public String getLocalizedMessage() { String s = getMessage(); if (s == null) return null; return _t(s); } /** * Translate */ private static String _t(String s) { return Translate.getString(s, I2PAppContext.getGlobalContext(), BUNDLE_NAME); } /** * Tag for translation */ private static String _x(String s) { return s; } }