001 package dk.i1.sctp; 002 import java.net.*; 003 import java.util.Collection; 004 import java.util.ArrayList; 005 006 /** An SCTP socket 007 An SCTP socket behaves in some ways like a TCP socket and in some ways like 008 a datagram socket. 009 <p>You cannot instantiate a SCTPSocket, but rather one of its two subclasses: {@link OneToOneSCTPSocket} and {@link OneToManySCTPSocket}. 010 011 */ 012 public class SCTPSocket { 013 static { 014 System.loadLibrary("dk_i1_sctp"); 015 init(); 016 } 017 private static native void init(); 018 private long impl; 019 SCTPSocket(boolean one_to_many) throws SocketException { 020 impl=0; 021 open(one_to_many); 022 } 023 SCTPSocket(boolean one_to_many, int port) throws SocketException { 024 impl=0; 025 open(one_to_many); 026 bind(port); 027 } 028 protected void finalize() throws Throwable { 029 try { 030 close(); 031 } finally { 032 super.finalize(); 033 } 034 } 035 private native void open(boolean one_to_many) throws SocketException; 036 037 /** Bind to an unspecified address/port. 038 * Binds the socket to a system-decided port and set of addresses. 039 * A socket can only be bound once. 040 */ 041 public void bind() throws SocketException { 042 bind(0); 043 } 044 /** Bind to a specific port. 045 * Binds the socket to the specified port, and system-decided set of addresses. 046 * A socket can only be bound once. 047 *@param port the SCTP port to bind to. 048 */ 049 public void bind(int port) throws SocketException { 050 bind((byte[])null,port); 051 } 052 /** Bind to a specific socket address. 053 * A socket can only be bound once. 054 * @deprecated An important feature of SCTP is multi-homing. This method binds the socket to a single interface and effectively disables multi-homing. This method is only here for completeness' sake. 055 */ 056 public void bind(InetSocketAddress bindaddr) throws SocketException { 057 bind(bindaddr.getAddress(),bindaddr.getPort()); 058 } 059 /** Bind the socket to a spcific port/address. 060 * A socket can only be bound once. 061 * @deprecated An important feature of SCTP is multi-homing. This method binds the socket to a single interface and effectively disables multi-homing. This method is only here for completeness' sake. 062 */ 063 public void bind(InetAddress addr, int port) throws SocketException { 064 bind(addr.getAddress(),port); 065 } 066 private void bind(byte[] addr, int port) throws SocketException { 067 bind_native(addr,port); 068 } 069 private native void bind_native(byte[] addr, int port) throws SocketException; 070 071 /**Close the socket. 072 * Closes the socket. It is better to close the socket explicitly than rely or Java's GC. 073 * note: This method waits for any otustanding receive() calls to finish. 074 */ 075 public native void close() throws SocketException; 076 077 /**Returns the closed state of the socket. 078 *@since 0.5.3 079 */ 080 public native boolean isClosed(); 081 082 /** Subscribe to specific SCTP notifications. 083 * 084 */ 085 public void subscribeEvents(sctp_event_subscribe ses) throws SocketException { 086 subscribeEvents(ses.sctp_data_io_event, 087 ses.sctp_association_event, 088 ses.sctp_address_event, 089 ses.sctp_send_failure_event, 090 ses.sctp_peer_error_event, 091 ses.sctp_shutdown_event, 092 ses.sctp_partial_delivery_event, 093 ses.sctp_adaptation_layer_event 094 ); 095 } 096 private native void subscribeEvents(boolean sctp_data_io_event, 097 boolean sctp_association_event, 098 boolean sctp_address_event, 099 boolean sctp_send_failure_event, 100 boolean sctp_peer_error_event, 101 boolean sctp_shutdown_event, 102 boolean sctp_partial_delivery_event, 103 boolean sctp_adaptation_layer_event 104 ) throws SocketException; 105 106 /**Configure the auto-close feature. 107 *Configures the auto-close timer, or disables it. 108 *@param seconds Number of seconds without traffic before automatically closing associations. 0 means disable. 109 */ 110 public native void configureAutoClose(int seconds) throws SocketException; 111 112 /**Set the blocking mode. 113 *The blocking mode on SCTP sockets affects only two operations: connect() and send(). 114 *When configured in non-blocking connect() will return before the association is established and you should subscribe to the sctp_association_event (see {@link #subscribeEvents}). 115 *When configured in non-blocking send() may throw the {@link WouldBlockException} exception if the send call would block (probably due to OS buffers being full). 116 *@param block If true then send() and connect() any block. If false then send() and connect() will not block 117 */ 118 public native void configureBlocking(boolean block) throws SocketException; 119 120 /**Tells whether send() and connect() may block. 121 */ 122 public native boolean isBlocking() throws SocketException; 123 124 /**Enable/disable SCTP_NODELAY (disable/enable Nagle's algorithm). 125 * @param on true to enable TCP_NODELAY, false to disable. 126 * @since 0.5.4 127 */ 128 public native void setSctpNoDelay(boolean on) throws SocketException; 129 /**Tests if SCTP_NODELAY is enabled. 130 * @return a boolean indicating whether or not SCTP_NODELAY is enabled. 131 * @since 0.5.4 132 */ 133 public native boolean getSctpNoDelay() throws SocketException; 134 135 /** Set the parameters for a peer. 136 * Sets the parameters for a peer, heartbeat intervlal among others. 137 */ 138 public void setPeerParameters(sctp_paddrparams spp) throws SocketException { 139 setPeerParameters_native(spp.spp_assoc_id.id, 140 spp.spp_address==null?null:spp.spp_address.getAddress().getAddress(), 141 spp.spp_address==null?0:spp.spp_address.getPort(), 142 spp.spp_hbinterval, 143 spp.spp_pathmaxrxt, 144 spp.spp_pathmtu, 145 spp.spp_sackdelay, 146 spp.spp_flags, 147 spp.spp_ipv6_flowlabel, 148 spp.spp_ipv4_tos 149 ); 150 } 151 private native void setPeerParameters_native(long spp_assoc_id, 152 byte[] spp_address_raw, 153 int spp_address_port, 154 int spp_hbinterval, 155 short spp_pathmaxrxt, 156 int spp_pathmtu, 157 int spp_sackdelay, 158 int spp_flags, 159 int spp_ipv6_flowlabel, 160 byte spp_ipv4_tos 161 ) throws SocketException; 162 163 /**Set default association parameters. 164 *Setting initialization parameters is effective only on an unconnected 165 *socket (for one-to-many style sockets only future associations are 166 *effected by the change). With one-to-one style sockets, this option 167 *is inherited by sockets derived from a listener socket. 168 */ 169 public void setInitMsg(sctp_initmsg im) throws SocketException { 170 setInitMsg_native(im.sinit_num_ostreams, im.sinit_max_instreams, 171 im.sinit_max_attempts, im.sinit_max_init_timeo); 172 } 173 private native void setInitMsg_native(short sinit_num_ostreams, 174 short sinit_max_instreams, 175 short sinit_max_attempts, 176 short sinit_max_init_timeo) 177 throws SocketException; 178 179 /**Enable inbound connections. 180 *Until listen() has been called inbound associations are not accepted. 181 */ 182 public native void listen() throws SocketException; 183 184 /**Create an association to a peer. 185 * Creates an association to a peer. Explicit association creation is 186 * not needed, but probably a good idea. 187 */ 188 public void connect(InetSocketAddress addr) throws SocketException { 189 connect(addr.getAddress(),addr.getPort()); 190 } 191 /**Create an association to a peer. 192 * Creates an association to a peer. Explicit association creation is 193 * not needed, but probably a good idea. 194 */ 195 public void connect(InetAddress addr, int port) throws SocketException { 196 connect(addr.getAddress(),port); 197 } 198 private void connect(byte[] addr, int port) throws SocketException { 199 connect_native(addr,port); 200 } 201 private native void connect_native(byte[] addr, int port) throws SocketException; 202 203 /**Shut down an association. 204 */ 205 public void disconnect(AssociationId assoc_id) throws SocketException { 206 disconnect_native(assoc_id.id,true); 207 } 208 /**Shut down an association. 209 *@param assoc_id The association to shut down 210 *@param gracefully Controls whether the association is shut down gracefully with SCTP_EOF, or with SCTP_ABORT. 211 */ 212 public void disconnect(AssociationId assoc_id, boolean gracefully) throws SocketException { 213 disconnect_native(assoc_id.id,gracefully); 214 } 215 private native void disconnect_native(long assoc_id, boolean gracefully) throws SocketException; 216 217 218 /**Get local addressed uses by the socket. 219 *Retrieves the list of local addresses the socket can be contacted on. 220 *The list usually includes loopback-addresses, public ip-address and link-local addresses. 221 */ 222 public Collection<InetAddress> getLocalInetAddresses() throws SocketException { 223 return getLocalInetAddresses(AssociationId.default_); 224 } 225 /**Get local addresses used by the socket. 226 *Retrieves the list of local addresses the socket can be contacted on. 227 *The list usually includes loopback-addresses, public ip-address and link-local addresses. 228 */ 229 public Collection<InetAddress> getLocalInetAddresses(AssociationId assoc_id) throws SocketException { 230 Collection<InetAddress> col = new ArrayList<InetAddress>(); 231 getLocalInetAddresses_native(col,assoc_id.id); 232 return col; 233 } 234 private native void getLocalInetAddresses_native(Collection<InetAddress> col, long assoc_id); 235 236 /**Get local port. 237 * Retrieves the local port the socket is bound to. This is useful if you 238 * did not specify a specific port to bind to in the call to bind(). 239 */ 240 public native int getLocalInetPort() throws SocketException; 241 242 /**Get addresses of a peer. 243 *Retrieves a list of known addresses of a peer, including non-reachable addresses. 244 */ 245 public Collection<InetAddress> getPeerInetAddresses(AssociationId assoc_id) { 246 Collection<InetAddress> col = new ArrayList<InetAddress>(); 247 getPeerInetAddresses_native(col,assoc_id.id); 248 return col; 249 } 250 private native void getPeerInetAddresses_native(Collection<InetAddress> col, long assoc_id); 251 252 public int getPeerInetPort(AssociationId assoc_id) throws SocketException { 253 return getPeerInetPort_native(assoc_id.id); 254 } 255 private native int getPeerInetPort_native(long aid) throws SocketException; 256 257 /**Probe if any unread chunks are pending 258 *@return true if any chunks are pending reading 259 */ 260 public native boolean chunkAvailable() throws SocketException; 261 262 /**Receive a data chunk or a notification. 263 *Implemented as <tt>receive(0)</tt> 264 *@return a SCTPChunk, or, in some cases, null 265 */ 266 public SCTPChunk receive() throws SocketException { 267 return receive_native(0); 268 } 269 /**Receive a data chunk or a notification. 270 *If no events are available the call returns immediately with null. 271 *@return a SCTPChunk, or, in some cases, null 272 */ 273 public SCTPChunk receiveNow() throws SocketException { 274 return receive_native(-1); 275 } 276 /**Receive a data chunk or a notification. 277 *@param timeout Milliseconds to wait for an event. 0 means infinite. Must not be negative. 278 *@return a SCTPChunk, or, in some cases, null 279 */ 280 public SCTPChunk receive(long timeout) throws SocketException, IllegalArgumentException { 281 if(timeout<0) 282 throw new IllegalArgumentException(); 283 return receive_native(timeout); 284 } 285 private native SCTPChunk receive_native(long timeout) throws SocketException; 286 287 /**Send a datagram to a peer. 288 * Sends the data chunk to a peer. The peer is specified in sctpdata.sndrcvinfo.sinfo_assoc_id. 289 * <p>Example:</p> 290 <pre> 291 SCTPData data = new SCTPData(<i>raw_byte_array</i>); 292 data.sndrcvinfo.sinfo_assoc_id = <i>destination_association_id</i>; 293 sctp_socket.send(data); 294 </pre> 295 *@param sctpdata the data chunk to send. 296 *@throws SocketException if a socket error occurs. 297 *@throws WouldBlockException if the socket is non-blocking and outgoing OS buffers are full. 298 */ 299 public void send(SCTPData sctpdata) throws SocketException, WouldBlockException { 300 send_native(sctpdata.data,sctpdata.sndrcvinfo); 301 } 302 private native void send_native(byte[] data, sctp_sndrcvinfo sndrcvinfo) throws SocketException, WouldBlockException; 303 304 /**Wake other threads from receive(). 305 *Wakes 1 thread that is currently blocking in a receive() call. 306 *This method is only meant for clean shutdown, and is not as nice and the equivalent method in java.nio.Selector. 307 *The woken thread will return null. 308 */ 309 public native void wakeup() throws SocketException; 310 }