Giter Club home page Giter Club logo

lua-websockets's Introduction

Not maintained / maintainer wanted !!!!

If someone wants to maintain / take ownership of this project, reach out to me (issue, email). I like Lua very much, but I don't have enough time / resources to stay engaged with it.

About

This project provides Lua modules for Websocket Version 13 conformant clients and servers. Build Status Coverage Status

The minified version is only ~10k bytes in size.

Clients are available in three different flavours:

  • synchronous
  • coroutine based (copas)
  • asynchronous (lua-ev)

Servers are available as two different flavours:

A webserver is NOT part of lua-websockets. If you are looking for a feature rich webserver framework, have a look at orbit or others. It is no problem to work with a "normal" webserver and lua-websockets side by side (two processes, different ports), since websockets are not subject of the 'Same origin policy'.

Usage

copas echo server

This implements a basic echo server via Websockets protocol. Once you are connected with the server, all messages you send will be returned ('echoed') by the server immediately.

local copas = require'copas'

-- create a copas webserver and start listening
local server = require'websocket'.server.copas.listen
{
  -- listen on port 8080
  port = 8080,
  -- the protocols field holds
  --   key: protocol name
  --   value: callback on new connection
  protocols = {
    -- this callback is called, whenever a new client connects.
    -- ws is a new websocket instance
    echo = function(ws)
      while true do
        local message = ws:receive()
        if message then
           ws:send(message)
        else
           ws:close()
           return
        end
      end
    end
  }
}

-- use the copas loop
copas.loop()

lua-ev echo server

This implements a basic echo server via Websockets protocol. Once you are connected with the server, all messages you send will be returned ('echoed') by the server immediately.

local ev = require'ev'

-- create a copas webserver and start listening
local server = require'websocket'.server.ev.listen
{
  -- listen on port 8080
  port = 8080,
  -- the protocols field holds
  --   key: protocol name
  --   value: callback on new connection
  protocols = {
    -- this callback is called, whenever a new client connects.
    -- ws is a new websocket instance
    echo = function(ws)
      ws:on_message(function(ws,message)
          ws:send(message)
        end)

      -- this is optional
      ws:on_close(function()
          ws:close()
        end)
    end
  }
}

-- use the lua-ev loop
ev.Loop.default:loop()

Running test-server examples

The folder test-server contains two re-implementations of the libwebsocket test-server.c example.

cd test-server
lua test-server-ev.lua
cd test-server
lua test-server-copas.lua

Connect to the from Javascript (e.g. chrome's debugging console) like this:

var echoWs = new WebSocket('ws://127.0.0.1:8002','echo');

Dependencies

The client and server modules depend on:

  • luasocket
  • luabitop (if not using Lua 5.2 nor luajit)
  • luasec
  • copas (optionally)
  • lua-ev (optionally)

Install

$ git clone git://github.com/lipp/lua-websockets.git
$ cd lua-websockets
$ luarocks make rockspecs/lua-websockets-scm-1.rockspec

Minify

A squishy file for squish is provided. Creating the minified version (~10k) can be created with:

$ squish --gzip

The minifed version has be to be installed manually though.

Tests

Running tests requires:

docker build .

The first run will take A WHILE.

lua-websockets's People

Contributors

afan1 avatar davidxifeng avatar delaguardo avatar lipp avatar moteus avatar nolar avatar novustheory avatar ntd avatar satom99 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

lua-websockets's Issues

Can you please clarify the installation process?

On windows 8, the last command
luarocks make rockspecs/lua-websockets-scm-1.rockspec
just prints
'"C:\Program Files (x86)\LuaRocks\lua5.1.exe"' is not recognized as internal or external command, operable program or batch file

Anyway, what should i do with results of its execution to compile examples?

handshake.http_headers won't read Sec-WebSocket-Accept line

I'm connecting to a simple echo server using websocket.io on localhost. The Sec-WebSocket-Accept line sent from this websocket.io server does not end with a \r\n so the key check fails.

Change made to handshake.http_headers

--for line in request:gmatch('[^\r\n]*\r\n') do
for line in request:gmatch("[^\r\n]+") do

Tested on both echo.websocket.org and localhost.

SSL?

A quick question: I have a websocket server behind https. How
hard would it be to use lua-websockets in such a context?

Cheers
/Joakim

Rmove `struct` deps

I just public version of frame.lua that have no deps from struct library.
Also it reduce number of string.sub operation during decoding so it faster when decoding multiple frames in single packet. This is drop in replacement but it also provide new function decode_by_pos which returns position of next frame instead of rest string.
It still needs more tests but this is my decode benchmark with luajit
I do not make PR because this is not fully tested and this is easy run benchmarks based on websocket.frame but when I done I make PR.

>luajit frame_decode.lua
---------------------------------------
Lua  version: LuaJIT 2.0.1
---------------------------------------

Verify done
---------------------------------------
Websocket (struct)      : frame  131[b] masked 1   38[sec]     1[frame/packet] 25936[frame/sec]
Websocket (bit only)    : frame  131[b] masked 1   30[sec]     1[frame/packet] 32988[frame/sec]
Websocket (bit only/pos): frame  131[b] masked 1   30[sec]     1[frame/packet] 32888[frame/sec]
---------------------------------------
Websocket (struct)      : frame  131[b] masked 1   55[sec]   100[frame/packet] 17903[frame/sec]
Websocket (bit only)    : frame  131[b] masked 1   37[sec]   100[frame/packet] 26562[frame/sec]
Websocket (bit only/pos): frame  131[b] masked 1   30[sec]   100[frame/packet] 33123[frame/sec]
---------------------------------------
Websocket (struct)      : frame  131[b] masked 1  165[sec]  1000[frame/packet] 6048[frame/sec]
Websocket (bit only)    : frame  131[b] masked 1   72[sec]  1000[frame/packet] 13797[frame/sec]
Websocket (bit only/pos): frame  131[b] masked 1   29[sec]  1000[frame/packet] 33979[frame/sec]
---------------------------------------
Websocket (struct)      : frame  127[b] masked 0  104[sec]     1[frame/packet] 959551[frame/sec]
Websocket (bit only)    : frame  127[b] masked 0  106[sec]     1[frame/packet] 934705[frame/sec]
Websocket (bit only/pos): frame  127[b] masked 0   94[sec]     1[frame/packet] 1055595[frame/sec]
---------------------------------------
Websocket (struct)      : frame  127[b] masked 0  120[sec]   100[frame/packet] 82839[frame/sec]
Websocket (bit only)    : frame  127[b] masked 0   70[sec]   100[frame/packet] 142554[frame/sec]
Websocket (bit only/pos): frame  127[b] masked 0    7[sec]   100[frame/packet] 1265617[frame/sec]
---------------------------------------
Websocket (struct)      : frame  127[b] masked 0  918[sec]  1000[frame/packet] 10889[frame/sec]
Websocket (bit only)    : frame  127[b] masked 0  433[sec]  1000[frame/packet] 23072[frame/sec]
Websocket (bit only/pos): frame  127[b] masked 0    7[sec]  1000[frame/packet] 1254069[frame/sec]
---------------------------------------

Question: Copas Receive

I hope you don't mind. This is more of a question than an issue. Do you know of any way to timeout the ws:receive() or whole sockets using copas and your lib? Maybe I'm missing something, I'm not sure.

Server Poll support (No Copas/No Ev)

You use ev and copas, but no pure lua based system that would let me call a function to check for updates( async). This makes this unusable for me, because otherwise it blocks Lua.

Compile with Copas only

Hi,
I would like to use lua-websocket on a microcontroller with Lua, and without operating system. That means that I can not use libev, bacause AFAIK libev depends on the mechanisms of OS (like epoll or POSIX select).

As I understand copas is pure Lua implementation of cooperative multithreading and depends only to Lua supported coroutines, so completely independent of OS, wich makes it good candidate for running it on bare-metal microcontroller (actually I am using eLua: http://www.eluaproject.net/).

Is it possible to compile lua-websockets with Copas support only, and how to achieve that?

Not only that I do not need libev for runtime, but also i am using Cygwin host for compilation, and over there I have:

/usr/lib/gcc/x86_64-pc-cygwin/4.9.2/../../../../x86_64-pc-cygwin/bin/ld: cannot find -lev
collect2: error: ld returned 1 exit status

Error: Build error: Failed compiling module ev.so

although I compiled and installed libev in Cygwin (I did it just to compile lua-websockets, not really because I need it).

BR,
Drasko

Unsupported protocol: "null" using http://www.websocket.org/echo.html

Hi @lipp,
When I use http://www.websocket.org/echo.html to test the ws:// request,

  1. Connection is established successfully
  2. Message is sent to the lua-websockets server
  3. I see "Unsupported protocol: "null" on server side
  4. No response received.
    Same test work fine with tornado.

If I try using my local javascript, it works fine.

function WebSocketTest()
{
if ("WebSocket" in window)
{
alert("WebSocket is supported by your Browser!");
// Let us open a web socket
var ws = new WebSocket("ws://ipaddress:8080/", 'echo');

 ws.onopen = function()
 {
    // Web Socket is connected, send data using send()
    ws.send('{"id":"dsfsdf", "body":"Rock it with HTML5 WebSocket"}');
    alert("Message is sent...");
 };
 ws.onmessage = function (evt)
 {
    var received_msg = evt.data;
    alert("Message is received..." );
    alert("received:" + received_msg)
 };
 ws.onclose = function()
 {
    // websocket is closed.
    alert("Connection is closed...");
 };

 ws.onerror = function(evt)
 {
    // Web Socket error
    var msg_error = evt.error;
    alert("error:");
    alert(msg_error);
 };

}
else
{
// The browser doesn't support WebSocket
alert("WebSocket NOT supported by your Browser!");
}
}

pure-lua too long message errors

I started trying pure-lua version and I found an issue.

When I send a message from browser it fails if the message is too long.

this message works:
{"method":"tasks#list","id":"tasks-1-F6CE0D2C-A000-4C0A-8E93-E7A992BE714D","params":{"showCompleted":true,"showDelet":false}}

this (and any longer) doesn't work:
{"method":"tasks#list","id":"tasks-1-F6CE0D2C-A000-4C0A-8E93-E7A992BE714D","params":{"showCompleted":true,"showDelete":false}}

Too long message gives error: lua/websocket/frame.lua:91: INVALID PAYLOAD

Also ws:broadcast(answer) fails to send anything if answer is too long. Message is received in the browser, but data is empty.

Accepting connections from multiple clients

It seems that the current copas example allows accepting a connection from single Websocket client, what is the correct method to extend it to allow support from multiple ones?

"bad protocol" Error

I tried with several WebSocket clients and I am constantly getting "bad protocol" error.

Is the code functional?

I am using an example "copas echo server" with freshly installed lua5.1 on Debian Linux:

drasko@Lenin:~/lua$ lua5.1 server.lua 
bad protocol

I tried test with both this code from the browser (both Chrome and Firefox):

<!doctype html>
<html><head>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
    <link href="bootstrap/css/bootstrap.min.css" rel="stylesheet">
    <script src="bootstrap/js/bootstrap.min.js"></script>

    </head>

    <body lang="en">
    <h1>WebSocket Echo example</h1>
    <button id="btnTest" type="button" class="btn btn-primary btn-lg">Primary</button>


    <script>
        var port = "8080";
        var uri = "/";
        var host = "localhost";
        ws = new WebSocket("ws://" + host + ":" + port + uri);
        ws.onopen    = function()  {console.log('[*] open', ws.protocol);};
        ws.onclose   = function()  {console.log('[*] close');};
        $(document).ready(function(){
            $("#btnTest").click(function(){
                ws.send("TEST");
            });
        });
    </script>

</body></html>

And also this code from Python: https://github.com/liris/websocket-client

Same result - "bad protocol".

Best regards,
Drasko

windows binaries

Has anyone compiled windows binaries and willing to share them?

Fail when client use not supported protocol handler

Error


CALLBACK FAILED: /usr/local/share/lua/5.1/websocket/server_ev.lua:104: attempt to index field '?' (a nil value)

Fix


clients[protocol][self] = nil

if clients[protocol] ~= nil and clients[protocol][self] ~= nil then
  clients[protocol][self] = nil
end

sync client and settimeout()

I am using the sync client, receiving about 30 msgs/sec. I don't want to get stuck waiting if there is no data ready, so i am trying this:

  ws.sock:settimeout(0)
  local message, opcode, close_was_clean, close_code, close_reason = ws:receive()
  ws.sock:settimeout()

My idea/hope being that if there is no data available, it will fail and return me nil or some such and then i will do my other job and keep polling from time to time till i get something. I get nil - HOWEVER it also seems to close the connection, so i never really receive anything!

From my point of view seems like a bug. What can i do?

Websocket Secure support

Hi lipp,

In client*.lua I see the following code snippet:

if protocol ~= 'ws' then
error('Protocol not supported:'..protocol)
end

There is no support for wss:// ? Is secure connection support on the roadmap? A non-secured websocket connection will run into proxy problems.

Nathan.

--

Edit: posted issue on the wrong repo.

install problem on OSX10..

sudo luarocks make rockspecs/lua-websockets-scm-1.rockspec

Missing dependencies for lua-websockets:
luasocket
lpack

Using http://www.luarocks.org/repositories/rocks/luasocket-2.0.2-5.src.rock... switching to 'build' mode
Archive: /tmp/luarocks_luarocks-rock-luasocket-2.0.2-5-4119/luasocket-2.0.2-5.src.rock
inflating: luasocket-2.0.2-5.rockspec
inflating: luasocket-2.0.2.tar.gz
sh: gmake: command not found

Error: Failed installing dependency: http://www.luarocks.org/repositories/rocks/luasocket-2.0.2-5.src.rock - Build error: Failed building.


$ which lua -> /usr/local/bin/lua
$ lua -v -> Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio
$ luarocks list -> Installed rocks:
luabitop
1.0.2-1 (installed) - /usr/local/lib/luarocks/rocks
luafft
1.1-1 (installed) - /Users/{USERNAME}/.luarocks/lib/luarocks/rocks
1.1-1 (installed) - /usr/local/lib/luarocks/rocks
midi
5.9-1 (installed) - /usr/local/lib/luarocks/rocks
prtr-dump
20121212-1 (installed) - /usr/local/lib/luarocks/rocks
'
did i miss a -flag or is there an other workaround?
"gmake" does not exist on osx machines. :/ or?

attempt to yield across C-call boundary

local copas = require'copas'
local ws_client = require('websocket.client').copas()
ws_client:connect('ws://127.0.0.1:8180/')

error:copas.lua:298: attempt to yield across C-call boundary

env:
luajit 2.0.2
the last version of copas and coxpcall
windows 7

help! - attempt to call upvalue 'rol' (a nil value)

Hi;
I have chosen lua-websockets (and ported it and dependencies to OpenWrt packages) for the client portion of a licencing client / server, which may be extended for a remote configuration service.

Lua 5.1 (and, cannot upgrade without breaking a lot of Lua portion of OpenWrt, such as Luci

I am missing bit operations support (issue title, not shown in dependencies) and, seek advice regarding how to remedy this. An outline of alternatives is here: http://lua-users.org/wiki/BitwiseOperators

From which the best practice is suggested to use Lua BitOp (library, Lua API). Is this true, or, anyone have a better recommendation?

Also, I note that luacrypto (optionally) is an openssl wrapper. I have luasec for this ( http://luasec.luaforge.net/), which appears to be a more modern implementation. Any plans / advice regarding using luasec as opposed to luacrypto, or, is my best option to port luacrypto?

Full disclosure: relative Lua newbie, but intend to catch up (engineer)

Thanks for considering...

Bill Ross

tools.lua:114: bad argument #2 to 'pack' (integer overflow)

For lua 5.3
I make a change to tools.lua and frame.lua
local struct = string.pack and string or require'struct'

and when I use a websocket client connect to the server ,
the server throws errors , like :
./pc/lualib/websocket\tools.lua:114: bad argument #2 to 'pack' (integer overflow) thread: 00A2F5AC tcp{client}: 23E6C860
./pc/lualib/websocket\tools.lua:114: bad argument #2 to 'pack' (integer overflow) thread: 00A2DB2C tcp{client}: 11A68DA8
./pc/lualib/websocket\tools.lua:114: bad argument #2 to 'pack' (integer overflow) thread: 00A2DB2C tcp{client}: 11A55D30
./pc/lualib/websocket\tools.lua:114: bad argument #2 to 'pack' (integer overflow) thread: 00A2E32C tcp{client}: 11A43CB8
./pc/lualib/websocket\tools.lua:114: bad argument #2 to 'pack' (integer overflow) thread: 00A2DB2C tcp{client}: 11A68DA8
./pc/lualib/websocket\tools.lua:114: bad argument #3 to 'pack' (integer overflow) thread: 00A2E32C tcp{client}: 11A7FF18
./pc/lualib/websocket\tools.lua:114: bad argument #2 to 'pack' (integer overflow) thread: 00A2E2AC tcp{client}: 23E6C860
./pc/lualib/websocket\tools.lua:114: bad argument #4 to 'pack' (integer overflow) thread: 00A2DB2C tcp{client}: 11A43CB8
./pc/lualib/websocket\tools.lua:114: bad argument #2 to 'pack' (integer overflow) thread: 00A2E32C tcp{client}: 11A55D30
./pc/lualib/websocket\tools.lua:114: bad argument #2 to 'pack' (integer overflow) thread: 00A2E2AC tcp{client}: 11A360C8
./pc/lualib/websocket\tools.lua:114: bad argument #2 to 'pack' (integer overflow) thread: 00A2DB2C tcp{client}: 26DDD060
./pc/lualib/websocket\tools.lua:114: bad argument #2 to 'pack' (integer overflow) thread: 00A2E32C tcp{client}: 23E6C860
./pc/lualib/websocket\tools.lua:114: bad argument #3 to 'pack' (integer overflow) thread: 00A2E2AC tcp{client}: 11A68DA8
./pc/lualib/websocket\tools.lua:114: bad argument #4 to 'pack' (integer overflow) thread: 00A2E4AC tcp{client}: 11A7FF18

what's the mistake I took ??

Clarify on_error/on_close behavior

Async client/server
on_error calls if there some error befor ws handshake done (IO error/SSL handshake/Invalid token/ protocol) . And in this case on_close did not call.
on_close calls if ws handshake done. In case of IO error we call on_close with (false, 1001, "Going away"). And in this caseon_error` did not call.

Is it correct behavior?

Sockets not closing on Ctrl-C

It seems the sockets linger after being closed by Ctrl-C, and do not accept new receives on same port, until a timeout passes. The only way to solve this immediately is to change the port.

Is there a proper way to close the sockets?

Handshake fails on iOS/Android

Handshake is failing due to mismatched auth. It may be an endian issue. Lost my output, but will attach some logs tomorrow.

Installing Error

While installing lua-websockets, I got this error:

lua_websockets.c:392:3: error: too few arguments to function ‘libwebsocket_create_context’ In file included from lua_websockets.c:13:0: /usr/local/include/libwebsockets.h:647:1: note: declared here Error: Build error: Failed compiling object lua_websockets.o

Using latest libwebsockets

pure-lua version interface

I also need 'as thin as possible' version and this pure-lua version is great. I also need to integrate websocket to existing http server event loop using Luajit and i think I can do it using copas.step().

I have also made a simple http+websocket server using previous libwebsockets 'on_http' event. Is is possible to get 'other-than-websocket' event callback into test-server-copas.lua example?

Maybe you should focus only on pure-lua version and bypass all problems related to other libraries. Luajit is fast.

SHA1 message digest computation on iOS Devices.

We've been encountering issues getting the handshake to work on iOS devices. After a lot of work, we've verified that SHA1 seems to be operating correctly, but the problem is how the pack procedure is configured.

When the variables h0-h4 are passed in to pack as unsigned integers, we see good values being generated on OSX. This includes the iOS Simulator.

Using the latest XCode and running on a device (you can't duplicate this issue using the Simulator), if the variable is > 2^31, it's treated as a negative number and is turned into a zero on iOS.

By converting the pack routine to using signed integers in src/websocket//tools.lua,
We changed the final line in the sha1 function

return spack('>I>I>I>I>I',h0,h1,h2,h3,h4)

to the following:

return spack('>i>i>i>i>i',h0,h1,h2,h3,h4)

It does seem counter-intuitive, but using unsigned integers causes lpack to fall into the C++ standard (4.9) of undefined conversion behaviour, and using signed integers gives the desired behaviour in lpack.

Make client socket accessible?

In an application using websocket.server.copas, i need to access some information from the socket: IP address and port. They can be obtained using luasocket's getpeername (). This method is hidden by copas (but can be worked around using sock.socket).

A very simple hack is to add a field containing the socket inside the ws object passed to the handler, as in this commit: d6c32fb. But you may also want a more general solution available also in websocket.server.ev and in clients.

Maybe i just missed an already existing solution?

mac osx support

I was able to make this to work in OSX with small changes. See libwebsockets README-test-server. Maybe this should be handled in rockspeck or as an install option? Also --enable-openssl would be nice.

Add to private-libwebsockets.h:

define LWS_NO_FORK

Add to lwebsockets.c:

define LWS_NO_FORK

ifndef LWS_NO_FORK

static int context_fork_service_loop(lua_State *L) {
struct context *user = checked_context(L);
int n = libwebsockets_fork_service_loop(user->context);
lua_pushinteger(user->L, n);
return 1;
}

endif

ifndef LWS_NO_FORK

{"fork_service_loop",context_fork_service_loop},

endif

Openwrt Support

HI,

I was searching for lua based websockets libs for theOpenWrt and came to your page. I am looking for a client only piece that can connect to a a WS server and would be able to exchange massages over WS. Your libabry fits all my needs, I then tried to build a package for this on OpenWrt/mips but due to other dependencies I could not build it.

Do you know if such package is available on OpenWrt/MIPS or someone else tried it, if not could you please point me right direction to build it.

Deepak

New backend

I just imlement new backend for lua-websocket based on my libuv binding.
For now it implement same API as ev backend.
And I have several question:
1 To be avaliable you need add optional require to client/server files in main repo? (I have no objection to just merge my reto to this repo)
2 No all Linstners share same client set (clients table). Is it intentional or better if each server will have its own set?
3 To support wss protocol is it enough just make TLS connection?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.