/*******************************************************************************
* Copyright 2011 See AUTHORS file.
*
* 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 com.badlogic.gdx;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Future;
import com.badlogic.gdx.Net.HttpRequest;
import com.badlogic.gdx.Net.HttpResponseListener;
import com.badlogic.gdx.net.ServerSocketHints;
import com.badlogic.gdx.net.Socket;
import com.badlogic.gdx.net.ServerSocket;
import com.badlogic.gdx.net.SocketHints;
import com.badlogic.gdx.utils.GdxRuntimeException;
import com.badlogic.gdx.utils.JsonWriter;
/**
* Provides methods to perform networking operations, such as simple HTTP get and post requests, and TCP server/client
* socket communication.</p>
*
* To perform an HTTP request create a {@link HttpRequest} with the HTTP method (see {@link HttpMethods} for common
* methods) and invoke {@link #sendHttpRequest(HttpRequest, HttpResponseListener)} with it and a
* {@link HttpResponseListener}. After the HTTP request was processed, the {@link HttpResponseListener} is called with a
* {@link HttpResponse} with the HTTP response values and an status code to determine if the request was successful or
* not.
*
* To create a TCP client socket to communicate with a remote TCP server, invoke the
* {@link #newClientSocket(Protocol, String, int, SocketHints)} method. The returned {@link Socket} offers an
* {@link InputStream} and {@link OutputStream} to communicate with the end point.</p>
*
* To create a TCP server socket that waits for incoming connections, invoke the
* {@link #newServerSocket(Protocol, int, ServerSocketHints)} method. The returned {@link ServerSocket} offers an
* {@link ServerSocket#accept(SocketHints options)} method that waits for an incoming connection.
*
* @author mzechner
* @author noblemaster
* @author arielsan
*/
public interface Net {
/**
* Contains information about the HTTP status line returned with the {@link HttpResponse} after a
* {@link HttpRequest} was performed.
*/
public static class HttpStatus {
int statusCode;
/**
* Returns the status code of the HTTP response, normally 2xx status codes indicate success while 4xx and 5xx
* indicate client and server errors, respectively (see <a
* href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html">HTTP/1.1: Status Code Definitions</a> for more
* information about HTTP status codes).
*/
public int getStatusCode() {
return statusCode;
}
public HttpStatus(int statusCode) {
this.statusCode = statusCode;
}
}
/**
* HTTP response interface with methods to get the response data as a byte[], a {@link String} or an
* {@link InputStream}.
*/
public static interface HttpResponse {
/**
* Returns the data of the HTTP response as a byte[].
*
* @return the result as a byte[] or null in case of a timeout or if the operation was canceled/terminated
* abnormally. The timeout is specified when creating the HTTP request, with
* {@link HttpRequest#setTimeOut(int)}
*/
byte[] getResult();
/**
* Returns the data of the HTTP response as a {@link String}.
*
* @return the result as a string or null in case of a timeout or if the operation was canceled/terminated
* abnormally. The timeout is specified when creating the HTTP request, with
* {@link HttpRequest#setTimeOut(int)}
*/
String getResultAsString();
/**
* Returns the data of the HTTP response as an {@link InputStream}.
*
* @return An {@link InputStream} with the {@link HttpResponse} data.
*/
InputStream getResultAsStream();
/** Returns the {@link HttpStatus} containing the statusCode of the HTTP response. */
HttpStatus getStatus();
}
/**
* Provides common HTTP methods to use when creating a {@link HttpRequest}.
* <ul>
* <li>GET</li>
* <li>POST</li>
* <li>JSON</li>
* </ul>
*/
public static interface HttpMethods {
public static final String GET = "GET";
public static final String POST = "POST";
}
/**
* Contains getters and setters for the following parameters:
* <ul>
* <li><strong>httpMethod:</strong> GET or POST are most common, can use {@link Net.HttpMethods HttpMethods} for
* static references</li>
* <li><strong>url:</strong> the url</li>
* <li><strong>headers:</strong> a map of the headers, setter can be called multiple times</li>
* <li><strong>timeout:</strong> time spent trying to connect before giving up</li>
* <li><strong>content:</strong> A string containing the data to be used when processing the HTTP request.</li>
* </ul>
*
* Abstracts the concept of a HTTP Request:
*
* <pre>
* Map<String, String> parameters = new HashMap<String, String>();
* parameters.put("user", "myuser");
*
* HttpRequest httpGet = new HttpRequest(HttpMethods.Get);
* httpGet.setUrl("http://somewhere.net");
* httpGet.setContent(HttpParametersUtils.convertHttpParameters(parameters));
* ...
* Gdx.net.sendHttpRequest (httpGet, new HttpResponseListener() {
* public void handleHttpResponse(HttpResponse httpResponse) {
* status = httpResponse.getResultAsString();
* //do stuff here based on response
* }
*
* public void failed(Throwable t) {
* status = "failed";
* //do stuff here based on the failed attempt
* }
* });
* </pre>
*/
public static class HttpRequest {
private final String httpMethod;
private String url;
private Map<String, String> headers;
private int timeOut = 0;
private String content;
private InputStream contentStream;
private long contentLength;
/**
* Creates a new HTTP request with the specified HTTP method, see {@link HttpMethods}.
*
* @param httpMethod
* This is the HTTP method for the request, see {@link HttpMethods}
*/
public HttpRequest(String httpMethod) {
this.httpMethod = httpMethod;
this.headers = new HashMap<String, String>();
}
/**
* Sets the URL of the HTTP request.
*
* @param url
* The URL to set.
*/
public void setUrl(String url) {
this.url = url;
}
/**
* Sets a header to this HTTP request. Headers definition could be found at <a
* href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html">HTTP/1.1: Header Field Definitions</a>
* document.
*
* @param name
* the name of the header.
* @param value
* the value of the header.
*/
public void setHeader(String name, String value) {
headers.put(name, value);
}
/**
* Sets the content to be used in the HTTP request.
*
* @param content
* A string encoded in the corresponding Content-Encoding set in the headers, with the data to send
* with the HTTP request. For example, in case of HTTP GET, the content is used as the query string
* of the GET while on a HTTP POST it is used to send the POST data.
*/
public void setContent(String content) {
this.content = content;
}
/**
* Sets the content as a stream to be used for a POST for example, to transmit custom data.
*
* @param contentStream
* The stream with the content data.
*/
public void setContent(InputStream contentStream, long contentLength) {
this.contentStream = contentStream;
this.contentLength = contentLength;
}
/**
* Sets the time to wait for the HTTP request to be processed, use 0 block until it is done. The timeout is used
* for both the timeout when establishing TCP connection, and the timeout until the first byte of data is
* received.
*
* @param timeOut
* the number of milliseconds to wait before giving up, 0 or negative to block until the operation is
* done
*/
public void setTimeOut(int timeOut) {
this.timeOut = timeOut;
}
/**
* Returns the timeOut of the HTTP request.
*
* @return the timeOut.
*/
public int getTimeOut() {
return timeOut;
}
/** Returns the HTTP method of the HttpRequest. */
public String getMethod() {
return httpMethod;
}
/** Returns the URL of the HTTP request. */
public String getUrl() {
return url;
}
/** Returns the content string to be used for the HTTP request. */
public String getContent() {
return content;
}
/** Returns the content stream. */
public InputStream getContentStream() {
return contentStream;
}
/** Returns the content length in case content is a stream. */
public long getContentLength() {
return contentLength;
}
/** Returns a Map<String, String> with the headers of the HTTP request. */
public Map<String, String> getHeaders() {
return headers;
}
}
/**
* Listener to be able to do custom logic once the {@link HttpResponse} is ready to be processed, register it with
* {@link Net#sendHttpRequest(HttpRequest, HttpResponseListener)}.
*/
public static interface HttpResponseListener {
/**
* Called when the {@link HttpRequest} has been processed and there is a {@link HttpResponse} ready.
* {@link HttpResponse} contains the {@link HttpStatus} and should be used to determine if the request was
* successful or not (see more info at {@link HttpStatus#getStatusCode()}). For example:
*
* <pre>
* HttpResponseListener listener = new HttpResponseListener() {
* public void handleHttpResponse (HttpResponse httpResponse) {
* HttpStatus status = httpResponse.getStatus();
* if (status.getStatusCode() >= 200 && status.getStatusCode() < 300) {
* // it was successful
* } else {
* // do something else
* }
* }
* }
* </pre>
*
* @param httpResponse
* The {@link HttpResponse} with the HTTP response values.
*/
void handleHttpResponse(HttpResponse httpResponse);
/**
* Called if the {@link HttpRequest} failed because an exception when processing the HTTP request, could be a
* timeout any other reason (not an HTTP error).
*
* @param t
* If the HTTP request failed because an Exception, t encapsulates it to give more information.
*/
void failed(Throwable t);
}
/**
* Process the specified {@link HttpRequest} and reports the {@link HttpResponse} to the specified
* {@link HttpResponseListener} .
*
* @param httpRequest
* The {@link HttpRequest} to be performed.
* @param httpResponseListener
* The {@link HttpResponseListener} to call once the HTTP response is ready to be processed. Could be
* null, in that case no listener is called.
*/
public void sendHttpRequest(HttpRequest httpRequest, HttpResponseListener httpResponseListener);
/**
* Protocol used by {@link Net#newServerSocket(Protocol, int, ServerSocketHints)} and
* {@link Net#newClientSocket(Protocol, String, int, SocketHints)}.
*
* @author mzechner
*/
public enum Protocol {
TCP
}
/**
* Creates a new server socket on the given port, using the given {@link Protocol}, waiting for incoming
* connections.
*
* @param port
* the port to listen on
* @param hints
* additional {@link ServerSocketHints} used to create the socket. Input null to use the default setting
* provided by the system.
* @return the {@link ServerSocket}
* @throws GdxRuntimeException
* in case the socket couldn't be opened
*/
public ServerSocket newServerSocket(Protocol protocol, int port, ServerSocketHints hints);
/**
* Creates a new TCP client socket that connects to the given host and port.
*
* @param host
* the host address
* @param port
* the port
* @param hints
* additional {@link SocketHints} used to create the socket. Input null to use the default setting
* provided by the system.
* @return GdxRuntimeException in case the socket couldn't be opened
*/
public Socket newClientSocket(Protocol protocol, String host, int port, SocketHints hints);
/**
* Launches the default browser to display a URI. If the default browser is not able to handle the specified URI,
* the application registered for handling URIs of the specified type is invoked. The application is determined from
* the protocol and path of the URI.
*
* @param URI
* the URI to be opened.
*/
public void openURI(String URI);
}