network/sockets/source/sockets.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <errno.h>
#include <stdarg.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <3ds.h>
#define SOC_ALIGN 0x1000
#define SOC_BUFFERSIZE 0x100000
static u32 *SOC_buffer = NULL;
s32 sock = -1, csock = -1;
__attribute__((format(printf,1,2)))
void failExit(const char *fmt, ...);
const static char http_200[] = "HTTP/1.1 200 OK\r\n";
const static char indexdata[] = "<html> \
<head><title>A test page</title></head> \
<body> \
This small test page has had %d hits. \
</body> \
</html>";
const static char http_html_hdr[] = "Content-type: text/html\r\n\r\n";
const static char http_get_index[] = "GET / HTTP/1.1\r\n";
//---------------------------------------------------------------------------------
void socShutdown() {
//---------------------------------------------------------------------------------
printf("waiting for socExit...\n");
socExit();
}
//---------------------------------------------------------------------------------
int main(int argc, char **argv) {
//---------------------------------------------------------------------------------
int ret;
u32 clientlen;
struct sockaddr_in client;
struct sockaddr_in server;
char temp[1026];
static int hits=0;
gfxInitDefault();
// register gfxExit to be run when app quits
// this can help simplify error handling
atexit(gfxExit);
consoleInit(GFX_TOP, NULL);
printf ("\nlibctru sockets demo\n");
// allocate buffer for SOC service
SOC_buffer = (u32*)memalign(SOC_ALIGN, SOC_BUFFERSIZE);
if(SOC_buffer == NULL) {
failExit("memalign: failed to allocate\n");
}
// Now intialise soc:u service
if ((ret = socInit(SOC_buffer, SOC_BUFFERSIZE)) != 0) {
failExit("socInit: 0x%08X\n", (unsigned int)ret);
}
// register socShutdown to run at exit
// atexit functions execute in reverse order so this runs before gfxExit
atexit(socShutdown);
// libctru provides BSD sockets so most code from here is standard
clientlen = sizeof(client);
sock = socket (AF_INET, SOCK_STREAM, IPPROTO_IP);
if (sock < 0) {
failExit("socket: %d %s\n", errno, strerror(errno));
}
memset (&server, 0, sizeof (server));
memset (&client, 0, sizeof (client));
server.sin_family = AF_INET;
server.sin_port = htons (80);
server.sin_addr.s_addr = gethostid();
printf("Point your browser to http://%s/\n",inet_ntoa(server.sin_addr));
if ( (ret = bind (sock, (struct sockaddr *) &server, sizeof (server))) ) {
close(sock);
failExit("bind: %d %s\n", errno, strerror(errno));
}
// Set socket non blocking so we can still read input to exit
fcntl(sock, F_SETFL, fcntl(sock, F_GETFL, 0) | O_NONBLOCK);
if ( (ret = listen( sock, 5)) ) {
failExit("listen: %d %s\n", errno, strerror(errno));
}
while (aptMainLoop()) {
gspWaitForVBlank();
hidScanInput();
csock = accept (sock, (struct sockaddr *) &client, &clientlen);
if (csock<0) {
if(errno != EAGAIN) {
failExit("accept: %d %s\n", errno, strerror(errno));
}
} else {
// set client socket to blocking to simplify sending data back
fcntl(csock, F_SETFL, fcntl(csock, F_GETFL, 0) & ~O_NONBLOCK);
printf("Connecting port %d from %s\n", client.sin_port, inet_ntoa(client.sin_addr));
memset (temp, 0, 1026);
ret = recv (csock, temp, 1024, 0);
if ( !strncmp( temp, http_get_index, strlen(http_get_index) ) ) {
hits++;
send(csock, http_200, strlen(http_200),0);
send(csock, http_html_hdr, strlen(http_html_hdr),0);
sprintf(temp, indexdata, hits);
send(csock, temp, strlen(temp),0);
}
close (csock);
csock = -1;
}
u32 kDown = hidKeysDown();
if (kDown & KEY_START) break;
}
close(sock);
return 0;
}
//---------------------------------------------------------------------------------
void failExit(const char *fmt, ...) {
//---------------------------------------------------------------------------------
if(sock>0) close(sock);
if(csock>0) close(csock);
va_list ap;
printf(CONSOLE_RED);
va_start(ap, fmt);
vprintf(fmt, ap);
va_end(ap);
printf(CONSOLE_RESET);
printf("\nPress B to exit\n");
while (aptMainLoop()) {
gspWaitForVBlank();
hidScanInput();
u32 kDown = hidKeysDown();
if (kDown & KEY_B) exit(0);
}
}
3ds.h
Central 3DS header.
aptMainLoop
bool aptMainLoop(void)
Main function which handles sleep mode and HOME/power buttons - call this at the beginning of every f...
consoleInit
PrintConsole * consoleInit(gfxScreen_t screen, PrintConsole *console)
Initialise the console.
gfxInitDefault
void gfxInitDefault(void)
Initializes the LCD framebuffers with default parameters This is equivalent to calling:
GFX_TOP
@ GFX_TOP
Top screen.
Definition: gfx.h:26
gfxExit
void gfxExit(void)
Deinitializes and frees the LCD framebuffers.
gspWaitForVBlank
#define gspWaitForVBlank()
Waits for VBlank.
Definition: gspgpu.h:151
KEY_B
@ KEY_B
B.
Definition: hid.h:13
KEY_START
@ KEY_START
Start.
Definition: hid.h:15
hidKeysDown
u32 hidKeysDown(void)
Returns a bitmask of newly pressed buttons, this frame.
hidScanInput
void hidScanInput(void)
Scans HID for input data.
__attribute__
__attribute__((warn_unused_result)) rbtree_node_t *rbtree_insert(rbtree_t *tree
Inserts a node into an rbtree.
socInit
Result socInit(u32 *context_addr, u32 context_size)
Initializes the SOC service.
socExit
Result socExit(void)
Closes the soc service.
gethostid
long gethostid(void)
Gets the system's host ID.
sockaddr_in
Definition: in.h:34
sockaddr
Definition: socket.h:52
s32
int32_t s32
32-bit signed integer
Definition: types.h:28
u32
uint32_t u32
32-bit unsigned integer
Definition: types.h:23