/*
* Copyright 2017 Async-IO.org
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.atmosphere.wasync;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
/**
* A Socket represents a connection to a remote server. A Socket abstract the transport used and will negotiate
* the best {@link org.atmosphere.wasync.Request.TRANSPORT} to communicate with the Server.
* <p></p>
* Depending on the transport used, one or two connections will be opened. For WebSocket, a single, bi-directional connection
* will be used. For other transport like streaming, server side events and long-polling, a connection will be opened
* to the server and will be suspended (stay opened) until an event happen on the server. A second connection will be opened every time the {@link #fire(Object)}
* method is invoked and cached for further re-use.
* <p></p>
*
* As simple as
* <blockquote><pre>
Client client = AtmosphereClientFactory.getDefault().newClient();
RequestBuilder request = client.newRequestBuilder()
.method(Request.METHOD.GET)
.uri(targetUrl + "/suspend")
.encoder(new Encoder<String, Reader>() { // Stream the request body
@Override
public Reader encode(String s) {
return new StringReader(s);
}
})
.decoder(new Decoder<String, Reader>() {
@Override
public Reader decode(String s) {
return new StringReader(s);
}
})
.transport(Request.TRANSPORT.WEBSOCKET) // Try WebSocket
.transport(Request.TRANSPORT.LONG_POLLING); // Fallback to Long-Polling
Socket socket = client.create();
socket.on("message", new Function<String>() {
@Override
public void on(Reader r) {
// Read the response
}
}).on(new Function<IOException>() {
@Override
public void on(Throwable t) {
// Some IOException occurred
}
}).open(request.build()).fire("echo");
* </pre></blockquote>
*
* @author Jeanfrancois Arcand
*/
public interface Socket {
/**
* The current state of the underlying Socket.
*/
public enum STATUS {
/**
* The socket is not yet connected
*/
INIT,
/**
* The socket is open and ready to send messages
*/
OPEN,
/**
* The socket was closed and re-opened
*/
REOPENED,
/**
* The socket is close
*/
CLOSE,
/**
* The socket is broken
*/
ERROR }
/**
* Send data to the remote Server. The object will first be delivered to the set of {@link Encoder}, and then send to the server.
* The server's response will be delivered to the set of defined {@link Function} using the opened {@link Transport}, e.g for
* {@link Request.TRANSPORT#WEBSOCKET}, the same connection will be re-used and, for others transports, the suspended connection.
* @param data object to send
* @return a {@link Future}
* @throws IOException
*/
Future fire(Object data) throws IOException;
/**
* Associate a {@link Function} with the Socket. When a response is received, the library will try to associated
* the decoded message (decoded by {@link Decoder}) to the defined type of the {@link Function}
* @param function a {@link Function}
* @return this
*/
Socket on(Function<?> function);
/**
* Associate a {@link Function} with the Socket. When a response is received, the library will try to associated
* the decoded message (decoded by {@link Decoder}) to the defined type of the {@link Function}. The default messages
* are defined by {@link org.atmosphere.wasync.Event} but handling of custom message can be done using a {@link FunctionResolver}
* @param function a {@link Function}
* @return this
*/
Socket on(String functionMessage, Function<?> function);
/**
* Associate a {@link Function} with an {@link Event}. When the event happen the library will try to associated
* the decoded event (decoded by {@link Decoder}) to the defined type of the {@link Function}. The default event
* are defined by {@link org.atmosphere.wasync.Event} but handling of custom event can be done using a {@link FunctionResolver}
* @param function a {@link Function}
* @return this
*/
Socket on(Event event, Function<?> function);
/**
* Connect to the remote Server using the {@link Request}'s information.
* @param request a {@link Request}
* @return this
* @throws IOException in case the connect fails or a network failure occurs.
*/
Socket open(Request request) throws IOException;
/**
* Connect to the remote Server using the {@link Request}'s information, will timeout if the connection failed to open
* within a certain time.
* @param request a {@link Request}
* @param timeout the maximum time to wait
* @param unit the time unit of the timeout argument
* @return this
* @throws IOException in case the connect fails or a network failure occurs.
*/
Socket open(Request request, long timeout, TimeUnit unit) throws IOException;
/**
* Close this Socket, asynchronously.
*/
void close();
/**
* Return the {@link STATUS} of this Socket.
*/
STATUS status();
}