From c9bc1e135a50e43b995cc0a3faa41088b58e47c4 Mon Sep 17 00:00:00 2001 From: Spoike Date: Sun, 24 Nov 2013 16:35:52 +0000 Subject: [PATCH] nacl tweaks. attempt to list local ips properly on linux (needed for ICE). git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4532 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- engine/client/cl_main.c | 2 +- engine/common/net_wins.c | 379 ++++++++++++++++++++++++-------------- engine/common/plugin.c | 2 +- engine/nacl/gl_vidppapi.c | 3 +- engine/nacl/sys_ppapi.c | 18 +- plugins/Makefile | 2 +- 6 files changed, 266 insertions(+), 140 deletions(-) diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index 9405b4e20..9dfa74270 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -2571,7 +2571,7 @@ client_connect: //fixme: make function char cmdtext[2048]; Con_TPrintf (TLC_CONLESS_CONCMD); - if (net_from.type != net_local_cl_ipadr.type + if (net_from.type != net_local_cl_ipadr.type || net_from.type != NA_IP || ((*(unsigned *)net_from.address.ip != *(unsigned *)net_local_cl_ipadr.address.ip) && (*(unsigned *)net_from.address.ip != htonl(INADDR_LOOPBACK)))) { Con_TPrintf (TLC_CMDFROMREMOTE); diff --git a/engine/common/net_wins.c b/engine/common/net_wins.c index 4f3af55e7..5d7c7ace2 100644 --- a/engine/common/net_wins.c +++ b/engine/common/net_wins.c @@ -2017,6 +2017,162 @@ void FTENET_Generic_Close(ftenet_generic_connection_t *con) Z_Free(con); } +#ifdef _WIN32 +int FTENET_GetLocalAddress(netadr_t *out, int port, int count, qboolean ipx, qboolean ipv4, qboolean ipv6) +{ + //in win32, we can look up our own hostname to retrieve a list of local interface addresses. + netadr_t adr; +#ifdef USE_GETHOSTNAME_LOCALLISTING + char adrs[MAX_ADR_SIZE]; + int b; +#endif + int idx = 0; + + gethostname(adrs, sizeof(adrs)); +#ifdef IPPROTO_IPV6 + if (pgetaddrinfo) + { + struct addrinfo hints, *result, *itr; + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = 0; /* Allow IPv4 or IPv6 */ + hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */ + hints.ai_flags = 0; + hints.ai_protocol = 0; /* Any protocol */ + + if (pgetaddrinfo(adrs, NULL, &hints, &result) == 0) + { + for (itr = result; itr; itr = itr->ai_next) + { + if ((itr->ai_addr->sa_family == AF_INET && ipv4) + || (itr->ai_addr->sa_family == AF_INET6 && ipv6) +#ifdef USEIPX + || (itr->ai_addr->sa_family == AF_IPX && ipx) +#endif + ) + if (idx++ == count) + { + SockadrToNetadr((struct sockaddr_qstorage*)itr->ai_addr, out); + out->port = port; + } + } + pfreeaddrinfo(result); + + /*if none found, fill in the 0.0.0.0 or whatever*/ + if (!idx) + { + idx++; + memset(out, 0, sizeof(*out)); + out->port = port; + if (ipv6) + out->type = NA_IPV6; + else if (ipv4) + out->type = NA_IP; + else if (ipx) + out->type = NA_IPX; + else + out->type = NA_INVALID; + } + } + } + else +#endif + { + struct hostent *h; + h = gethostbyname(adrs); + b = 0; +#ifdef HAVE_IPV4 + if(h && h->h_addrtype == AF_INET) + { + for (b = 0; h->h_addr_list[b]; b++) + { + struct sockaddr_in from; + from.sin_family = AF_INET; + memcpy(&from.sin_addr, h->h_addr_list[b], sizeof(&from.sin_addr)); + SockadrToNetadr((struct sockaddr_qstorage*)&from, &adr); + if (idx++ == count) + *out = adr; + } + } +#endif +#ifdef IPPROTO_IPV6 + if(h && h->h_addrtype == AF_INET6) + { + for (b = 0; h->h_addr_list[b]; b++) + { + struct sockaddr_in6 from; + from.sin6_family = AF_INET6; + memcpy(&from.sin6_addr, h->h_addr_list[b], sizeof(((struct sockaddr_in6*)&from)->sin6_addr)); + SockadrToNetadr((struct sockaddr_qstorage*)&from, &adr); + if (idx++ == count) + *out = adr; + } + } +#endif + } + return idx; +} + +#elif defined(__linux__) +//in linux, looking up our own hostname to retrieve a list of local interface addresses will give no indication that other systems are able to do the same thing and is thus not supported. +//there's some special api instead +//glibc 2.3. +//also available with certain bsds. +#include + +static struct ifaddrs *iflist; +unsigned int iftime; //requery sometimes. +int FTENET_GetLocalAddress(netadr_t *out, int port, int count, qboolean ipx, qboolean ipv4, qboolean ipv6 +{ + struct ifaddrs *ifa; + int fam; + unsigned int time = Sys_Milliseconds(); + if (time - iftime > 1000 && iflist) + { + freeifaddrs(iflist) + iflist = NULL; + } + if (!iflist) + { + iftime = time; + getifaddrs(&iflist); + } + + for (ifa = iflist; ifa; ifa = ifa->ifa_next) + { + //can happen if the interface is not bound. + if (ifa->ifa_addr == NULL) + continue; + + //filter out families that we're not interested in. + fam = ifa->ifa_addr->sa_family; + if ( +#ifdef HAVE_IPV4 + (fam == AF_INET && ipv4) || +#endif +#ifdef HAVE_IPV6 + (fam == AF_INET6 && ipv6) || +#endif +#ifdef USEIPX + (fam == AF_IPX && ipx) || +#endif + 0) + { + if (idx++ == count) + { + SockadrToNetadr(&ifa->ifa_addr, out); + out->port = port; + } + } + } + return idx; +} +#else +int FTENET_GetLocalAddress(netadr_t *out, int count) +{ + return 0; +} +#endif + int FTENET_Generic_GetLocalAddress(ftenet_generic_connection_t *con, netadr_t *out, int count) { #ifndef HAVE_PACKET @@ -2025,10 +2181,6 @@ int FTENET_Generic_GetLocalAddress(ftenet_generic_connection_t *con, netadr_t *o struct sockaddr_qstorage from; int fromsize = sizeof(from); netadr_t adr; -#ifdef USE_GETHOSTNAME_LOCALLISTING - char adrs[MAX_ADR_SIZE]; - int b; -#endif int idx = 0; if (getsockname (con->thesocket, (struct sockaddr*)&from, &fromsize) != -1) @@ -2037,6 +2189,7 @@ int FTENET_Generic_GetLocalAddress(ftenet_generic_connection_t *con, netadr_t *o SockadrToNetadr(&from, &adr); #ifdef USE_GETHOSTNAME_LOCALLISTING + //if its bound to 'any' address, ask the system what addresses it actually accepts. if (adr.type == NA_IPV6 && !*(int*)&adr.address.ip6[0] && !*(int*)&adr.address.ip6[4] && @@ -2044,117 +2197,43 @@ int FTENET_Generic_GetLocalAddress(ftenet_generic_connection_t *con, netadr_t *o *(short*)&adr.address.ip6[10]==(short)0xffff && !*(int*)&adr.address.ip6[12]) { - /*ipv4-mapped address ANY, pretend we read blank*/ - b = sizeof(adr.address); + //ipv6 socket bound to the ipv4-any address is a bit weird, but oh well. + //FIXME: should we first validate that we support hybrid sockets? + idx = FTENET_GetLocalAddress(out, adr.port, count, false, true, false); } else { + int b; for (b = 0; b < sizeof(adr.address); b++) if (((unsigned char*)&adr.address)[b] != 0) break; - } - if (b == sizeof(adr.address)) - { - gethostname(adrs, sizeof(adrs)); -#ifdef IPPROTO_IPV6 - if (pgetaddrinfo) - { - struct addrinfo hints, *result, *itr; - memset(&hints, 0, sizeof(struct addrinfo)); - hints.ai_family = 0; /* Allow IPv4 or IPv6 */ - hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */ - hints.ai_flags = 0; - hints.ai_protocol = 0; /* Any protocol */ - if (pgetaddrinfo(adrs, NULL, &hints, &result) != 0) + if (b == sizeof(adr.address)) + { + qboolean ipx=false, ipv4=false, ipv6=false; + if (adr.type == NA_IP) + ipv4 = true; + else if (adr.type == NA_IPX) + ipx = true; + else if (adr.type == NA_IPV6) { - if (idx++ == count) - *out = adr; - } - else - { - for (itr = result; itr; itr = itr->ai_next) - { - if (itr->ai_addr->sa_family != ((struct sockaddr_in*)&from)->sin_family) - { #ifdef IPV6_V6ONLY - if (((struct sockaddr_in*)&from)->sin_family == AF_INET6 && itr->ai_addr->sa_family == AF_INET) - { - int ipv6only = true; - int optlen = sizeof(ipv6only); - getsockopt(con->thesocket, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&ipv6only, &optlen); - if (ipv6only) - continue; - } - else + int ipv6only = true; + int optlen = sizeof(ipv6only); + getsockopt(con->thesocket, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&ipv6only, &optlen); + if (!ipv6only) + ipv4 = true; #endif - continue; - } + ipv6 = true; + } - if (itr->ai_addr->sa_family == AF_INET - || itr->ai_addr->sa_family == AF_INET6 -#ifdef USEIPX - || itr->ai_addr->sa_family == AF_IPX -#endif - ) - if (idx++ == count) - { - SockadrToNetadr((struct sockaddr_qstorage*)itr->ai_addr, out); - out->port = ((struct sockaddr_in*)&from)->sin_port; - } - } - pfreeaddrinfo(result); - - /*if none found, fill in the 0.0.0.0 or whatever*/ - if (!idx) - { - idx++; - *out = adr; - } - } - } - else -#endif - { - struct hostent *h; - h = gethostbyname(adrs); - b = 0; -#ifdef HAVE_IPV4 - if(h && h->h_addrtype == AF_INET) - { - for (b = 0; h->h_addr_list[b]; b++) - { - ((struct sockaddr_in*)&from)->sin_family = AF_INET; - memcpy(&((struct sockaddr_in*)&from)->sin_addr, h->h_addr_list[b], sizeof(((struct sockaddr_in*)&from)->sin_addr)); - SockadrToNetadr(&from, &adr); - if (idx++ == count) - *out = adr; - } - } -#endif -#ifdef IPPROTO_IPV6 - if(h && h->h_addrtype == AF_INET6) - { - for (b = 0; h->h_addr_list[b]; b++) - { - ((struct sockaddr_in*)&from)->sin_family = AF_INET6; - memcpy(&((struct sockaddr_in6*)&from)->sin6_addr, h->h_addr_list[b], sizeof(((struct sockaddr_in6*)&from)->sin6_addr)); - SockadrToNetadr(&from, &adr); - if (idx++ == count) - *out = adr; - } - } -#endif - - if (b == 0) - { - if (idx++ == count) - *out = adr; - } + idx = FTENET_GetLocalAddress(out, adr.port, count, ipx, ipv4, ipv6); } } - else #endif + + //and use the bound address (even if its 0.0.0.0) if we didn't grab a list from the system. + if (!idx) { if (adr.type == NA_IPV6 && !*(int*)&adr.address.ip6[0] && @@ -2457,7 +2536,7 @@ ftenet_generic_connection_t *FTENET_Generic_EstablishConnection(int adrfamily, i // // determine my name & address if we don't already know it // - if (!net_local_cl_ipadr.type == NA_INVALID) + if (net_local_cl_ipadr.type == NA_INVALID) NET_GetLocalAddress (newsocket, &net_local_cl_ipadr); newcon = Z_Malloc(sizeof(*newcon)); @@ -4143,10 +4222,12 @@ static ftenet_generic_connection_t *FTENET_WebSocket_EstablishConnection(qboolea #include #include #include +#include #include extern PPB_Core *ppb_core; extern PPB_WebSocket *ppb_websocket_interface; extern PPB_Var *ppb_var_interface; +extern PPB_VarArrayBuffer *ppb_vararraybuffer_interface; extern PP_Instance pp_instance; typedef struct @@ -4223,36 +4304,50 @@ static qboolean FTENET_NaClWebSocket_GetPacket(ftenet_generic_connection_t *gcon int len = 0; if (wsc->havepacket) { - unsigned char *utf8 = (unsigned char *)ppb_var_interface->VarToUtf8(wsc->incomingpacket, &len); - unsigned char *out = (unsigned char *)net_message_buffer; - - wsc->havepacket = false; - memcpy(&net_from, &wsc->remoteadr, sizeof(net_from)); - - while(len && out < net_message_buffer + sizeof(net_message_buffer)) + if (wsc->incomingpacket.type == PP_VARTYPE_ARRAY_BUFFER) { - if ((*utf8 & 0xe0)==0xc0 && len > 1) + uint32_t length; + void *buf = ppb_vararraybuffer_interface->Map(wsc->incomingpacket); + if (buf && ppb_vararraybuffer_interface->ByteLength(wsc->incomingpacket, &length)) { - *out = ((utf8[0] & 0x1f)<<6) | ((utf8[1] & 0x3f)<<0); - utf8+=2; - len -= 2; - } - else if (*utf8 & 0x80) - { - *out = '?'; - utf8++; - len -= 1; + net_message.cursize = length; + memcpy(net_message_buffer, buf, length); + ppb_vararraybuffer_interface->Unmap(wsc->incomingpacket); } else - { - *out = utf8[0]; - utf8++; - len -= 1; - } - out++; + net_message.cursize = 0; } - net_message.cursize = out - net_message_buffer; + else + { + unsigned char *utf8 = (unsigned char *)ppb_var_interface->VarToUtf8(wsc->incomingpacket, &len); + unsigned char *out = (unsigned char *)net_message_buffer; + while(len && out < net_message_buffer + sizeof(net_message_buffer)) + { + if ((*utf8 & 0xe0)==0xc0 && len > 1) + { + *out = ((utf8[0] & 0x1f)<<6) | ((utf8[1] & 0x3f)<<0); + utf8+=2; + len -= 2; + } + else if (*utf8 & 0x80) + { + *out = '?'; + utf8++; + len -= 1; + } + else + { + *out = utf8[0]; + utf8++; + len -= 1; + } + out++; + } + net_message.cursize = out - net_message_buffer; + } + memcpy(&net_from, &wsc->remoteadr, sizeof(net_from)); + wsc->havepacket = false; ppb_var_interface->Release(wsc->incomingpacket); if (!wsc->failed) @@ -4278,12 +4373,20 @@ static qboolean FTENET_NaClWebSocket_SendPacket(ftenet_generic_connection_t *gco { ftenet_websocket_connection_t *wsc = (void*)gcon; int res; - int outchars = 0; - unsigned char outdata[length*2+1]; - unsigned char *out=outdata, *in=data; if (wsc->failed) return false; +#if 0 + struct PP_Var str = ppb_vararraybuffer_interface->Create(length); + void *out = ppb_vararraybuffer_interface->Map(wsc->incomingpacket); + if (!out) + return false; + memcpy(out, data, length); + ppb_vararraybuffer_interface->Unmap(wsc->incomingpacket); +#else + int outchars = 0; + unsigned char outdata[length*2+1]; + unsigned char *out=outdata, *in=data; while(length-->0) { if (!*in) @@ -4304,6 +4407,7 @@ static qboolean FTENET_NaClWebSocket_SendPacket(ftenet_generic_connection_t *gco } *out = 0; struct PP_Var str = ppb_var_interface->VarFromUtf8(outdata, out - outdata); +#endif res = ppb_websocket_interface->SendMessage(wsc->sock, str); // Sys_Printf("FTENET_WebSocket_SendPacket: result %i\n", res); ppb_var_interface->Release(str); @@ -4905,11 +5009,12 @@ qboolean NET_Sleep(int msec, qboolean stdinissocket) } #endif +//this function is used to determine the 'default' local address. +//this is used for compat with gamespy which insists on sending us a packet via that interface and not something more sensible like 127.0.0.1 +//thus its only needed on windows and with ipv4. void NET_GetLocalAddress (int socket, netadr_t *out) { -#ifndef HAVE_PACKET - out->type = NA_INVALID; -#else +#ifdef _WIN32 char buff[512]; char adrbuf[MAX_ADR_SIZE]; struct sockaddr_qstorage address; @@ -4940,11 +5045,15 @@ void NET_GetLocalAddress (int socket, netadr_t *out) *(int *)out->address.ip = *(int *)adr.address.ip; //change it to what the machine says it is, rather than the socket. } - if (notvalid) - Con_Printf("Couldn't detect local ip\n"); - else + if (!notvalid) + { Con_TPrintf(TL_IPADDRESSIS, NET_AdrToString (adrbuf, sizeof(adrbuf), out) ); + return; + } + Con_Printf("Couldn't detect local ip\n"); #endif + + out->type = NA_INVALID; } #ifndef CLIENTONLY diff --git a/engine/common/plugin.c b/engine/common/plugin.c index 1c589e879..f2f021467 100644 --- a/engine/common/plugin.c +++ b/engine/common/plugin.c @@ -1326,7 +1326,7 @@ void Plug_Initialise(qboolean fromgamedir) if (!fromgamedir) { FS_NativePath("", FS_BINARYPATH, nat, sizeof(nat)); - Con_Printf("Loading plugins from %s\n", nat); + Con_DPrintf("Loading plugins from \"%s\"\n", nat); Sys_EnumerateFiles(nat, "fteplug_*" ARCH_CPU_POSTFIX ARCH_DL_POSTFIX, Plug_EnumeratedRoot, NULL, NULL); } if (fromgamedir) diff --git a/engine/nacl/gl_vidppapi.c b/engine/nacl/gl_vidppapi.c index ad265c81e..c027dd130 100644 --- a/engine/nacl/gl_vidppapi.c +++ b/engine/nacl/gl_vidppapi.c @@ -62,7 +62,8 @@ void GL_DoSwap(void) case PP_OK: break; case PP_ERROR_INPROGRESS: - Con_DPrintf("chrome can't handle vid_wait 0\n"); + Con_DPrintf("chrome still can't handle vid_wait 0. forcing vsync\n"); + _vid_wait_override.ival = 1; break; default: Con_DPrintf("unknown error on SwapBuffers call\n"); diff --git a/engine/nacl/sys_ppapi.c b/engine/nacl/sys_ppapi.c index 91f1fd19f..7dfe30fc8 100644 --- a/engine/nacl/sys_ppapi.c +++ b/engine/nacl/sys_ppapi.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -34,6 +35,7 @@ PPB_Graphics3D *graphics3d_interface = NULL; PPB_Instance *instance_interface = NULL; PPB_Messaging *ppb_messaging_interface = NULL; PPB_Var *ppb_var_interface = NULL; +PPB_VarArrayBuffer *ppb_vararraybuffer_interface = NULL; PPB_InputEvent *ppb_inputevent_interface = NULL; PPB_KeyboardInputEvent *ppb_keyboardinputevent_interface = NULL; PPB_MouseInputEvent *ppb_mouseinputevent_interface = NULL; @@ -502,7 +504,15 @@ static PP_Bool InputEvent_HandleEvent(PP_Instance pp_instance, PP_Resource resou // Con_Printf("rawkeydown\n"); return PP_FALSE; case PP_INPUTEVENT_TYPE_KEYDOWN: - IN_KeyEvent(0, 1, domkeytoquake(ppb_keyboardinputevent_interface->GetKeyCode(resource)), 0); + { + int k = domkeytoquake(ppb_keyboardinputevent_interface->GetKeyCode(resource)); + int u = 0; + if (k == K_TAB) + u = '\t'; + if (k == K_ENTER) + u = '\r'; + IN_KeyEvent(0, 1, k, u); + } return PP_FALSE; case PP_INPUTEVENT_TYPE_KEYUP: IN_KeyEvent(0, 0, domkeytoquake(ppb_keyboardinputevent_interface->GetKeyCode(resource)), 0); @@ -558,6 +568,10 @@ static PP_Bool InputEvent_HandleEvent(PP_Instance pp_instance, PP_Resource resou len--; } + //these keys are handled by actual proper keys + if (c == '\t' || c == '\r') + continue; + IN_KeyEvent(0, true, 0, c); IN_KeyEvent(0, false, 0, c); } @@ -585,6 +599,7 @@ static void Instance_DidChangeView(PP_Instance instance, PP_Resource view_resour } static void Instance_DidChangeFocus(PP_Instance instance, PP_Bool has_focus) { +// ActiveApp = has_focus; } static PP_Bool Instance_HandleDocumentLoad(PP_Instance instance, PP_Resource url_loader) { @@ -616,6 +631,7 @@ PP_EXPORT int32_t PPP_InitializeModule(PP_Module a_module_id, PPB_GetInterface g ppb_fullscreen_interface = (PPB_Fullscreen*)(get_browser(PPB_FULLSCREEN_INTERFACE)); ppb_websocket_interface = (PPB_WebSocket*)(get_browser(PPB_WEBSOCKET_INTERFACE)); ppb_view_instance = (PPB_View*)(get_browser(PPB_VIEW_INTERFACE)); + ppb_vararraybuffer_interface = (PPB_View*)(get_browser(PPB_VAR_ARRAY_BUFFER_INTERFACE)); glInitializePPAPI(sys_gbi); diff --git a/plugins/Makefile b/plugins/Makefile index a0667aec5..667bbef58 100644 --- a/plugins/Makefile +++ b/plugins/Makefile @@ -109,7 +109,7 @@ distclean: $(OUT_DIR)/fteplug_avplug$(PLUG_NATIVE_EXT): avplug/avencode.c avplug/avdecode.c plugin.c qvm_api.c $(CC) $(BASE_CFLAGS) $(CFLAGS) -DFTEPLUGIN -s -o $(OUT_DIR)/fteplug_avplug$(PLUG_NATIVE_EXT) -shared $(PLUG_CFLAGS) -Iavplug/msvc_lib $^ $(PLUG_DEFFILE) $(PLUG_LDFLAGS) -lavcodec -lavformat -lavutil -lswscale -native: $(OUT_DIR)/fteplug_avplug$(PLUG_NATIVE_EXT) +#native: $(OUT_DIR)/fteplug_avplug$(PLUG_NATIVE_EXT) $(OUT_DIR)/fteplug_mpq$(PLUG_NATIVE_EXT): mpq/fs_mpq.c mpq/blast.c plugin.c qvm_api.c $(CC) $(BASE_CFLAGS) $(CFLAGS) -DFTEPLUGIN -o $(OUT_DIR)/fteplug_mpq$(PLUG_NATIVE_EXT) -shared $(PLUG_CFLAGS) -Impq $^ $(PLUG_DEFFILE) $(PLUG_LDFLAGS)