/* This file is part of jpcsp. Jpcsp is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Jpcsp is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Jpcsp. If not, see <http://www.gnu.org/licenses/>. */ package jpcsp.HLE.modules; import java.io.FileNotFoundException; import java.io.IOException; import java.io.OutputStream; import java.net.CookieHandler; import java.net.CookieManager; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.Proxy; import java.net.URL; import java.net.URLConnection; import java.util.HashMap; import java.util.List; import java.util.Map; import jpcsp.Memory; import jpcsp.HLE.BufferInfo; import jpcsp.HLE.BufferInfo.LengthInfo; import jpcsp.HLE.BufferInfo.Usage; import jpcsp.HLE.CanBeNull; import jpcsp.HLE.HLEFunction; import jpcsp.HLE.HLELogging; import jpcsp.HLE.HLEModule; import jpcsp.HLE.HLEUnimplemented; import jpcsp.HLE.PspString; import jpcsp.HLE.SceKernelErrorException; import jpcsp.HLE.TPointer; import jpcsp.HLE.TPointer32; import jpcsp.HLE.TPointer64; import jpcsp.HLE.kernel.managers.SceUidManager; import jpcsp.HLE.kernel.types.SceKernelErrors; import jpcsp.HLE.modules.SysMemUserForUser.SysMemInfo; import jpcsp.HLE.Modules; import jpcsp.memory.IMemoryWriter; import jpcsp.memory.MemoryWriter; import jpcsp.remote.HTTPConfiguration; import jpcsp.remote.HTTPConfiguration.HttpServerConfiguration; import jpcsp.remote.HTTPServer; import jpcsp.util.ThreadLocalCookieManager; import jpcsp.util.Utilities; import org.apache.log4j.Logger; public class sceHttp extends HLEModule { public static Logger log = Modules.getLogger("sceHttp"); public static final int PSP_HTTP_SYSTEM_COOKIE_HEAP_SIZE = 130 * 1024; private boolean isHttpInit; private boolean isSystemCookieLoaded; private int maxMemSize; private SysMemInfo memInfo; protected HashMap<Integer, HttpTemplate> httpTemplates = new HashMap<Integer, HttpTemplate>(); protected HashMap<Integer, HttpConnection> httpConnections = new HashMap<Integer, HttpConnection>(); protected HashMap<Integer, HttpRequest> httpRequests = new HashMap<Integer, HttpRequest>(); private CookieManager cookieManager; private static final String httpMethods[] = { "GET", "POST", "HEAD", "OPTIONS", "PUT", "DELETE", "TRACE", "CONNECT" }; protected static class HttpRequest { private static final String uidPurpose = "sceHttp-HttpRequest"; private int id; private String url; private String path; private int method; private long contentLength; private HttpConnection httpConnection; private URLConnection urlConnection; private HttpURLConnection httpUrlConnection; private HashMap<String, String> headers = new HashMap<String, String>(); private byte[] sendData; private int sendDataLength; public HttpRequest() { id = SceUidManager.getNewUid(uidPurpose); Modules.sceHttpModule.httpRequests.put(id, this); } public void delete() { Modules.sceHttpModule.httpRequests.remove(id); SceUidManager.releaseUid(id, uidPurpose); id = -1; } public int getId() { return id; } public String getUrl() { if (url != null) { return url; } if (path != null) { if (path.startsWith("http:") || path.startsWith("https:")) { return path; } return getHttpConnection().getUrl() + path; } return null; } public void setUrl(String url) { this.url = url; } public void setPath(String path) { this.path = path; } public int getMethod() { return method; } public void setMethod(int method) { this.method = method; } public long getContentLength() { return contentLength; } public void setContentLength(long contentLength) { this.contentLength = contentLength; } public HttpConnection getHttpConnection() { return httpConnection; } public void setHttpConnection(HttpConnection httpConnection) { this.httpConnection = httpConnection; } public void send(int data, int dataSize) { if (dataSize > 0) { sendData = Utilities.extendArray(sendData, dataSize); Utilities.readBytes(data, dataSize, sendData, sendDataLength); sendDataLength += dataSize; } } public void connect() { if (urlConnection != null) { // Already connected return; } ThreadLocalCookieManager.setCookieManager(Modules.sceHttpModule.cookieManager); if (log.isTraceEnabled()) { log.trace(String.format("HttpRequest %s send: %s", this, Utilities.getMemoryDump(sendData, 0, sendDataLength))); } String sendUrl = getUrl(); Proxy proxy = getProxyForUrl(sendUrl); // Replace https with http when using a proxy if (proxy != null) { if (sendUrl.startsWith("https:")) { sendUrl = "http:" + sendUrl.substring(6); } } try { if (proxy != null) { urlConnection = new URL(sendUrl).openConnection(proxy); } else { urlConnection = new URL(sendUrl).openConnection(); } String agent = getHttpConnection().getHttpTemplate().getAgent(); if (agent != null) { if (log.isTraceEnabled()) { log.trace((String.format("Adding header '%s': '%s'", "User-Agent", agent))); } urlConnection.setRequestProperty("User-Agent", agent); } for (String header : headers.keySet()) { if (log.isTraceEnabled()) { log.trace(String.format("Adding header '%s': '%s'", header, headers.get(header))); } urlConnection.setRequestProperty(header, headers.get(header)); } if (urlConnection instanceof HttpURLConnection) { httpUrlConnection = (HttpURLConnection) urlConnection; httpUrlConnection.setRequestMethod(httpMethods[method]); httpUrlConnection.setInstanceFollowRedirects(getHttpConnection().isEnableRedirect()); if (sendDataLength > 0) { httpUrlConnection.setDoOutput(true); OutputStream os = httpUrlConnection.getOutputStream(); os.write(sendData, 0, sendDataLength); os.close(); } } else { httpUrlConnection = null; } urlConnection.connect(); setContentLength(urlConnection.getContentLength()); } catch (MalformedURLException e) { log.error("HttpRequest.send", e); } catch (IOException e) { log.error("HttpRequest.send", e); } } public int readData(int data, int dataSize) { byte buffer[] = new byte[dataSize]; int bufferLength = 0; try { while (bufferLength < dataSize) { int readSize = urlConnection.getInputStream().read(buffer, bufferLength, dataSize - bufferLength); if (readSize < 0) { break; } bufferLength += readSize; } } catch (FileNotFoundException e) { log.debug("HttpRequest.readData", e); } catch (IOException e) { log.error("HttpRequest.readData", e); } if (bufferLength > 0) { IMemoryWriter memoryWriter = MemoryWriter.getMemoryWriter(data, bufferLength, 1); for (int i = 0; i < bufferLength; i++) { memoryWriter.writeNext(buffer[i] & 0xFF); } memoryWriter.flush(); } return bufferLength; } public String getAllHeaders() { if (urlConnection == null) { return null; } StringBuilder allHeaders = new StringBuilder(); Map<String, List<String>> properties = urlConnection.getHeaderFields(); for (String key : properties.keySet()) { if (key != null) { List<String> values = properties.get(key); for (String value : values) { allHeaders.append(String.format("%s: %s\r\n", key, value)); } } } return allHeaders.toString(); } public int getStatusCode() { int statusCode = 0; if (httpUrlConnection != null) { try { statusCode = httpUrlConnection.getResponseCode(); } catch (IOException e) { log.error("HttpRequest.getStatusCode", e); } } return statusCode; } private void addHeader(String name, String value) { headers.put(name, value); } @Override public String toString() { return String.format("HttpRequest id=%d, url='%s', method=%d, contentLength=%d", getId(), getUrl(), getMethod(), contentLength); } } protected static class HttpConnection { private static final String uidPurpose = "sceHttp-HttpConnection"; private int id; private HashMap<Integer, HttpRequest> httpRequests = new HashMap<Integer, sceHttp.HttpRequest>(); private String url; private HttpTemplate httpTemplate; private boolean enableRedirect; public HttpConnection() { id = SceUidManager.getNewUid(uidPurpose); Modules.sceHttpModule.httpConnections.put(id, this); } public void delete() { // Delete all the HttpRequests for (HttpRequest httpRequest : httpRequests.values()) { httpRequest.delete(); } httpRequests.clear(); Modules.sceHttpModule.httpConnections.remove(id); SceUidManager.releaseUid(id, uidPurpose); id = -1; } public void addHttpRequest(HttpRequest httpRequest) { httpRequest.setHttpConnection(this); httpRequests.put(httpRequest.getId(), httpRequest); } public int getId() { return id; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public int getDefaultPort(String protocol) { if ("http".equals(protocol)) { return 80; } if ("https".equals(protocol)) { return 443; } return -1; } public void setUrl(String host, String protocol, int port) { url = String.format("%s://%s", protocol, host); if (port != getDefaultPort(protocol)) { url += String.format(":%s", port); } } public HttpTemplate getHttpTemplate() { return httpTemplate; } public void setHttpTemplate(HttpTemplate httpTemplate) { this.httpTemplate = httpTemplate; } public boolean isEnableRedirect() { return enableRedirect; } public void setEnableRedirect(boolean enableRedirect) { this.enableRedirect = enableRedirect; } @Override public String toString() { return String.format("HttpConnection id=%d, url='%s'", getId(), getUrl()); } } protected static class HttpTemplate { private static final String uidPurpose = "sceHttp-HttpTemplate"; private int id; private HashMap<Integer, HttpConnection> httpConnections = new HashMap<Integer, sceHttp.HttpConnection>(); private String agent; private boolean enableRedirect; public HttpTemplate() { id = SceUidManager.getNewUid(uidPurpose); Modules.sceHttpModule.httpTemplates.put(id, this); } public void delete() { // Delete all the HttpConnections for (HttpConnection httpConnection : httpConnections.values()) { httpConnection.delete(); } httpConnections.clear(); Modules.sceHttpModule.httpTemplates.remove(id); SceUidManager.releaseUid(id, uidPurpose); id = -1; } public void addHttpConnection(HttpConnection httpConnection) { httpConnection.setHttpTemplate(this); httpConnection.setEnableRedirect(isEnableRedirect()); httpConnections.put(httpConnection.getId(), httpConnection); } public int getId() { return id; } public String getAgent() { return agent; } public void setAgent(String agent) { this.agent = agent; } public boolean isEnableRedirect() { return enableRedirect; } public void setEnableRedirect(boolean enableRedirect) { this.enableRedirect = enableRedirect; } @Override public String toString() { return String.format("HttpTemplate id=%d, agent='%s'", getId(), getAgent()); } } @Override public void start() { CookieHandler.setDefault(new ThreadLocalCookieManager()); cookieManager = new CookieManager(); super.start(); } public void checkHttpInit() { if (!isHttpInit) { throw(new SceKernelErrorException(SceKernelErrors.ERROR_HTTP_NOT_INIT)); } } private static Proxy getProxyForUrl(String url) { for (HttpServerConfiguration httpServerConfiguration : HTTPConfiguration.doProxyServers) { if (httpServerConfiguration.isMatchingUrl(url)) { return HTTPServer.getInstance().getProxy(); } } return null; } public static String patchUrl(String url) { for (HttpServerConfiguration httpServerConfiguration : HTTPConfiguration.doProxyServers) { if (httpServerConfiguration.isHttps()) { if (httpServerConfiguration.isMatchingUrl(url)) { // Replace https with http return url.replaceFirst("https", "http"); } } } return url; } protected HttpRequest getHttpRequest(int requestId) { HttpRequest httpRequest = httpRequests.get(requestId); if (httpRequest == null) { throw new SceKernelErrorException(SceKernelErrors.ERROR_INVALID_ARGUMENT); } return httpRequest; } protected HttpConnection getHttpConnection(int connectionId) { HttpConnection httpConnection = httpConnections.get(connectionId); if (httpConnection == null) { throw new SceKernelErrorException(SceKernelErrors.ERROR_INVALID_ARGUMENT); } return httpConnection; } protected boolean isHttpTemplateId(int templateId) { return httpTemplates.containsKey(templateId); } protected HttpTemplate getHttpTemplate(int templateId) { HttpTemplate httpTemplate = httpTemplates.get(templateId); if (httpTemplate == null) { throw new SceKernelErrorException(SceKernelErrors.ERROR_INVALID_ARGUMENT); } return httpTemplate; } private int getTempMemory() { if (memInfo == null) { memInfo = Modules.SysMemUserForUserModule.malloc(SysMemUserForUser.VSHELL_PARTITION_ID, "sceHttp", SysMemUserForUser.PSP_SMEM_Low, maxMemSize, 0); if (memInfo == null) { return 0; } } return memInfo.addr; } /** * Init the http library. * * @param heapSize - Memory pool size? Pass 20000 * @return 0 on success, < 0 on error. */ @HLELogging(level="info") @HLEFunction(nid = 0xAB1ABE07, version = 150, checkInsideInterrupt = true) public int sceHttpInit(int heapSize) { if (isHttpInit) { return SceKernelErrors.ERROR_HTTP_ALREADY_INIT; } maxMemSize = heapSize; isHttpInit = true; memInfo = null; // Allocate memory during sceHttpInit int addr = getTempMemory(); if (addr == 0) { log.warn(String.format("sceHttpInit cannot allocate 0x%X bytes", maxMemSize)); return -1; } Utilities.disableSslCertificateChecks(); return 0; } /** * Terminate the http library. * * @return 0 on success, < 0 on error. */ @HLEUnimplemented @HLEFunction(nid = 0xD1C8945E, version = 150, checkInsideInterrupt = true) public int sceHttpEnd() { checkHttpInit(); isSystemCookieLoaded = false; isHttpInit = false; if (memInfo != null) { Modules.SysMemUserForUserModule.free(memInfo); memInfo = null; } return 0; } /** * Get http request response length. * * @param requestid - ID of the request created by sceHttpCreateRequest or sceHttpCreateRequestWithURL * @param contentlength - The size of the content * @return 0 on success, < 0 on error. */ @HLEUnimplemented @HLEFunction(nid = 0x0282A3BD, version = 150) public int sceHttpGetContentLength(int requestId, @BufferInfo(usage=Usage.out) TPointer64 contentLengthAddr){ HttpRequest httpRequest = getHttpRequest(requestId); httpRequest.connect(); long contentLength = httpRequest.getContentLength(); int result; if (contentLength < 0) { // Value in contentLengthAddr is left unchanged when returning an error, checked on PSP. result = SceKernelErrors.ERROR_HTTP_NO_CONTENT_LENGTH; } else { contentLengthAddr.setValue(contentLength); result = 0; } if (log.isDebugEnabled()) { log.debug(String.format("sceHttpGetContentLength request %s returning 0x%X, contentLength=0x%X", httpRequest, result, contentLengthAddr.getValue())); } return result; } /** * Set resolver retry * * @param id - ID of the template or connection * @param count - Number of retries * @return 0 on success, < 0 on error. */ @HLEUnimplemented @HLEFunction(nid = 0x03D9526F, version = 150) public int sceHttpSetResolveRetry(int templateId, int count) { return 0; } @HLEUnimplemented @HLEFunction(nid = 0x06488A1C, version = 150) public int sceHttpSetCookieSendCallback() { return 0; } /** * Enable redirect * * @param id - ID of the template or connection * @return 0 on success, < 0 on error. */ @HLEUnimplemented @HLEFunction(nid = 0x0809C831, version = 150) public int sceHttpEnableRedirect(int id) { if (isHttpTemplateId(id)) { HttpTemplate httpTemplate = getHttpTemplate(id); httpTemplate.setEnableRedirect(true); } else { HttpConnection httpConnection = getHttpConnection(id); httpConnection.setEnableRedirect(true); } return 0; } /** * Disable cookie * * @param id - ID of the template or connection * @return 0 on success, < 0 on error. */ @HLEUnimplemented @HLEFunction(nid = 0x0B12ABFB, version = 150) public int sceHttpDisableCookie(int templateId) { return 0; } /** * Enable cookie * * @param id - ID of the template or connection * @return 0 on success, < 0 on error. */ @HLEUnimplemented @HLEFunction(nid = 0x0DAFA58F, version = 150) public int sceHttpEnableCookie(int templateId) { return 0; } /** * Delete content header * * @param id - ID of the template, connection or request * @param name - Name of the content * @return 0 on success, < 0 on error. */ @HLEUnimplemented @HLEFunction(nid = 0x15540184, version = 150) public int sceHttpDeleteHeader(int templateId, int name) { return 0; } /** * Disable redirect * * @param id - ID of the template or connection * @return 0 on success, < 0 on error. */ @HLEUnimplemented @HLEFunction(nid = 0x1A0EBB69, version = 150) public int sceHttpDisableRedirect(int id) { if (isHttpTemplateId(id)) { HttpTemplate httpTemplate = getHttpTemplate(id); httpTemplate.setEnableRedirect(false); } else { HttpConnection httpConnection = getHttpConnection(id); httpConnection.setEnableRedirect(false); } return 0; } @HLEUnimplemented @HLEFunction(nid = 0x1CEDB9D4, version = 150) public int sceHttpFlushCache() { return 0; } /** * Set receive timeout * * @param id - ID of the template or connection * @param timeout - Timeout value in microseconds * @return 0 on success, < 0 on error. */ @HLEUnimplemented @HLEFunction(nid = 0x1F0FC3E3, version = 150) public int sceHttpSetRecvTimeOut(int templateId, int timeout) { return 0; } @HLEUnimplemented @HLEFunction(nid = 0x2255551E, version = 150) public int sceHttpGetNetworkPspError(int connectionId, TPointer32 errorAddr) { errorAddr.setValue(0); return 0; } @HLEUnimplemented @HLEFunction(nid = 0x267618F4, version = 150) public int sceHttpSetAuthInfoCallback(int templateId, TPointer callback, int callbackArg) { return 0; } @HLEUnimplemented @HLEFunction(nid = 0x2A6C3296, version = 150) public int sceHttpSetAuthInfoCB() { return 0; } @HLEUnimplemented @HLEFunction(nid = 0x2C3C82CF, version = 150) public int sceHttpFlushAuthList() { return 0; } @HLEUnimplemented @HLEFunction(nid = 0x3A67F306, version = 150) public int sceHttpSetCookieRecvCallback() { return 0; } /** * Add content header * * @param id - ID of the template, connection or request * @param name - Name of the content * @param value - Value of the content * @param unknown1 - Pass 0 * @return 0 on success, < 0 on error. */ @HLEUnimplemented @HLEFunction(nid = 0x3EABA285, version = 150) public int sceHttpAddExtraHeader(int requestId, PspString name, PspString value, int unknown1) { HttpRequest httpRequest = getHttpRequest(requestId); httpRequest.addHeader(name.getString(), value.getString()); return 0; } /** * Create a http request. * * @param connectionid - ID of the connection created by sceHttpCreateConnection or sceHttpCreateConnectionWithURL * @param method - One of ::PspHttpMethod * @param path - Path to access * @param contentlength - Length of the content (POST method only) * @return A request ID on success, < 0 on error. */ @HLEUnimplemented @HLEFunction(nid = 0x47347B50, version = 150) public int sceHttpCreateRequest(int connectionId, int method, PspString path, long contentLength) { HttpConnection httpConnection = getHttpConnection(connectionId); HttpRequest httpRequest = new HttpRequest(); httpRequest.setMethod(method); httpRequest.setPath(path.getString()); httpRequest.setContentLength(contentLength); httpConnection.addHttpRequest(httpRequest); return httpRequest.getId(); } /** * Set resolver timeout * * @param id - ID of the template or connection * @param timeout - Timeout value in microseconds * @return 0 on success, < 0 on error. */ @HLEUnimplemented @HLEFunction(nid = 0x47940436, version = 150) public int sceHttpSetResolveTimeOut(int templateId, int timeout) { return 0; } /** * Get http request status code. * * @param requestid - ID of the request created by sceHttpCreateRequest or sceHttpCreateRequestWithURL * @param statuscode - The status code from the host (200 is ok, 404 is not found etc) * @return 0 on success, < 0 on error. */ @HLEUnimplemented @HLEFunction(nid = 0x4CC7D78F, version = 150) public int sceHttpGetStatusCode(int requestId, @BufferInfo(usage=Usage.out) TPointer32 statusCode) { HttpRequest httpRequest = getHttpRequest(requestId); httpRequest.connect(); statusCode.setValue(httpRequest.getStatusCode()); if (log.isDebugEnabled()) { log.debug(String.format("sceHttpGetStatusCode on request %s returning statusCode=%d", httpRequest, statusCode.getValue())); } return 0; } /** * Delete a http connection. * * @param connectionid - ID of the connection created by sceHttpCreateConnection or sceHttpCreateConnectionWithURL * @return 0 on success, < 0 on error. */ @HLEUnimplemented @HLEFunction(nid = 0x5152773B, version = 150) public int sceHttpDeleteConnection(int connectionId) { return 0; } @HLEUnimplemented @HLEFunction(nid = 0x54E7DF75, version = 150) public int sceHttpIsRequestInCache(int requestId, int unknown1, int unknown2) { return 0; } @HLEUnimplemented @HLEFunction(nid = 0x59E6D16F, version = 150) public int sceHttpEnableCache(int templateId) { return 0; } /** * Save cookie * * @return 0 on success, < 0 on error. */ @HLEUnimplemented @HLEFunction(nid = 0x76D1363B, version = 150, checkInsideInterrupt = true) public int sceHttpSaveSystemCookie() { checkHttpInit(); if (!isSystemCookieLoaded){ return SceKernelErrors.ERROR_HTTP_SYSTEM_COOKIE_NOT_LOADED; } return 0; } @HLEUnimplemented @HLEFunction(nid = 0x7774BF4C, version = 150) public int sceHttpAddCookie(PspString url, @BufferInfo(lengthInfo=LengthInfo.nextParameter, usage=Usage.in) TPointer cookieAddr, int length) { String cookie = cookieAddr.getStringNZ(length); if (log.isDebugEnabled()) { log.debug(String.format("sceHttpAddCookie for URL '%s': '%s'", url.getString(), cookie)); } return 0; } @HLEUnimplemented @HLEFunction(nid = 0x77EE5319, version = 150) public int sceHttpLoadAuthList() { return 0; } /** * Enable keep alive * * @param id - ID of the template or connection * @return 0 on success, < 0 on error. */ @HLEUnimplemented @HLEFunction(nid = 0x78A0D3EC, version = 150) public int sceHttpEnableKeepAlive(int templateId) { return 0; } @HLEUnimplemented @HLEFunction(nid = 0x78B54C09, version = 150) public int sceHttpEndCache() { return 0; } /** * Set connect timeout * * @param id - ID of the template, connection or request * @param timeout - Timeout value in microseconds * @return 0 on success, < 0 on error. */ @HLEUnimplemented @HLEFunction(nid = 0x8ACD1F73, version = 150) public int sceHttpSetConnectTimeOut(int templateId, int timeout) { return 0; } /** * Create a http connection. * * @param templateid - ID of the template created by sceHttpCreateTemplate * @param host - Host to connect to * @param protocol - Pass "http" * @param port - Port to connect on * @param unknown1 - Pass 0 * @return A connection ID on success, < 0 on error. */ @HLEUnimplemented @HLEFunction(nid = 0x8EEFD953, version = 150) public int sceHttpCreateConnection(int templateId, PspString host, PspString protocol, int port, int unknown1) { HttpTemplate httpTemplate = getHttpTemplate(templateId); HttpConnection httpConnection = new HttpConnection(); httpConnection.setUrl(host.getString(), protocol.getString(), port); httpTemplate.addHttpConnection(httpConnection); return httpConnection.getId(); } @HLEUnimplemented @HLEFunction(nid = 0x951D310E, version = 150) public int sceHttpDisableProxyAuth() { return 0; } @HLEUnimplemented @HLEFunction(nid = 0x9668864C, version = 150) public int sceHttpSetRecvBlockSize() { return 0; } @HLEUnimplemented @HLEFunction(nid = 0x96F16D3E, version = 150) public int sceHttpGetCookie(PspString url, @BufferInfo(lengthInfo=LengthInfo.nextNextParameter, usage=Usage.out) TPointer cookie, @CanBeNull @BufferInfo(usage=Usage.out) TPointer32 cookieLengthAddr, int prepare, int secure) { return SceKernelErrors.ERROR_HTTP_NOT_FOUND; } /** * Set send timeout * * @param id - ID of the template, connection or request * @param timeout - Timeout value in microseconds * @return 0 on success, < 0 on error. */ @HLEUnimplemented @HLEFunction(nid = 0x9988172D, version = 150) public int sceHttpSetSendTimeOut(int templateId, int timeout) { return 0; } @HLEUnimplemented @HLEFunction(nid = 0x9AFC98B2, version = 150) public int sceHttpSendRequestInCacheFirstMode() { return 0; } /** * Create a http template. * * @param agent - User agent * @param unknown1 - Pass 1 * @param unknown2 - Pass 0 * @return A template ID on success, < 0 on error. */ @HLEUnimplemented @HLEFunction(nid = 0x9B1F1F36, version = 150) public int sceHttpCreateTemplate(PspString agent, int unknown1, int unknown2) { HttpTemplate httpTemplate = new HttpTemplate(); httpTemplate.setAgent(agent.getString()); return httpTemplate.getId(); } @HLEUnimplemented @HLEFunction(nid = 0x9FC5F10D, version = 150) public int sceHttpEnableAuth(int templateId) { return 0; } @HLEUnimplemented @HLEFunction(nid = 0xA4496DE5, version = 150) public int sceHttpSetRedirectCallback(int templateId, @CanBeNull TPointer callbackAddr, int callbackArg) { return 0; } /** * Delete a http request. * * @param requestid - ID of the request created by sceHttpCreateRequest or sceHttpCreateRequestWithURL * @return 0 on success, < 0 on error. */ @HLEUnimplemented @HLEFunction(nid = 0xA5512E01, version = 150) public int sceHttpDeleteRequest(int requestId) { return 0; } @HLEUnimplemented @HLEFunction(nid = 0xA6800C34, version = 150) public int sceHttpInitCache() { return 0; } @HLEUnimplemented @HLEFunction(nid = 0xAE948FEE, version = 150) public int sceHttpDisableAuth(int templateId) { return 0; } @HLEUnimplemented @HLEFunction(nid = 0xB0C34B1D, version = 150) public int sceHttpSetCacheContentLengthMaxSize() { return 0; } /** * Create a http request with url. * * @param connectionid - ID of the connection created by sceHttpCreateConnection or sceHttpCreateConnectionWithURL * @param method - One of ::PspHttpMethod * @param url - url to access * @param contentlength - Length of the content (POST method only) * @return A request ID on success, < 0 on error. */ @HLEUnimplemented @HLEFunction(nid = 0xB509B09E, version = 150) public int sceHttpCreateRequestWithURL(int connectionId, int method, PspString url, long contentLength) { HttpConnection httpConnection = getHttpConnection(connectionId); HttpRequest httpRequest = new HttpRequest(); httpRequest.setMethod(method); httpRequest.setUrl(url.getString()); httpRequest.setContentLength(contentLength); httpConnection.addHttpRequest(httpRequest); return httpRequest.getId(); } /** * Send a http request. * * @param requestid - ID of the request created by sceHttpCreateRequest or sceHttpCreateRequestWithURL * @param data - For POST methods specify a pointer to the post data, otherwise pass NULL * @param datasize - For POST methods specify the size of the post data, otherwise pass 0 * @return 0 on success, < 0 on error. */ @HLEUnimplemented @HLEFunction(nid = 0xBB70706F, version = 150) public int sceHttpSendRequest(int requestId, @CanBeNull @BufferInfo(lengthInfo=LengthInfo.nextParameter, usage=Usage.in) TPointer data, int dataSize) { HttpRequest httpRequest = getHttpRequest(requestId); httpRequest.send(data.getAddress(), dataSize); return 0; } /** * Abort a http request. * * @param requestid - ID of the request created by sceHttpCreateRequest or sceHttpCreateRequestWithURL * @return 0 on success, < 0 on error. */ @HLEUnimplemented @HLEFunction(nid = 0xC10B6BD9, version = 150) public int sceHttpAbortRequest(int requestId) { return 0; } @HLEUnimplemented @HLEFunction(nid = 0xC6330B0D, version = 150) public int sceHttpChangeHttpVersion() { return 0; } /** * Disable keep alive * * @param id - ID of the template or connection * @return 0 on success, < 0 on error. */ @HLEUnimplemented @HLEFunction(nid = 0xC7EF2559, version = 150) public int sceHttpDisableKeepAlive(int templateId) { return 0; } @HLEUnimplemented @HLEFunction(nid = 0xC98CBBA7, version = 150) public int sceHttpSetResHeaderMaxSize() { return 0; } @HLEUnimplemented @HLEFunction(nid = 0xCCBD167A, version = 150) public int sceHttpDisableCache(int templateId) { return 0; } @HLEUnimplemented @HLEFunction(nid = 0xCDB0DC58, version = 150) public int sceHttpEnableProxyAuth() { return 0; } /** * Create a http connection to a url. * * @param templateid - ID of the template created by sceHttpCreateTemplate * @param url - url to connect to * @param unknown1 - Pass 0 * @return A connection ID on success, < 0 on error. */ @HLEUnimplemented @HLEFunction(nid = 0xCDF8ECB9, version = 150) public int sceHttpCreateConnectionWithURL(int templateId, PspString url, int unknown1) { HttpTemplate httpTemplate = getHttpTemplate(templateId); HttpConnection httpConnection = new HttpConnection(); httpConnection.setUrl(url.getString()); httpTemplate.addHttpConnection(httpConnection); return httpConnection.getId(); } @HLEUnimplemented @HLEFunction(nid = 0xD081EC8F, version = 150) public int sceHttpGetNetworkErrno(int requestId, TPointer32 errno) { errno.setValue(0); return 0; } @HLEUnimplemented @HLEFunction(nid = 0xD70D4847, version = 150) public int sceHttpGetProxy() { return 0; } @HLEUnimplemented @HLEFunction(nid = 0xDB266CCF, version = 150) public int sceHttpGetAllHeader(int requestId, @BufferInfo(usage=Usage.out) TPointer32 headerAddr, @BufferInfo(usage=Usage.out) TPointer32 headerLengthAddr) { HttpRequest httpRequest = getHttpRequest(requestId); httpRequest.connect(); String allHeaders = httpRequest.getAllHeaders(); if (allHeaders == null) { return -1; } int addr = getTempMemory(); Utilities.writeStringZ(Memory.getInstance(), addr, allHeaders); headerAddr.setValue(addr); headerLengthAddr.setValue(allHeaders.length()); if (log.isDebugEnabled()) { log.debug(String.format("sceHttpGetAllHeader returning at 0x%08X: %s", addr, Utilities.getMemoryDump(addr, headerLengthAddr.getValue()))); } return 0; } @HLEUnimplemented @HLEFunction(nid = 0xDD6E7857, version = 150) public int sceHttpSaveAuthList() { return 0; } /** * Read a http request response. * * @param requestid - ID of the request created by sceHttpCreateRequest or sceHttpCreateRequestWithURL * @param data - Buffer for the response data to be stored * @param datasize - Size of the buffer * @return The size read into the data buffer, 0 if there is no more data, < 0 on error. */ @HLEUnimplemented @HLEFunction(nid = 0xEDEEB999, version = 150) public int sceHttpReadData(int requestId, @BufferInfo(lengthInfo=LengthInfo.returnValue, usage=Usage.out) TPointer data, int dataSize) { HttpRequest httpRequest = getHttpRequest(requestId); httpRequest.connect(); int readSize = httpRequest.readData(data.getAddress(), dataSize); if (log.isDebugEnabled()) { log.debug(String.format("sceHttpReadData returning 0x%X: %s", readSize, Utilities.getMemoryDump(data.getAddress(), readSize))); } return readSize; } @HLEUnimplemented @HLEFunction(nid = 0xF0F46C62, version = 150) public int sceHttpSetProxy() { return 0; } /** * Load cookie * * @return 0 on success, < 0 on error. */ @HLEUnimplemented @HLEFunction(nid = 0xF1657B22, version = 150, checkInsideInterrupt = true) public int sceHttpLoadSystemCookie() { checkHttpInit(); if (isSystemCookieLoaded) { // The system's cookie list can only be loaded once per session. return SceKernelErrors.ERROR_HTTP_ALREADY_INIT; } else if (maxMemSize < PSP_HTTP_SYSTEM_COOKIE_HEAP_SIZE){ return SceKernelErrors.ERROR_HTTP_NO_MEMORY; } else { isSystemCookieLoaded = true; return 0; } } @HLEUnimplemented @HLEFunction(nid = 0xF49934F6, version = 150) public int sceHttpSetMallocFunction(TPointer function1, TPointer function2, TPointer function3) { return 0; } /** * Delete a http template. * * @param templateid - ID of the template created by sceHttpCreateTemplate * @return 0 on success, < 0 on error. */ @HLEUnimplemented @HLEFunction(nid = 0xFCF8C055, version = 150) public int sceHttpDeleteTemplate(int templateId) { return 0; } @HLEUnimplemented @HLEFunction(nid = 0x87F1E666, version = 150) public int sceHttp_87F1E666(int templateId, int unknown) { return 0; } @HLEUnimplemented @HLEFunction(nid = 0x3C478044, version = 150) public int sceHttp_3C478044(int templateId, int unknown) { return 0; } @HLEUnimplemented @HLEFunction(nid = 0x739C2D79, version = 150) public int sceHttpInitExternalCache() { return 0; } @HLEUnimplemented @HLEFunction(nid = 0xA461A167, version = 150) public int sceHttpEndExternalCache() { return 0; } @HLEUnimplemented @HLEFunction(nid = 0x8046E250, version = 150) public int sceHttpEnableExternalCache() { return 0; } @HLEUnimplemented @HLEFunction(nid = 0xB0257723, version = 150) public int sceHttpFlushExternalCache() { return 0; } @HLEUnimplemented @HLEFunction(nid = 0x457D221D, version = 150) public int sceHttpFlushCookie() { return 0; } @HLEUnimplemented @HLEFunction(nid = 0x4E4A284A, version = 150) public int sceHttpCloneTemplate(int templateId) { HttpTemplate clonedHttpTemplate = new HttpTemplate(); HttpTemplate httpTemplate = getHttpTemplate(templateId); clonedHttpTemplate.setAgent(httpTemplate.getAgent()); return clonedHttpTemplate.getId(); } @HLEUnimplemented @HLEFunction(nid = 0xD80BE761, version = 150) public int sceHttp_D80BE761(int templateId) { return 0; } @HLEUnimplemented @HLEFunction(nid = 0xA909F2AE, version = 150) public int sceHttp_A909F2AE1() { return 0; } }