diff --git a/libctru/include/3ds/services/httpc.h b/libctru/include/3ds/services/httpc.h index c49069b..847779d 100644 --- a/libctru/include/3ds/services/httpc.h +++ b/libctru/include/3ds/services/httpc.h @@ -31,8 +31,8 @@ typedef enum { // Result code returned when asked about a non-existing header #define HTTPC_RESULTCODE_NOTFOUND 0xd840a028 -/// Initializes HTTPC. -Result httpcInit(void); +/// Initializes HTTPC. For HTTP GET the sharedmem_size can be zero. The sharedmem contains data which will be later uploaded for HTTP POST. sharedmem_size should be aligned to 0x1000-bytes. +Result httpcInit(u32 sharedmem_size); /// Exits HTTPC. void httpcExit(void); @@ -59,6 +59,14 @@ Result httpcCloseContext(httpcContext *context); */ Result httpcAddRequestHeaderField(httpcContext *context, char* name, char* value); +/** + * @brief Adds a POST form field to a HTTP context. + * @param context Context to use. + * @param name Name of the field. + * @param value Value of the field. + */ +Result httpcAddPostDataAscii(httpcContext *context, char* name, char* value); + /** * @brief Begins a HTTP request. * @param context Context to use. @@ -121,7 +129,7 @@ Result httpcDownloadData(httpcContext *context, u8* buffer, u32 size, u32 *downl * @brief Initializes HTTPC. * @param handle HTTPC service handle to use. */ -Result HTTPC_Initialize(Handle handle); +Result HTTPC_Initialize(Handle handle, u32 sharedmem_size, Handle sharedmem_handle); /** * @brief Initializes a HTTP connection session. @@ -161,6 +169,15 @@ Result HTTPC_SetProxyDefault(Handle handle, Handle contextHandle); */ Result HTTPC_AddRequestHeaderField(Handle handle, Handle contextHandle, char* name, char* value); +/** + * @brief Adds a POST form field to a HTTP context. + * @param handle HTTPC service handle to use. + * @param contextHandle HTTP context handle to use. + * @param name Name of the field. + * @param value of the field. + */ +Result HTTPC_AddPostDataAscii(Handle handle, Handle contextHandle, char* name, char* value); + /** * @brief Begins a HTTP request. * @param handle HTTPC service handle to use. diff --git a/libctru/source/services/httpc.c b/libctru/source/services/httpc.c index ec979fa..9c0a750 100644 --- a/libctru/source/services/httpc.c +++ b/libctru/source/services/httpc.c @@ -1,4 +1,6 @@ #include +#include +#include #include <3ds/types.h> #include <3ds/result.h> #include <3ds/svc.h> @@ -10,7 +12,11 @@ Handle __httpc_servhandle; static int __httpc_refcount; -Result httpcInit(void) +u32 *__httpc_sharedmem_addr; +static u32 __httpc_sharedmem_size; +static Handle __httpc_sharedmem_handle; + +Result httpcInit(u32 sharedmem_size) { Result ret=0; @@ -19,11 +25,32 @@ Result httpcInit(void) ret = srvGetServiceHandle(&__httpc_servhandle, "http:C"); if (R_SUCCEEDED(ret)) { - ret = HTTPC_Initialize(__httpc_servhandle); + __httpc_sharedmem_size = sharedmem_size; + __httpc_sharedmem_handle = 0; + + if(__httpc_sharedmem_size) + { + __httpc_sharedmem_addr = memalign(0x1000, __httpc_sharedmem_size); + if(__httpc_sharedmem_addr==NULL)ret = -1; + + if (R_SUCCEEDED(ret))ret = svcCreateMemoryBlock(&__httpc_sharedmem_handle, (u32)__httpc_sharedmem_addr, __httpc_sharedmem_size, 0, 3); + } + + if (R_SUCCEEDED(ret))ret = HTTPC_Initialize(__httpc_servhandle, __httpc_sharedmem_size, __httpc_sharedmem_handle); if (R_FAILED(ret)) svcCloseHandle(__httpc_servhandle); } if (R_FAILED(ret)) AtomicDecrement(&__httpc_refcount); + if (R_FAILED(ret) && __httpc_sharedmem_handle) + { + svcCloseHandle(__httpc_sharedmem_handle); + __httpc_sharedmem_handle = 0; + __httpc_sharedmem_size = 0; + + free(__httpc_sharedmem_addr); + __httpc_sharedmem_addr = NULL; + } + return ret; } @@ -31,6 +58,16 @@ void httpcExit(void) { if (AtomicDecrement(&__httpc_refcount)) return; svcCloseHandle(__httpc_servhandle); + + if(__httpc_sharedmem_handle) + { + svcCloseHandle(__httpc_sharedmem_handle); + __httpc_sharedmem_handle = 0; + __httpc_sharedmem_size = 0; + + free(__httpc_sharedmem_addr); + __httpc_sharedmem_addr = NULL; + } } Result httpcOpenContext(httpcContext *context, HTTPC_RequestMethod method, char* url, u32 use_defaultproxy) @@ -80,6 +117,11 @@ Result httpcAddRequestHeaderField(httpcContext *context, char* name, char* value return HTTPC_AddRequestHeaderField(context->servhandle, context->httphandle, name, value); } +Result httpcAddPostDataAscii(httpcContext *context, char* name, char* value) +{ + return HTTPC_AddPostDataAscii(context->servhandle, context->httphandle, name, value); +} + Result httpcBeginRequest(httpcContext *context) { return HTTPC_BeginRequest(context->servhandle, context->httphandle); @@ -140,15 +182,15 @@ Result httpcDownloadData(httpcContext *context, u8* buffer, u32 size, u32 *downl return dlret; } -Result HTTPC_Initialize(Handle handle) +Result HTTPC_Initialize(Handle handle, u32 sharedmem_size, Handle sharedmem_handle) { u32* cmdbuf=getThreadCommandBuffer(); cmdbuf[0]=IPC_MakeHeader(0x1,1,4); // 0x10044 - cmdbuf[1]=0x1000; // POST buffer size (page aligned) + cmdbuf[1]=sharedmem_size; // POST buffer size (page aligned) cmdbuf[2]=IPC_Desc_CurProcessHandle(); cmdbuf[4]=IPC_Desc_SharedHandles(1); - cmdbuf[5]=0;// POST buffer memory block handle + cmdbuf[5]=sharedmem_handle;// POST buffer memory block handle Result ret=0; if(R_FAILED(ret=svcSendSyncRequest(handle)))return ret; @@ -237,6 +279,28 @@ Result HTTPC_AddRequestHeaderField(Handle handle, Handle contextHandle, char* na return cmdbuf[1]; } +Result HTTPC_AddPostDataAscii(Handle handle, Handle contextHandle, char* name, char* value) +{ + u32* cmdbuf=getThreadCommandBuffer(); + + int name_len=strlen(name)+1; + int value_len=strlen(value)+1; + + cmdbuf[0]=IPC_MakeHeader(0x12,3,4); // 0x1200C4 + cmdbuf[1]=contextHandle; + cmdbuf[2]=name_len; + cmdbuf[3]=value_len; + cmdbuf[4]=IPC_Desc_StaticBuffer(name_len,3); + cmdbuf[5]=(u32)name; + cmdbuf[6]=IPC_Desc_Buffer(value_len,IPC_BUFFER_R); + cmdbuf[7]=(u32)value; + + Result ret=0; + if(R_FAILED(ret=svcSendSyncRequest(handle)))return ret; + + return cmdbuf[1]; +} + Result HTTPC_BeginRequest(Handle handle, Handle contextHandle) { u32* cmdbuf=getThreadCommandBuffer();