summaryrefslogtreecommitdiff
path: root/packaging/nacl/ports/sdl-net/nacl.patch
diff options
context:
space:
mode:
authorAndrei Karas <akaras@inbox.ru>2015-12-19 14:23:52 +0300
committerAndrei Karas <akaras@inbox.ru>2015-12-19 14:23:52 +0300
commitd3fe6cbd77ac51c6d62ac6fffaf72a7825e7f853 (patch)
tree2e3d31568a5cf4f56e9da81e7954b56d3eadbdda /packaging/nacl/ports/sdl-net/nacl.patch
parentbc28a803b641cb7b33829a6bfd5f9a704cf21fbe (diff)
downloadmanaplus-d3fe6cbd77ac51c6d62ac6fffaf72a7825e7f853.tar.gz
manaplus-d3fe6cbd77ac51c6d62ac6fffaf72a7825e7f853.tar.bz2
manaplus-d3fe6cbd77ac51c6d62ac6fffaf72a7825e7f853.tar.xz
manaplus-d3fe6cbd77ac51c6d62ac6fffaf72a7825e7f853.zip
Update nacl ports.
Diffstat (limited to 'packaging/nacl/ports/sdl-net/nacl.patch')
-rw-r--r--packaging/nacl/ports/sdl-net/nacl.patch1813
1 files changed, 1576 insertions, 237 deletions
diff --git a/packaging/nacl/ports/sdl-net/nacl.patch b/packaging/nacl/ports/sdl-net/nacl.patch
index 8d7fd7e52..f07fdcffd 100644
--- a/packaging/nacl/ports/sdl-net/nacl.patch
+++ b/packaging/nacl/ports/sdl-net/nacl.patch
@@ -1,251 +1,1590 @@
-diff -urN SDL_net-1.2.7/SDL_net.h SDL_net-1.2.7-nacl/SDL_net.h
---- SDL_net-1.2.7/SDL_net.h 2007-07-15 09:59:03.000000000 +0400
-+++ SDL_net-1.2.7-nacl/SDL_net.h 2013-11-03 00:01:10.871933000 +0400
-@@ -30,7 +30,7 @@
- #include "SDL_version.h"
- #include "begin_code.h"
+diff -Naur a/Makefile.am b/Makefile.am
+--- a/Makefile.am 2007-07-21 09:26:47.000000000 +0400
++++ b/Makefile.am 2015-11-28 01:09:05.901015000 +0300
+@@ -8,7 +8,7 @@
+ libSDL_net_la_SOURCES = \
+ SDLnet.c \
+- SDLnetTCP.c \
++ SDLnetTCP.cpp \
+ SDLnetUDP.c \
+ SDLnetselect.c \
+ SDLnetsys.h
+diff -Naur a/Makefile.in b/Makefile.in
+--- a/Makefile.in 2007-07-21 11:55:27.000000000 +0400
++++ b/Makefile.in 2015-11-28 01:09:18.049151000 +0300
+@@ -244,7 +244,7 @@
+
+ libSDL_net_la_SOURCES = \
+ SDLnet.c \
+- SDLnetTCP.c \
++ SDLnetTCP.cpp \
+ SDLnetUDP.c \
+ SDLnetselect.c \
+ SDLnetsys.h
+diff -Naur a/SDLnetselect.c b/SDLnetselect.c
+--- a/SDLnetselect.c 2007-07-02 06:04:03.000000000 +0400
++++ b/SDLnetselect.c 2015-11-30 00:33:29.895731000 +0300
+@@ -111,109 +111,24 @@
+ first. This function returns the number of sockets ready for reading,
+ or -1 if there was an error with the select() system call.
+ */
+-#ifdef MACOS_OPENTRANSPORT
+-int SDLNet_CheckSockets(SDLNet_SocketSet set, Uint32 timeout)
+-{
+-Uint32 stop;
+-int numReady;
+-
+- /* Loop, polling the network devices */
+-
+- stop = SDL_GetTicks() + timeout;
+-
+- do
+- {
+- OTResult status;
+- size_t numBytes;
+- int i;
+-
+- numReady = 0;
+-
+- for (i = set->numsockets-1;i >= 0;--i)
+- {
+- status = OTLook( set->sockets[i]->channel );
+- if( status > 0 )
+- {
+- switch( status )
+- {
+- case T_UDERR:
+- OTRcvUDErr( set->sockets[i]->channel , nil);
+- break;
+- case T_DISCONNECT:
+- OTRcvDisconnect( set->sockets[i]->channel, nil );
+- break;
+- case T_ORDREL:
+- OTRcvOrderlyDisconnect(set->sockets[i]->channel );
+- break;
+- case T_CONNECT:
+- OTRcvConnect( set->sockets[i]->channel, nil );
+- break;
+-
+-
+- default:
+- set->sockets[i]->ready = 1;
+- ++numReady;
+- }
+- }
+- else if( OTCountDataBytes(set->sockets[i]->channel, &numBytes ) != kOTNoDataErr )
+- {
+- set->sockets[i]->ready = 1;
+- ++numReady;
+- }
+- else
+- set->sockets[i]->ready = 0;
+- }
+-
+- } while (!numReady && (SDL_GetTicks() < stop));
+
+- return(numReady);
+-}
+-#else
+ int SDLNet_CheckSockets(SDLNet_SocketSet set, Uint32 timeout)
+ {
+ int i;
+- SOCKET maxfd;
+ int retval;
+- struct timeval tv;
+- fd_set mask;
-
-+#define u_int32_t uint32_t
+- /* Find the largest file descriptor */
+- maxfd = 0;
+- for ( i=set->numsockets-1; i>=0; --i ) {
+- if ( set->sockets[i]->channel > maxfd ) {
+- maxfd = set->sockets[i]->channel;
+- }
+- }
+-
+- /* Check the file descriptors for available data */
+- do {
+- errno = 0;
+-
+- /* Set up the mask of file descriptors */
+- FD_ZERO(&mask);
+- for ( i=set->numsockets-1; i>=0; --i ) {
+- FD_SET(set->sockets[i]->channel, &mask);
+- }
+
+- /* Set up the timeout */
+- tv.tv_sec = timeout/1000;
+- tv.tv_usec = (timeout%1000)*1000;
++ retval = 0;
- /* Set up for C function definitions, even when using C++ */
- #ifdef __cplusplus
-
-diff -urN /dev/null SDL_net-1.2.7-nacl/inet_addr.c
---- /dev/null 2013-11-02 22:47:51.150226312 +0400
-+++ SDL_net-1.2.7-nacl/inet_addr.c 2013-11-02 23:59:09.523930000 +0400
-@@ -0,0 +1,201 @@
-+/* $KAME: inet_addr.c,v 1.5 2001/08/20 02:32:40 itojun Exp $ */
+- /* Look! */
+- retval = select(maxfd+1, &mask, NULL, NULL, &tv);
+- } while ( errno == EINTR );
+-
+- /* Mark all file descriptors ready that have data available */
+- if ( retval > 0 ) {
+- for ( i=set->numsockets-1; i>=0; --i ) {
+- if ( FD_ISSET(set->sockets[i]->channel, &mask) ) {
+- set->sockets[i]->ready = 1;
+- }
+- }
++ for (i = 0; i < set->numsockets; ++i) {
++ if (set->sockets[i]->ready)
++ retval++;
++ else
++#warning SDLNet_CheckSockets can work only with TCPsockets!
++ SDLNet_TCP_Recv (set->sockets[i], NULL, 0);
+ }
+- return(retval);
+
++ return retval;
+ }
+-#endif /* MACOS_OPENTRANSPORT */
+
+ /* Free a set of sockets allocated by SDL_NetAllocSocketSet() */
+ extern void SDLNet_FreeSocketSet(SDLNet_SocketSet set)
+diff -Naur a/SDLnetTCP.c b/SDLnetTCP.c
+--- a/SDLnetTCP.c 2007-07-15 09:55:42.000000000 +0400
++++ b/SDLnetTCP.c 1970-01-01 03:00:00.000000000 +0300
+@@ -1,953 +0,0 @@
+-/*
+- SDL_net: An example cross-platform network library for use with SDL
+- Copyright (C) 1997-2004 Sam Lantinga
+-
+- This library is free software; you can redistribute it and/or
+- modify it under the terms of the GNU Library General Public
+- License as published by the Free Software Foundation; either
+- version 2 of the License, or (at your option) any later version.
+-
+- This library 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
+- Library General Public License for more details.
+-
+- You should have received a copy of the GNU Library General Public
+- License along with this library; if not, write to the Free
+- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+-
+- Sam Lantinga
+- slouken@libsdl.org
+-*/
+-
+-/* $Id: SDLnetTCP.c 3280 2007-07-15 05:55:42Z slouken $ */
+-
+-#include "SDLnetsys.h"
+-#include "SDL_net.h"
+-
+-/* The network API for TCP sockets */
+-
+-/* Since the UNIX/Win32/BeOS code is so different from MacOS,
+- we'll just have two completely different sections here.
+-*/
+-
+-#ifdef MACOS_OPENTRANSPORT
+-
+-#include <Events.h>
+-#include <Threads.h>
+-#include <OpenTransport.h>
+-#include <OpenTptInternet.h>
+-#include <OTDebug.h>
+-
+-struct _TCPsocket {
+- int ready;
+- SOCKET channel;
+-
+- // These are taken from GUSI interface.
+- // I'm not sure if it's really necessary here yet
+- // ( masahiro minami<elsur@aaa.letter.co.jp> )
+- // ( 01/02/19 )
+- OTEventCode curEvent;
+- OTEventCode newEvent;
+- OTEventCode event;
+- OTEventCode curCompletion;
+- OTEventCode newCompletion;
+- OTEventCode completion;
+- OSStatus error;
+- TEndpointInfo info;
+- Boolean readShutdown;
+- Boolean writeShutdown;
+- Boolean connected;
+- OTConfigurationRef config; // Master configuration. you can clone this.
+- TCPsocket nextListener;
+- // ( end of new members --- masahiro minami<elsur@aaa.letter.co.jp>
+-
+- IPaddress remoteAddress;
+- IPaddress localAddress;
+- int sflag;
+-
+- // Maybe we don't need this---- it's from original SDL_net
+- // (masahiro minami<elsur@aaa.letter.co.jp>)
+- // ( 01/02/20 )
+- int rcvdPassConn;
+-};
+-
+-// To be used in WaitNextEvent() here and there....
+-// (010311 masahiro minami<elsur@aaa.letter.co.jp>)
+-EventRecord macEvent;
+-
+-#if TARGET_API_MAC_CARBON
+-/* for Carbon */
+-OTNotifyUPP notifier;
+-#endif
+-
+-/* Input: ep - endpointref on which to negotiate the option
+- enableReuseIPMode - desired option setting - true/false
+- Return: kOTNoError indicates that the option was successfully negotiated
+- OSStatus is an error if < 0, otherwise, the status field is
+- returned and is > 0.
+-
+- IMPORTANT NOTE: The endpoint is assumed to be in synchronous more, otherwise
+- this code will not function as desired
+-*/
+-
+-/*
+-NOTE: As this version is written async way, we don't use this function...
+-(010526) masahiro minami<elsur@aaa.letter.co.jp>
+-*/
+-/*
+-OSStatus DoNegotiateIPReuseAddrOption(EndpointRef ep, Boolean enableReuseIPMode)
+-
+-{
+- UInt8 buf[kOTFourByteOptionSize]; // define buffer for fourByte Option size
+- TOption* opt; // option ptr to make items easier to access
+- TOptMgmt req;
+- TOptMgmt ret;
+- OSStatus err;
+-
+- if (!OTIsSynchronous(ep))
+- {
+- return (-1);
+- }
+- opt = (TOption*)buf; // set option ptr to buffer
+- req.opt.buf = buf;
+- req.opt.len = sizeof(buf);
+- req.flags = T_NEGOTIATE; // negotiate for option
+-
+- ret.opt.buf = buf;
+- ret.opt.maxlen = kOTFourByteOptionSize;
+-
+- opt->level = INET_IP; // dealing with an IP Level function
+- opt->name = IP_REUSEADDR;
+- opt->len = kOTFourByteOptionSize;
+- opt->status = 0;
+- *(UInt32*)opt->value = enableReuseIPMode; // set the desired option level, true or false
+-
+- err = OTOptionManagement(ep, &req, &ret);
+-
+- // if no error then return the option status value
+- if (err == kOTNoError)
+- {
+- if (opt->status != T_SUCCESS)
+- err = opt->status;
+- else
+- err = kOTNoError;
+- }
+-
+- return err;
+-}
+-*/
+-
+-/* A helper function for Mac OpenTransport support*/
+-// This function is a complete copy from GUSI
+-// ( masahiro minami<elsur@aaa.letter.co.jp> )
+-// ( 01/02/19 )
+-static __inline__ Uint32 CompleteMask(OTEventCode code)
+-{
+- return 1 << (code & 0x1F);
+-}
+-
+-/* Notifier for async OT calls */
+-static pascal void AsyncTCPNotifier( TCPsocket sock, OTEventCode code,
+- OTResult result, void* cookie )
+-{
+-
+-#ifdef DEBUG_NET
+- printf("AsyncTCPNotifier got an event : 0x%8.8x\n", code );
+-#endif
+-
+- switch( code & 0x7f000000L)
+- {
+- case 0:
+- sock->newEvent |= code;
+- result = 0;
+- break;
+- case kCOMPLETEEVENT:
+- if(!(code & 0x00FFFFE0 ))
+- sock->newCompletion |= CompleteMask( code );
+- if( code == T_OPENCOMPLETE )
+- sock->channel = (SOCKET)(cookie);
+- break;
+- default:
+- if( code != kOTProviderWillClose )
+- result = 0;
+- }
+- // Do we need these ???? TODO
+- // sock->SetAsyncMacError( result );
+- // sock->Wakeup();
+-}
+-
+-/* Retrieve OT event */
+-// This function is taken from GUSI interface.
+-// ( 01/02/19 masahiro minami<elsur@aaa.letter.co.jp> )
+-static void AsyncTCPPopEvent( TCPsocket sock )
+-{
+- // Make sure OT calls are not interrupted
+- // Not sure if we really need this.
+- OTEnterNotifier( sock->channel );
+-
+- sock->event |= (sock->curEvent = sock->newEvent );
+- sock->completion |= ( sock->curCompletion = sock->newCompletion );
+- sock->newEvent = sock->newCompletion = 0;
+-
+- OTLeaveNotifier( sock->channel );
+-
+- if( sock->curEvent & T_UDERR)
+- {
+- // We just clear the error.
+- // Should we feed this back to users ?
+- // (TODO )
+- OTRcvUDErr( sock->channel, NULL );
+-
+-#ifdef DEBUG_NET
+- printf("AsyncTCPPopEvent T_UDERR recognized");
+-#endif
+- }
+-
+- // Remote is disconnecting...
+- if( sock->curEvent & ( T_DISCONNECT | T_ORDREL ))
+- {
+- sock->readShutdown = true;
+- }
+-
+- if( sock->curEvent &T_CONNECT )
+- {
+- // Ignore the info of remote (second parameter).
+- // Shoule we care ?
+- // (TODO)
+- OTRcvConnect( sock->channel, NULL );
+- sock->connected = 1;
+- }
+-
+- if( sock->curEvent & T_ORDREL )
+- {
+- OTRcvOrderlyDisconnect( sock->channel );
+- }
+-
+- if( sock->curEvent & T_DISCONNECT )
+- {
+- OTRcvDisconnect( sock->channel, NULL );
+- }
+-
+- // Do we need to ?
+- // (masahiro minami<elsur@aaa.letter.co.jp>)
+- //YieldToAnyThread();
+-}
+-
+-/* Create a new TCPsocket */
+-// Because TCPsocket structure gets bigger and bigger,
+-// I think we'd better have a constructor function and delete function.
+-// ( 01/02/25 masahiro minami<elsur@aaa.letter.co.jp> )
+-static TCPsocket AsyncTCPNewSocket()
+-{
+- TCPsocket sock;
+-
+- sock = (TCPsocket)malloc(sizeof(*sock));
+- if ( sock == NULL ) {
+- SDLNet_SetError("Out of memory");
+- return NULL;
+- }
+-
+- sock->newEvent = 0;
+- sock->event = 0;
+- sock->curEvent = 0;
+- sock->newCompletion = 0;
+- sock->completion = 0;
+- sock->curCompletion = 0;
+- //sock->info = NULL;
+- sock->readShutdown = sock->writeShutdown = sock->connected = false;
+- sock->error = 0;
+- sock->config = NULL;
+- sock->nextListener = NULL;
+- sock->sflag = 0;
+- return sock;
+-}
+-
+-// hmmm.... do we need this ???
+-// ( 01/02/25 masahiro minami<elsur@aaa.letter.co.jp>)
+-static void AsycnTCPDeleteSocket( TCPsocket sock )
+-{
+- SDLNet_TCP_Close( sock );
+-}
+-/* Open a TCP network socket
+- If 'remote' is NULL, this creates a local server socket on the given port,
+- otherwise a TCP connection to the remote host and port is attempted.
+- The newly created socket is returned, or NULL if there was an error.
+-
+- ( re-written by masahiro minami<elsur@aaa.letter.co.jp>
+- Now endpoint is created in Async mode.
+- 01/02/20 )
+-*/
+-TCPsocket SDLNet_TCP_Open(IPaddress *ip)
+-{
+- EndpointRef dummy = NULL;
+-
+- TCPsocket sock = AsyncTCPNewSocket();
+- if( ! sock)
+- return NULL;
+-
+- // Determin whether bind locally, or connect to remote
+- if ( (ip->host != INADDR_NONE) && (ip->host != INADDR_ANY) )
+- {
+- // ######## Connect to remote
+- OTResult stat;
+- InetAddress inAddr;
+- TBind bindReq;
+-
+- // Open endpoint
+- sock->error = OTAsyncOpenEndpoint(
+- OTCreateConfiguration(kTCPName), NULL, &(sock->info),
+- (OTNotifyProcPtr)(AsyncTCPNotifier),
+- sock );
+-
+- AsyncTCPPopEvent( sock );
+- while( !sock->error && !( sock->completion & CompleteMask(T_OPENCOMPLETE)))
+- {
+- //SetThreadState( kCurrentThreadID, kReadyThreadState, kNoThreadID );
+- //YieldToAnyThread();
+- //WaitNextEvent(everyEvent, &macEvent, 1, NULL);
+- AsyncTCPPopEvent( sock );
+- }
+-
+- if( !sock->channel )
+- {
+- SDLNet_SetError("OTAsyncOpenEndpoint failed --- client socket could not be opened");
+- goto error_return;
+- }
+-
+- // Set blocking mode
+- // I'm not sure if this is a good solution....
+- // Check out Apple's sample code, OT Virtual Server
+- // ( 010314 masahiro minami<elsur@aaa.letter.co.jp>)
+-
+- sock->error = OTSetBlocking( sock->channel );
+- if( sock->error != kOTNoError )
+- {
+- SDLNet_SetError("OTSetBlocking() returned an error");
+- goto error_return;
+- }
+-
+- // Bind the socket
+- OTInitInetAddress(&inAddr, 0, 0 );
+- bindReq.addr.len = sizeof( InetAddress );
+- bindReq.addr.buf = (unsigned char*)&inAddr;
+- bindReq.qlen = 0;
+-
+- sock->error = OTBind( sock->channel, &bindReq, NULL );
+- AsyncTCPPopEvent(sock);
+- while( !sock->error && !( sock->completion & CompleteMask(T_BINDCOMPLETE)))
+- {
+- //YieldToAnyThread();
+- //WaitNextEvent(everyEvent, &macEvent, 1, NULL);
+- AsyncTCPPopEvent(sock);
+- }
+-
+-
+- switch( stat = OTGetEndpointState( sock->channel ))
+- {
+- InetAddress inAddr;
+- TCall sndCall;
+- OTResult res;
+-
+- case T_OUTCON:
+- SDLNet_SetError("SDLNet_Open() failed -- T_OUTCON");
+- goto error_return;
+- break;
+- case T_IDLE:
+- sock->readShutdown = false;
+- sock->writeShutdown = false;
+- sock->event &=~T_CONNECT;
+-
+- OTMemzero(&sndCall, sizeof(TCall));
+- OTInitInetAddress(&inAddr, ip->port, ip->host );
+- sndCall.addr.len = sizeof(InetAddress);
+- sndCall.addr.buf = (unsigned char*)&inAddr;
+- sock->connected = 0;
+- res = OTConnect( sock->channel, &sndCall, NULL );
+- AsyncTCPPopEvent(sock);
+- while( sock->error == kOTNoDataErr || !sock->connected )
+- AsyncTCPPopEvent(sock);
+- break;
+- default:
+- // What's to be done ? (TODO)
+- SDLNet_SetError("SDLNet_TCP_Open() failed -- EndpointState not good");
+- goto error_return;
+-
+- }
+- if( !(sock->event & (T_CONNECT|T_DISCONNECT)))
+- goto error_return;
+-
+- AsyncTCPPopEvent( sock );
+- while( !(sock->event & (T_CONNECT|T_DISCONNECT)))
+- {
+- AsyncTCPPopEvent( sock );
+- }
+- // OTConnect successfull
+- if( sock->event & T_CONNECT)
+- {
+- sock->remoteAddress.host = inAddr.fHost;
+- sock->remoteAddress.port = inAddr.fPort;
+- sock->sflag = false;
+- }
+- else
+- {
+- // OTConnect failed
+- sock->event &= ~T_DISCONNECT;
+- goto error_return;
+- }
+- }
+- else
+- {
+- // ######## Bind locally
+- TBind bindReq;
+- InetAddress inAddr;
+-
+- // First, get InetInterfaceInfo.
+- // I don't search for all of them.
+- // Does that matter ?
+-
+- sock->error = OTAsyncOpenEndpoint(
+- OTCreateConfiguration("tilisten, tcp"), NULL, &(sock->info),
+- (OTNotifyProcPtr)(AsyncTCPNotifier),
+- sock);
+- AsyncTCPPopEvent( sock );
+- while( !sock->error && !( sock->completion & CompleteMask( T_OPENCOMPLETE)))
+- {
+- AsyncTCPPopEvent( sock );
+- }
+-
+- if( ! sock->channel )
+- {
+- SDLNet_SetError("OTAsyncOpenEndpoint failed --- server socket could not be opened");
+- goto error_return;
+- }
+-
+- // Create a master OTConfiguration
+- sock->config = OTCreateConfiguration(kTCPName);
+- if( ! sock->config )
+- {
+- SDLNet_SetError("Could not create master OTConfiguration");
+- goto error_return;
+- }
+-
+- // Bind the socket
+- OTInitInetAddress(&inAddr, ip->port, 0 );
+- inAddr.fAddressType = AF_INET;
+- bindReq.addr.len = sizeof( InetAddress );
+- bindReq.addr.buf = (unsigned char*)&inAddr;
+- bindReq.qlen = 35; // This number is NOT well considered. (TODO)
+- sock->localAddress.host = inAddr.fHost;
+- sock->localAddress.port = inAddr.fPort;
+- sock->sflag = true;
+-
+- sock->error = OTBind( sock->channel, &bindReq, NULL );
+- AsyncTCPPopEvent(sock);
+- while( !sock->error && !( sock->completion & CompleteMask(T_BINDCOMPLETE)))
+- {
+- AsyncTCPPopEvent(sock);
+- }
+- if( sock->error != kOTNoError )
+- {
+- SDLNet_SetError("Could not bind server socket");
+- goto error_return;
+- }
+-
+- if( dummy )
+- OTCloseProvider( dummy );
+-
+- }
+-
+- sock->ready = 0;
+- return sock;
+-
+- error_return:
+- if( dummy )
+- OTCloseProvider( dummy );
+- SDLNet_TCP_Close( sock );
+- return NULL;
+-}
+-
+-/* Accept an incoming connection on the given server socket.
+- The newly created socket is returned, or NULL if there was an error.
+-*/
+-TCPsocket SDLNet_TCP_Accept(TCPsocket server)
+-{
+-
+- /* Only server sockets can accept */
+- if ( ! server->sflag ) {
+- SDLNet_SetError("Only server sockets can accept()");
+- return(NULL);
+- }
+- server->ready = 0;
+-
+- /* Accept a new TCP connection on a server socket */
+- {
+- InetAddress peer;
+- TCall peerinfo;
+- TCPsocket sock = NULL;
+- Boolean mustListen = false;
+- OTResult err;
+-
+- memset(&peerinfo, 0, (sizeof peerinfo ));
+- peerinfo.addr.buf = (Uint8 *) &peer;
+- peerinfo.addr.maxlen = sizeof(peer);
+-
+- while( mustListen || !sock )
+- {
+- // OTListen
+- // We do NOT block ---- right thing ? (TODO)
+- err = OTListen( server->channel, &peerinfo );
+-
+- if( err )
+- goto error_return;
+- else
+- {
+- mustListen = false;
+- sock = AsyncTCPNewSocket();
+- if( ! sock )
+- goto error_return;
+- }
+- }
+- if( sock )
+- {
+- // OTAsyncOpenEndpoint
+- server->error = OTAsyncOpenEndpoint( OTCloneConfiguration( server->config ),
+- NULL, &(sock->info), (OTNotifyProcPtr)AsyncTCPNotifier, sock );
+- AsyncTCPPopEvent( sock );
+- while( !sock->error && !( sock->completion & CompleteMask( T_OPENCOMPLETE)))
+- {
+- AsyncTCPPopEvent( sock );
+- }
+- if( ! sock->channel )
+- {
+- mustListen = false;
+- goto error_return;
+- }
+-
+- // OTAccept
+- server->completion &= ~(CompleteMask(T_ACCEPTCOMPLETE));
+- server->error = OTAccept( server->channel, sock->channel, &peerinfo );
+- AsyncTCPPopEvent( server );
+- while( !(server->completion & CompleteMask(T_ACCEPTCOMPLETE)))
+- {
+- AsyncTCPPopEvent( server );
+- }
+-
+- switch( server->error )
+- {
+- case kOTLookErr:
+- switch( OTLook(server->channel ))
+- {
+- case T_LISTEN:
+- mustListen = true;
+- break;
+- case T_DISCONNECT:
+- goto error_return;
+- }
+- break;
+- case 0:
+- sock->nextListener = server->nextListener;
+- server->nextListener = sock;
+- sock->remoteAddress.host = peer.fHost;
+- sock->remoteAddress.port = peer.fPort;
+- return sock;
+- // accept successful
+- break;
+- default:
+- free( sock );
+- }
+- }
+- sock->remoteAddress.host = peer.fHost;
+- sock->remoteAddress.port = peer.fPort;
+- sock->sflag = 0;
+- sock->ready = 0;
+-
+- /* The socket is ready */
+- return(sock);
+-
+- // Error; close the socket and return
+- error_return:
+- SDLNet_TCP_Close(sock);
+- return(NULL);
+- }
+-}
+-
+-/* Get the IP address of the remote system associated with the socket.
+- If the socket is a server socket, this function returns NULL.
+-*/
+-IPaddress *SDLNet_TCP_GetPeerAddress(TCPsocket sock)
+-{
+- if ( sock->sflag ) {
+- return(NULL);
+- }
+- return(&sock->remoteAddress);
+-}
+-
+-/* Send 'len' bytes of 'data' over the non-server socket 'sock'
+- This function returns the actual amount of data sent. If the return value
+- is less than the amount of data sent, then either the remote connection was
+- closed, or an unknown socket error occurred.
+-*/
+-int SDLNet_TCP_Send(TCPsocket sock, const void *datap, int len)
+-{
+- const Uint8 *data = (const Uint8 *)datap; /* For pointer arithmetic */
+- int sent, left;
+-
+- /* Server sockets are for accepting connections only */
+- if ( sock->sflag ) {
+- SDLNet_SetError("Server sockets cannot send");
+- return(-1);
+- }
+-
+- /* Keep sending data until it's sent or an error occurs */
+- left = len;
+- sent = 0;
+- errno = 0;
+- do {
+- len = OTSnd(sock->channel, (void *)data, left, 0);
+- if (len == kOTFlowErr)
+- len = 0;
+- if ( len > 0 ) {
+- sent += len;
+- left -= len;
+- data += len;
+- }
+- // Do we need to ?
+- // ( masahiro minami<elsur@aaa.letter.co.jp> )
+- // (TODO)
+- //WaitNextEvent(everyEvent, &macEvent, 1, NULL);
+- //AsyncTCPPopEvent(sock);
+- } while ( (left > 0) && (len > 0) );
+-
+- return(sent);
+-}
+-
+-/* Receive up to 'maxlen' bytes of data over the non-server socket 'sock',
+- and store them in the buffer pointed to by 'data'.
+- This function returns the actual amount of data received. If the return
+- value is less than or equal to zero, then either the remote connection was
+- closed, or an unknown socket error occurred.
+-*/
+-int SDLNet_TCP_Recv(TCPsocket sock, void *data, int maxlen)
+-{
+- int len = 0;
+- OSStatus res;
+- /* Server sockets are for accepting connections only */
+- if ( sock->sflag ) {
+- SDLNet_SetError("Server sockets cannot receive");
+- return(-1);
+- }
+-
+- do
+- {
+- res = OTRcv(sock->channel, data, maxlen-len, 0);
+- if (res > 0) {
+- len = res;
+- }
+-
+-#ifdef DEBUG_NET
+- if ( res != kOTNoDataErr )
+- printf("SDLNet_TCP_Recv received ; %d\n", res );
+-#endif
+-
+- AsyncTCPPopEvent(sock);
+- if( res == kOTLookErr )
+- {
+- res = OTLook(sock->channel );
+- continue;
+- }
+- } while ( (len == 0) && (res == kOTNoDataErr) );
+-
+- sock->ready = 0;
+- if ( len == 0 ) { /* Open Transport error */
+-#ifdef DEBUG_NET
+- printf("Open Transport error: %d\n", res);
+-#endif
+- return(-1);
+- }
+- return(len);
+-}
+-
+-/* Close a TCP network socket */
+-void SDLNet_TCP_Close(TCPsocket sock)
+-{
+- if ( sock != NULL ) {
+- if ( sock->channel != INVALID_SOCKET ) {
+- //closesocket(sock->channel);
+- OTSndOrderlyDisconnect( sock->channel );
+- }
+- free(sock);
+- }
+-}
+-
+-#else /* !MACOS_OPENTRANSPORT */
+-
+-struct _TCPsocket {
+- int ready;
+- SOCKET channel;
+- IPaddress remoteAddress;
+- IPaddress localAddress;
+- int sflag;
+-};
+-
+-/* Open a TCP network socket
+- If 'remote' is NULL, this creates a local server socket on the given port,
+- otherwise a TCP connection to the remote host and port is attempted.
+- The newly created socket is returned, or NULL if there was an error.
+-*/
+-TCPsocket SDLNet_TCP_Open(IPaddress *ip)
+-{
+- TCPsocket sock;
+- struct sockaddr_in sock_addr;
+-
+- /* Allocate a TCP socket structure */
+- sock = (TCPsocket)malloc(sizeof(*sock));
+- if ( sock == NULL ) {
+- SDLNet_SetError("Out of memory");
+- goto error_return;
+- }
+-
+- /* Open the socket */
+- sock->channel = socket(AF_INET, SOCK_STREAM, 0);
+- if ( sock->channel == INVALID_SOCKET ) {
+- SDLNet_SetError("Couldn't create socket");
+- goto error_return;
+- }
+-
+- /* Connect to remote, or bind locally, as appropriate */
+- if ( (ip->host != INADDR_NONE) && (ip->host != INADDR_ANY) ) {
+-
+- // ######### Connecting to remote
+-
+- memset(&sock_addr, 0, sizeof(sock_addr));
+- sock_addr.sin_family = AF_INET;
+- sock_addr.sin_addr.s_addr = ip->host;
+- sock_addr.sin_port = ip->port;
+-
+- /* Connect to the remote host */
+- if ( connect(sock->channel, (struct sockaddr *)&sock_addr,
+- sizeof(sock_addr)) == SOCKET_ERROR ) {
+- SDLNet_SetError("Couldn't connect to remote host");
+- goto error_return;
+- }
+- sock->sflag = 0;
+- } else {
+-
+- // ########## Binding locally
+-
+- memset(&sock_addr, 0, sizeof(sock_addr));
+- sock_addr.sin_family = AF_INET;
+- sock_addr.sin_addr.s_addr = INADDR_ANY;
+- sock_addr.sin_port = ip->port;
+-
+-/*
+- * Windows gets bad mojo with SO_REUSEADDR:
+- * http://www.devolution.com/pipermail/sdl/2005-September/070491.html
+- * --ryan.
+- */
+-#ifndef WIN32
+- /* allow local address reuse */
+- { int yes = 1;
+- setsockopt(sock->channel, SOL_SOCKET, SO_REUSEADDR, (char*)&yes, sizeof(yes));
+- }
+-#endif
+-
+- /* Bind the socket for listening */
+- if ( bind(sock->channel, (struct sockaddr *)&sock_addr,
+- sizeof(sock_addr)) == SOCKET_ERROR ) {
+- SDLNet_SetError("Couldn't bind to local port");
+- goto error_return;
+- }
+- if ( listen(sock->channel, 5) == SOCKET_ERROR ) {
+- SDLNet_SetError("Couldn't listen to local port");
+- goto error_return;
+- }
+-
+- /* Set the socket to non-blocking mode for accept() */
+-#if defined(__BEOS__) && defined(SO_NONBLOCK)
+- /* On BeOS r5 there is O_NONBLOCK but it's for files only */
+- {
+- long b = 1;
+- setsockopt(sock->channel, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b));
+- }
+-#elif defined(O_NONBLOCK)
+- {
+- fcntl(sock->channel, F_SETFL, O_NONBLOCK);
+- }
+-#elif defined(WIN32)
+- {
+- unsigned long mode = 1;
+- ioctlsocket (sock->channel, FIONBIO, &mode);
+- }
+-#elif defined(__OS2__)
+- {
+- int dontblock = 1;
+- ioctl(sock->channel, FIONBIO, &dontblock);
+- }
+-#else
+-#warning How do we set non-blocking mode on other operating systems?
+-#endif
+- sock->sflag = 1;
+- }
+- sock->ready = 0;
+-
+-#ifdef TCP_NODELAY
+- /* Set the nodelay TCP option for real-time games */
+- { int yes = 1;
+- setsockopt(sock->channel, IPPROTO_TCP, TCP_NODELAY, (char*)&yes, sizeof(yes));
+- }
+-#endif /* TCP_NODELAY */
+-
+- /* Fill in the channel host address */
+- sock->remoteAddress.host = sock_addr.sin_addr.s_addr;
+- sock->remoteAddress.port = sock_addr.sin_port;
+-
+- /* The socket is ready */
+- return(sock);
+-
+-error_return:
+- SDLNet_TCP_Close(sock);
+- return(NULL);
+-}
+-
+-/* Accept an incoming connection on the given server socket.
+- The newly created socket is returned, or NULL if there was an error.
+-*/
+-TCPsocket SDLNet_TCP_Accept(TCPsocket server)
+-{
+- TCPsocket sock;
+- struct sockaddr_in sock_addr;
+- int sock_alen;
+-
+- /* Only server sockets can accept */
+- if ( ! server->sflag ) {
+- SDLNet_SetError("Only server sockets can accept()");
+- return(NULL);
+- }
+- server->ready = 0;
+-
+- /* Allocate a TCP socket structure */
+- sock = (TCPsocket)malloc(sizeof(*sock));
+- if ( sock == NULL ) {
+- SDLNet_SetError("Out of memory");
+- goto error_return;
+- }
+-
+- /* Accept a new TCP connection on a server socket */
+- sock_alen = sizeof(sock_addr);
+- sock->channel = accept(server->channel, (struct sockaddr *)&sock_addr,
+-#ifdef USE_GUSI_SOCKETS
+- (unsigned int *)&sock_alen);
+-#else
+- &sock_alen);
+-#endif
+- if ( sock->channel == SOCKET_ERROR ) {
+- SDLNet_SetError("accept() failed");
+- goto error_return;
+- }
+-#ifdef WIN32
+- {
+- /* passing a zero value, socket mode set to block on */
+- unsigned long mode = 0;
+- ioctlsocket (sock->channel, FIONBIO, &mode);
+- }
+-#elif defined(O_NONBLOCK)
+- {
+- int flags = fcntl(sock->channel, F_GETFL, 0);
+- fcntl(sock->channel, F_SETFL, flags & ~O_NONBLOCK);
+- }
+-#endif /* WIN32 */
+- sock->remoteAddress.host = sock_addr.sin_addr.s_addr;
+- sock->remoteAddress.port = sock_addr.sin_port;
+-
+- sock->sflag = 0;
+- sock->ready = 0;
+-
+- /* The socket is ready */
+- return(sock);
+-
+-error_return:
+- SDLNet_TCP_Close(sock);
+- return(NULL);
+-}
+-
+-/* Get the IP address of the remote system associated with the socket.
+- If the socket is a server socket, this function returns NULL.
+-*/
+-IPaddress *SDLNet_TCP_GetPeerAddress(TCPsocket sock)
+-{
+- if ( sock->sflag ) {
+- return(NULL);
+- }
+- return(&sock->remoteAddress);
+-}
+-
+-/* Send 'len' bytes of 'data' over the non-server socket 'sock'
+- This function returns the actual amount of data sent. If the return value
+- is less than the amount of data sent, then either the remote connection was
+- closed, or an unknown socket error occurred.
+-*/
+-int SDLNet_TCP_Send(TCPsocket sock, const void *datap, int len)
+-{
+- const Uint8 *data = (const Uint8 *)datap; /* For pointer arithmetic */
+- int sent, left;
+-
+- /* Server sockets are for accepting connections only */
+- if ( sock->sflag ) {
+- SDLNet_SetError("Server sockets cannot send");
+- return(-1);
+- }
+-
+- /* Keep sending data until it's sent or an error occurs */
+- left = len;
+- sent = 0;
+- errno = 0;
+- do {
+- len = send(sock->channel, (const char *) data, left, 0);
+- if ( len > 0 ) {
+- sent += len;
+- left -= len;
+- data += len;
+- }
+- } while ( (left > 0) && ((len > 0) || (errno == EINTR)) );
+-
+- return(sent);
+-}
+-
+-/* Receive up to 'maxlen' bytes of data over the non-server socket 'sock',
+- and store them in the buffer pointed to by 'data'.
+- This function returns the actual amount of data received. If the return
+- value is less than or equal to zero, then either the remote connection was
+- closed, or an unknown socket error occurred.
+-*/
+-int SDLNet_TCP_Recv(TCPsocket sock, void *data, int maxlen)
+-{
+- int len;
+-
+- /* Server sockets are for accepting connections only */
+- if ( sock->sflag ) {
+- SDLNet_SetError("Server sockets cannot receive");
+- return(-1);
+- }
+-
+- errno = 0;
+- do {
+- len = recv(sock->channel, (char *) data, maxlen, 0);
+- } while ( errno == EINTR );
+-
+- sock->ready = 0;
+- return(len);
+-}
+-
+-/* Close a TCP network socket */
+-void SDLNet_TCP_Close(TCPsocket sock)
+-{
+- if ( sock != NULL ) {
+- if ( sock->channel != INVALID_SOCKET ) {
+- closesocket(sock->channel);
+- }
+- free(sock);
+- }
+-}
+-
+-#endif /* MACOS_OPENTRANSPORT */
+diff -Naur a/SDLnetTCP.cpp b/SDLnetTCP.cpp
+--- a/SDLnetTCP.cpp 1970-01-01 03:00:00.000000000 +0300
++++ b/SDLnetTCP.cpp 2015-11-30 00:34:59.378830000 +0300
+@@ -0,0 +1,483 @@
+/*
-+ * ++Copyright++ 1983, 1990, 1993
-+ * -
-+ * Copyright (c) 1983, 1990, 1993
-+ * The Regents of the University of California. All rights reserved.
-+ *
-+ * Redistribution and use in source and binary forms, with or without
-+ * modification, are permitted provided that the following conditions
-+ * are met:
-+ * 1. Redistributions of source code must retain the above copyright
-+ * notice, this list of conditions and the following disclaimer.
-+ * 2. Redistributions in binary form must reproduce the above copyright
-+ * notice, this list of conditions and the following disclaimer in the
-+ * documentation and/or other materials provided with the distribution.
-+ * 3. All advertising materials mentioning features or use of this software
-+ * must display the following acknowledgement:
-+ * This product includes software developed by the University of
-+ * California, Berkeley and its contributors.
-+ * 4. Neither the name of the University nor the names of its contributors
-+ * may be used to endorse or promote products derived from this software
-+ * without specific prior written permission.
-+ *
-+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
-+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
-+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-+ * SUCH DAMAGE.
-+ * -
-+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
-+ *
-+ * Permission to use, copy, modify, and distribute this software for any
-+ * purpose with or without fee is hereby granted, provided that the above
-+ * copyright notice and this permission notice appear in all copies, and that
-+ * the name of Digital Equipment Corporation not be used in advertising or
-+ * publicity pertaining to distribution of the document or software without
-+ * specific, written prior permission.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
-+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
-+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
-+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
-+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
-+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
-+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-+ * SOFTWARE.
-+ * -
-+ * --Copyright--
-+ */
-+
-+#if defined(LIBC_SCCS) && !defined(lint)
-+static char sccsid[] = "@(#)inet_addr.c 8.1 (Berkeley) 6/17/93";
-+#endif /* LIBC_SCCS and not lint */
-+#include <sys/cdefs.h>
-+#include <sys/types.h>
-+#include <machine/endian.h>
-+
-+#include <sys/param.h>
-+
-+#include <netinet/in.h>
-+#include <arpa/inet.h>
-+
-+#include <ctype.h>
-+#include <errno.h>
-+#include <string.h>
-+#include <stdlib.h>
++ SDL_net: An example cross-platform network library for use with SDL
++ Copyright (C) 1997-2004 Sam Lantinga
+
-+/*
-+ * ASCII internet address interpretation routine.
-+ * The value returned is in network order.
-+ */
-+in_addr_t /* XXX should be struct in_addr :( */
-+inet_addr(cp)
-+ const char *cp;
++ This library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Library General Public
++ License as published by the Free Software Foundation; either
++ version 2 of the License, or (at your option) any later version.
++
++ This library 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
++ Library General Public License for more details.
++
++ You should have received a copy of the GNU Library General Public
++ License along with this library; if not, write to the Free
++ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++ Sam Lantinga
++ slouken@libsdl.org
++*/
++
++/* $Id: SDLnetTCP.c 3280 2007-07-15 05:55:42Z slouken $ */
++
++#include "SDLnetsys.h"
++#include "SDL_net.h"
++
++#include "ppapi_simple/ps.h"
++#include "ppapi/cpp/tcp_socket.h"
++#include "ppapi/cpp/instance_handle.h"
++#include "ppapi/cpp/message_loop.h"
++#include "ppapi/cpp/instance.h"
++#include "ppapi/c/ppb_net_address.h"
++#include "ppapi/cpp/var.h"
++#include "ppapi/utility/completion_callback_factory.h"
++
++#include "pthread.h"
++#include <condition_variable>
++#include <mutex>
++
++/* The network API for TCP sockets */
++
++#define BUFFER_SIZE 2000
++
++struct _TCPsocket {
++ int ready;
++ pp::TCPSocket channel;
++ IPaddress remoteAddress;
++ IPaddress localAddress;
++ int sflag;
++
++ bool readInProgress;
++ int bufferAmount;
++ int bufferOffset;
++ char buffer [BUFFER_SIZE];
++};
++
++class SDLNetSynchronizer {
++ public:
++ pp::CompletionCallbackFactory <SDLNetSynchronizer> factory;
++ pp::InstanceHandle handle;
++ pp::Instance instance;
++
++ static pp::MessageLoop loop;
++
++ pp::TCPSocket sock_result;
++ int32_t result;
++ bool ready;
++ std::condition_variable cv;
++ std::mutex mtx;
++
++ SDLNetSynchronizer () : factory (this), handle (PSGetInstanceId ()), instance (PSGetInstanceId ()) {
++ ready = false;
++ if (loop.is_null ())
++ loop = pp::MessageLoop::GetForMainThread ();
++ }
++
++ int32_t Connect (pp::TCPSocket &sock, IPaddress *ip_addr) {
++ int32_t code;
++ PP_NetAddress_IPv4 ipv4_addr;
++ IpToIpv4 (ip_addr, &ipv4_addr);
++
++ pp::CompletionCallback cb = factory.NewCallback (
++ &SDLNetSynchronizer::ConnectWork,
++ sock,
++ pp::NetAddress (handle, ipv4_addr)
++ );
++
++ loop.PostWork (cb, 0);
++ wait ();
++
++ return result;
++ }
++
++ int32_t Bind (pp::TCPSocket &sock, IPaddress *ip_addr) {
++ PP_NetAddress_IPv4 ipv4_addr;
++ IpToIpv4 (ip_addr, &ipv4_addr);
++
++
++ pp::CompletionCallback cb = factory.NewCallback (
++ &SDLNetSynchronizer::BindWork,
++ sock,
++ pp::NetAddress (handle, ipv4_addr)
++ );
++
++ loop.PostWork (cb, 0);
++
++ wait ();
++ return result;
++ }
++
++ int32_t Listen (pp::TCPSocket &sock, int32_t backlog) {
++
++ pp::CompletionCallback cb = factory.NewCallback (
++ &SDLNetSynchronizer::ListenWork,
++ sock, backlog
++ );
++
++ loop.PostWork (cb, 0);
++
++ wait ();
++ return result;
++ }
++
++ void WriteWork (int32_t result, pp::TCPSocket &sock, const char *data, size_t size) {
++ sock.Write (
++ data, size,
++ factory.NewCallback (&SDLNetSynchronizer::resultCallback)
++ );
++ }
++
++ int32_t Write (pp::TCPSocket &sock, const char *data, size_t size) {
++ pp::CompletionCallback cb = factory.NewCallback (
++ &SDLNetSynchronizer::WriteWork,
++ sock, data, size
++ );
++
++ loop.PostWork (cb, 0);
++
++ wait ();
++ return result;
++ }
++
++ void ReadAsyncCallback (int32_t result, TCPsocket sock) {
++ if (result <= 0)
++ return;
++
++ sock->bufferOffset = 0;
++ sock->bufferAmount = result;
++ sock->ready = 1;
++ sock->readInProgress = false;
++ }
++
++ void ReadAsyncWork (int32_t result, TCPsocket sock) {
++ sock->channel.Read (
++ sock->buffer, BUFFER_SIZE,
++ factory.NewCallback (&SDLNetSynchronizer::ReadAsyncCallback, sock)
++ );
++ }
++
++ void ReadAsync (TCPsocket sock) {
++ pp::CompletionCallback cb = factory.NewCallback (
++ &SDLNetSynchronizer::ReadAsyncWork,
++ sock
++ );
++
++ sock->readInProgress = true;
++ loop.PostWork (cb, 0);
++ }
++
++ void AcceptWork (int32_t result, pp::TCPSocket &sock) {
++ sock.Accept (
++ factory.NewCallbackWithOutput (&SDLNetSynchronizer::acceptCallback)
++ );
++ }
++
++ pp::TCPSocket Accept (pp::TCPSocket &sock, int32_t &out) {
++ pp::CompletionCallback cb = factory.NewCallback (
++ &SDLNetSynchronizer::AcceptWork,
++ sock
++ );
++
++ loop.PostWork (cb, 0);
++
++ wait ();
++ out = result;
++ return sock_result;
++ }
++
++ void IpToIpv4 (IPaddress *ip_addr, PP_NetAddress_IPv4 *ipv4_addr) {
++ ipv4_addr->port = ip_addr->port;
++ for (int i = 0; i < 4; ++i)
++ ipv4_addr->addr[i] = (ip_addr->host >> (8 * i)) & 0xFF;
++ }
++
++ void NetToIp (pp::NetAddress net_addr, IPaddress *ip_addr) {
++ PP_NetAddress_IPv4 ipv4_addr;
++ net_addr.DescribeAsIPv4Address (&ipv4_addr);
++ Ipv4ToIp (&ipv4_addr, ip_addr);
++ }
++
++ void Ipv4ToIp (PP_NetAddress_IPv4 *ipv4_addr, IPaddress *ip_addr) {
++ ip_addr->port = ipv4_addr->port;
++ ip_addr->host = 0;
++ for (int i = 0; i < 4; ++i)
++ ip_addr->host ^= (((uint32_t) ipv4_addr->addr[i]) << (8 * i));
++ }
++
++ void postMessage (std::string msg) {
++ instance.PostMessage (pp::Var (msg));
++ }
++
++ void postMessage (int32_t msg) {
++ instance.PostMessage (pp::Var (msg));
++ }
++
++ private:
++ void ConnectWork (int32_t result, pp::TCPSocket &sock, pp::NetAddress &addr) {
++ sock.Connect (
++ addr,
++ factory.NewCallback (&SDLNetSynchronizer::resultCallback)
++ );
++ }
++
++ void BindWork (int32_t result, pp::TCPSocket &sock, pp::NetAddress &addr) {
++ sock.Bind (
++ addr,
++ factory.NewCallback (&SDLNetSynchronizer::resultCallback)
++ );
++ }
++
++ void ListenWork (int32_t result, pp::TCPSocket &sock, int32_t backlog) {
++ sock.Listen (
++ backlog,
++ factory.NewCallback (&SDLNetSynchronizer::resultCallback)
++ );
++ }
++
++ void resultCallback (int32_t res) {
++ result = res;
++ unlock ();
++ }
++
++ void acceptCallback (int32_t res, pp::TCPSocket sock) {
++ result = res;
++ sock_result = sock;
++
++ unlock();
++ }
++
++ void wait () {
++ std::unique_lock <std::mutex> lck (mtx);
++ while (!ready)
++ cv.wait (lck);
++ ready = false;
++ }
++
++ void unlock () {
++ std::unique_lock <std::mutex> lck (mtx);
++ ready = true;
++ cv.notify_all ();
++ }
++};
++
++pp::MessageLoop SDLNetSynchronizer::loop = pp::MessageLoop ();
++
++SDLNetSynchronizer *__read_syncer = NULL;
++
++/* Open a TCP network socket
++ If 'remote' is NULL, this creates a local server socket on the given port,
++ otherwise a TCP connection to the remote host and port is attempted.
++ The newly created socket is returned, or NULL if there was an error.
++*/
++TCPsocket SDLNet_TCP_Open (IPaddress *ip)
+{
-+ struct in_addr val;
++ TCPsocket sock;
++ SDLNetSynchronizer syncer;
++
++ /* Allocate a TCP socket structure */
++ sock = (TCPsocket)malloc (sizeof (*sock));
++ if ( sock == NULL ) {
++ SDLNet_SetError ("Out of memory");
++ goto error_return;
++ }
++
++ sock->channel = pp::TCPSocket (syncer.handle);
++
++ /* Connect to remote, or bind locally, as appropriate */
++ if ( (ip->host != INADDR_NONE) && (ip->host != INADDR_ANY) ) {
++
++ // ######### Connecting to remote
++
++ /* Connect to the remote host */
++ if ( syncer.Connect (sock->channel, ip) != PP_OK ) {
++ SDLNet_SetError("Couldn't connect to remote host");
++ goto error_return;
++ }
++ sock->sflag = 0;
++
++ } else {
++
++ // ########## Binding locally
++
++ /* Bind the socket for listening */
++ if ( syncer.Bind (sock->channel, ip) != PP_OK ) {
++ SDLNet_SetError("Couldn't bind to local port");
++ goto error_return;
++ }
++
++ if ( syncer.Listen (sock->channel, 5) != PP_OK ) {
++ SDLNet_SetError("Couldn't listen to local port");
++ goto error_return;
++ }
++
++ /* Set the socket to non-blocking mode for accept() */
++
++ {
++ /* In nacl O_NONBLOCK is defined */
++ // fcntl(sock->channel, F_SETFL, O_NONBLOCK);
++ }
++
++ sock->sflag = 1;
++ }
+
-+ if (inet_aton(cp, &val))
-+ return (val.s_addr);
-+ return (INADDR_NONE);
++ sock->readInProgress = 0;
++ sock->ready = 0;
++ sock->bufferOffset = sock->bufferAmount = 0;
++
++#ifdef TCP_NODELAY
++ /* Set the nodelay TCP option for real-time games */
++ { int yes = 1;
++ setsockopt(sock->channel, IPPROTO_TCP, TCP_NODELAY, (char*)&yes, sizeof(yes));
++ }
++#endif /* TCP_NODELAY */
++
++ /* Fill in the channel host address */
++ sock->remoteAddress = *ip;
++
++ /* The socket is ready */
++ return(sock);
++
++error_return:
++ SDLNet_TCP_Close(sock);
++ return(NULL);
+}
+
-+/*
-+ * Check whether "cp" is a valid ASCII representation
-+ * of an Internet address and convert to a binary address.
-+ * Returns 1 if the address is valid, 0 if not.
-+ * This replaces inet_addr, the return value from which
-+ * cannot distinguish between failure and a local broadcast address.
-+ */
-+int
-+inet_aton(cp, addr)
-+ const char *cp;
-+ struct in_addr *addr;
++/* Accept an incoming connection on the given server socket.
++ The newly created socket is returned, or NULL if there was an error.
++*/
++TCPsocket SDLNet_TCP_Accept(TCPsocket server)
+{
-+ u_long parts[4];
-+ in_addr_t val;
-+ char *c;
-+ char *endptr;
-+ int gotend, n;
-+
-+ c = (char *)cp;
-+ n = 0;
-+ /*
-+ * Run through the string, grabbing numbers until
-+ * the end of the string, or some error
-+ */
-+ gotend = 0;
-+ while (!gotend) {
-+ errno = 0;
-+ val = strtoul(c, &endptr, 0);
-+
-+ if (errno == ERANGE) /* Fail completely if it overflowed. */
-+ return (0);
-+
-+ /*
-+ * If the whole string is invalid, endptr will equal
-+ * c.. this way we can make sure someone hasn't
-+ * gone '.12' or something which would get past
-+ * the next check.
-+ */
-+ if (endptr == c)
-+ return (0);
-+ parts[n] = val;
-+ c = endptr;
-+
-+ /* Check the next character past the previous number's end */
-+ switch (*c) {
-+ case '.' :
-+ /* Make sure we only do 3 dots .. */
-+ if (n == 3) /* Whoops. Quit. */
-+ return (0);
-+ n++;
-+ c++;
-+ break;
-+
-+ case '\0':
-+ gotend = 1;
-+ break;
-+
-+ default:
-+ if (isspace((unsigned char)*c)) {
-+ gotend = 1;
-+ break;
-+ } else
-+ return (0); /* Invalid character, so fail */
-+ }
-+
-+ }
-+
-+ /*
-+ * Concoct the address according to
-+ * the number of parts specified.
-+ */
-+
-+ switch (n) {
-+ case 0: /* a -- 32 bits */
-+ /*
-+ * Nothing is necessary here. Overflow checking was
-+ * already done in strtoul().
-+ */
-+ break;
-+ case 1: /* a.b -- 8.24 bits */
-+ if (val > 0xffffff || parts[0] > 0xff)
-+ return (0);
-+ val |= parts[0] << 24;
-+ break;
-+
-+ case 2: /* a.b.c -- 8.8.16 bits */
-+ if (val > 0xffff || parts[0] > 0xff || parts[1] > 0xff)
-+ return (0);
-+ val |= (parts[0] << 24) | (parts[1] << 16);
-+ break;
-+
-+ case 3: /* a.b.c.d -- 8.8.8.8 bits */
-+ if (val > 0xff || parts[0] > 0xff || parts[1] > 0xff ||
-+ parts[2] > 0xff)
-+ return (0);
-+ val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
-+ break;
-+ }
-+
-+ if (addr != NULL)
-+ addr->s_addr = htonl(val);
-+ return (1);
++ TCPsocket sock;
++ SDLNetSynchronizer syncer;
++ int acc_res;
++
++ /* Only server sockets can accept */
++ if ( ! server->sflag ) {
++ SDLNet_SetError("Only server sockets can accept()");
++ return(NULL);
++ }
++ server->ready = 0;
++
++ /* Allocate a TCP socket structure */
++ sock = (TCPsocket)malloc (sizeof (*sock));
++ if ( sock == NULL ) {
++ SDLNet_SetError("Out of memory");
++ goto error_return;
++ }
++
++ /* Accept a new TCP connection on a server socket */
++ sock->channel = syncer.Accept (server->channel, acc_res);
++
++ if ( acc_res != PP_OK ) {
++ SDLNet_SetError("accept() failed");
++ goto error_return;
++ }
++
++
++ {
++ /* int flags = fcntl(sock->channel, F_GETFL, 0);
++ fcntl(sock->channel, F_SETFL, flags & ~O_NONBLOCK); */
++ }
++
++ syncer.NetToIp ((sock->channel).GetRemoteAddress (), &sock->remoteAddress);
++
++ sock->sflag = 0;
++ sock->ready = 0;
++
++ /* The socket is ready */
++ return(sock);
++
++error_return:
++ SDLNet_TCP_Close(sock);
++ return(NULL);
+}
+
-+/*
-+ * Weak aliases for applications that use certain private entry points,
-+ * and fail to include <arpa/inet.h>.
-+ */
-+#undef inet_addr
-+__weak_reference(__inet_addr, inet_addr);
-+#undef inet_aton
-+__weak_reference(__inet_aton, inet_aton);
-
-diff -urN SDL_net-1.2.7/SDLnet.c SDL_net-1.2.7-nacl/SDLnet.c
---- SDL_net-1.2.7/SDLnet.c 2007-07-02 06:04:03.000000000 +0400
-+++ SDL_net-1.2.7-nacl/SDLnet.c 2013-11-03 00:43:36.859998000 +0400
-@@ -29,6 +29,8 @@
- #include "SDLnetsys.h"
- #include "SDL_net.h"
-
-+#include "inet_addr.c"
++/* Get the IP address of the remote system associated with the socket.
++ If the socket is a server socket, this function returns NULL.
++*/
++IPaddress *SDLNet_TCP_GetPeerAddress(TCPsocket sock)
++{
++ if ( sock->sflag ) {
++ return(NULL);
++ }
++ return(&sock->remoteAddress);
++}
+
-
- const SDL_version *SDLNet_Linked_Version(void)
- {
-@@ -344,7 +346,7 @@
-
- hp = gethostbyname(host);
- if ( hp ) {
-- memcpy(&address->host,hp->h_addr,hp->h_length);
-+ memcpy(&address->host,hp->h_addr_list[0],hp->h_length);
- } else {
- retval = -1;
- }
-@@ -368,8 +370,7 @@
- const char *SDLNet_ResolveIP(IPaddress *ip)
- {
- struct hostent *hp;
--
-- hp = gethostbyaddr((char *)&ip->host, 4, AF_INET);
-+ hp = NULL;
- if ( hp != NULL ) {
- return hp->h_name;
- }
-
++/* Send 'len' bytes of 'data' over the non-server socket 'sock'
++ This function returns the actual amount of data sent. If the return value
++ is less than the amount of data sent, then either the remote connection was
++ closed, or an unknown socket error occurred.
++*/
++int SDLNet_TCP_Send(TCPsocket sock, const void *datap, int len)
++{
++ SDLNetSynchronizer syncer;
++ Uint8 *data = (Uint8 *)datap; /* For pointer arithmetic */
++ int sent, left;
++
++ /* Server sockets are for accepting connections only */
++ if ( sock->sflag ) {
++ SDLNet_SetError("Server sockets cannot send");
++ return(-1);
++ }
++
++ /* Keep sending data until it's sent or an error occurs */
++ left = len;
++ sent = 0;
++ errno = 0;
++ do {
++ len = syncer.Write (sock->channel, (const char *) data, left);
++ if ( len > 0 ) {
++ sent += len;
++ left -= len;
++ data += len;
++ }
++ } while ( (left > 0) && (len >= 0 || errno == EINTR) );
++
++ return(sent);
++}
++
++/* Receive up to 'maxlen' bytes of data over the non-server socket 'sock',
++ and store them in the buffer pointed to by 'data'.
++ This function returns the actual amount of data received. If the return
++ value is less than or equal to zero, then either the remote connection was
++ closed, or an unknown socket error occurred.
++*/
++int SDLNet_TCP_Recv(TCPsocket sock, void *data, int maxlen)
++{
++ SDLNetSynchronizer syncer;
++ int len = 0;
++
++ /* Server sockets are for accepting connections only */
++ if ( sock->sflag ) {
++ SDLNet_SetError("Server sockets cannot receive");
++ return(-1);
++ }
++
++ if ( sock->ready && maxlen > 0 ) {
++ len = std::min (sock->bufferAmount - sock->bufferOffset, maxlen);
++ memcpy (data, sock->buffer + sock->bufferOffset, len);
++ sock->bufferOffset += len;
++ if ( sock->bufferOffset == sock->bufferAmount )
++ sock->ready = 0;
++ }
++
++ if ( sock->ready == 0 && sock->readInProgress == 0) {
++ if (__read_syncer == NULL)
++ __read_syncer = new SDLNetSynchronizer ();
++ __read_syncer->ReadAsync (sock);
++ }
++
++ return(len);
++}
++
++/* Close a TCP network socket */
++void SDLNet_TCP_Close(TCPsocket sock)
++{
++ SDLNetSynchronizer syncer;
++ if ( sock != NULL ) {
++ sock->channel.Close ();
++ free (sock);
++ }
++}