Code Monkey home page Code Monkey logo

goupnp's People

Contributors

afjoseph avatar andrew-d avatar davelar avatar dennwc avatar edwardbetts avatar fanhai avatar fjl avatar games647 avatar huin avatar huin-google avatar humboldt-xie avatar hzyitc avatar jochenhiller avatar julianknodt avatar jybp avatar mh-cbon avatar noobtw avatar steve-hellwege-wdc avatar thinxer avatar tmm1 avatar traetox avatar tv42 avatar yuukanoo avatar zeebo 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

goupnp's Issues

Why can't i find this upnp device (http://192.168.61.1:5000/rootDesc.xml)?

Is it a subnet issue?
I can find this device using a third party app.
Finally i can load it by url

<root xmlns="urn:schemas-upnp-org:device-1-0"> <specVersion> <major>1</major> <minor>0</minor> </specVersion> <device> <deviceType> urn:schemas-upnp-org:device:InternetGatewayDevice:1 </deviceType> <friendlyName>OpenWRT router</friendlyName> <manufacturer>OpenWRT</manufacturer> <manufacturerURL>http://www.openwrt.org/</manufacturerURL> <modelDescription>OpenWRT router</modelDescription> <modelName>OpenWRT router</modelName> <modelNumber>1</modelNumber> <modelURL>http://www.openwrt.org/</modelURL> <serialNumber>00000000</serialNumber> <UDN>uuid:8d483abf-ca0e-45cc-9b....</UDN> <serviceList> <service> <serviceType>urn:schemas-upnp-org:service:Layer3Forwarding:1</serviceType> <serviceId>urn:upnp-org:serviceId:Layer3Forwarding1</serviceId> <controlURL>/ctl/L3F</controlURL> <eventSubURL>/evt/L3F</eventSubURL> <SCPDURL>/L3F.xml</SCPDURL> </service> </serviceList> <deviceList> <device> <deviceType>urn:schemas-upnp-org:device:WANDevice:1</deviceType> <friendlyName>WANDevice</friendlyName> <manufacturer>MiniUPnP</manufacturer> <manufacturerURL>http://miniupnp.free.fr/</manufacturerURL> <modelDescription>WAN Device</modelDescription> <modelName>WAN Device</modelName> <modelNumber>20160127</modelNumber> <modelURL>http://miniupnp.free.fr/</modelURL> <serialNumber>00000000</serialNumber> <UDN>uuid:8d483abf-ca0e-4f</UDN> <UPC>000000000000</UPC> <serviceList> <service> <serviceType> urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1 </serviceType> <serviceId>urn:upnp-org:serviceId:WANCommonIFC1</serviceId> <controlURL>/ctl/CmnIfCfg</controlURL> <eventSubURL>/evt/CmnIfCfg</eventSubURL> <SCPDURL>/WANCfg.xml</SCPDURL> </service> </serviceList> <deviceList> <device> <deviceType>urn:schemas-upnp-org:device:WANConnectionDevice:1</deviceType> <friendlyName>WANConnectionDevice</friendlyName> <manufacturer>MiniUPnP</manufacturer> <manufacturerURL>http://miniupnp.free.fr/</manufacturerURL> <modelDescription>MiniUPnP daemon</modelDescription> <modelName>MiniUPnPd</modelName> <modelNumber>20160127</modelNumber> <modelURL>http://miniupnp.free.fr/</modelURL> <serialNumber>00000000</serialNumber> <UDN>uuid:8d483abf-ca0e-45cc-9bf0</UDN> <UPC>000000000000</UPC> <serviceList> <service> <serviceType>urn:schemas-upnp-org:service:WANIPConnection:1</serviceType> <serviceId>urn:upnp-org:serviceId:WANIPConn1</serviceId> <controlURL>/ctl/IPConn</controlURL> <eventSubURL>/evt/IPConn</eventSubURL> <SCPDURL>/WANIPCn.xml</SCPDURL> </service> </serviceList> </device> </deviceList> </device> </deviceList> <presentationURL>http://192....1/</presentationURL> </device> </root>

httpu multicast fails on multiple interfaces

Using a single PacketConn to send multicast UDP requests for SSDP search fails, if there are multiple interfaces in the system.
The WriteTo() will pick any interface and use that alone, not sending the SSDP search to any other network interface.

I think that for SSDP search to work we need a PacketConn per network interface.

port mapping?

I was wondering if this library supports port mapping? not too familiar with upnp but I'm basically just looking for the ability to setup an open port through the router. I tried searching for urn:schemas-upnp-org:service:WANIPConnection:1 and couldn't find any references but not sure if I'm ever searching for the right thing =)

GetTotalBytesSent() can't parse value, if it's negative

Sent:

POST /upnp/control/WANCommonIFC1 HTTP/1.1
Host: 192.168.1.1:4562
User-Agent: Go-http-client/1.1
Content-Length: 302
CONTENT-TYPE: text/xml; charset="utf-8"
SOAPACTION: "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1#GetTotalBytesSent"
Accept-Encoding: gzip

<?xml version="1.0" encoding="UTF-8"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><s:Body><u:GetTotalBytesSent xmlns:u="urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1"></u:GetTotalBytesSent></s:Body></s:Envelope>

Received:

HTTP/1.1 200 OK
CONTENT-LENGTH:334
CONTENT-TYPE:text/xml
DATE: Fri, 21 Jun 2019 21:00:19 GMT
EXT:
SERVER:Linux/2.6.36 UPnP/1.0 myigd/1.0

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><s:Body>
<u:GetTotalBytesSentResponse xmlns:u="urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1">
<NewTotalBytesSent>-1363540943</NewTotalBytesSent>
</u:GetTotalBytesSentResponse>
</s:Body></s:Envelope>.

AFAIK this device is not following standards. However, miniupnpc client is not failing to parse this response.

Please provide example of AV dlna device implementation (audio)

Would it be possible to create a dlna device implementation with this library? So a device that actually listens to play, stop, previous, next, requests and can receive direct URI commands? I believe it is called a media renderer? If so, please provide a little example with the play stop previous next as stubs. I would like to use this as a starting point for creating the device that can be controlled via dlna. Thanks.

Unable to find devices most of the time

I just started using this library and initially was very happy that clients, errors, err := av1.NewAVTransport1Clients() found my Samsung TV and Teufel loudspeakers, but soon after that, it stopped working and clients was empty. After like 20 runs, it worked again, but eventually it's no longer finding anything. My system is Windows 10. Before using your library, I played around with Developer Tools for UPnP Technologies (http://www.meshcommander.com/upnptools) and their "Device Spy" that works all the time, so it doesn't appear to be a limitation of my OS or network / firewall. Any idea what might be wrong? Should I use Wireshark to inspect the traffic or do you recommend something else?

SSDPRawSearch: With the same USN, ipv4Response was replaced by ipv6Response, which is not effected for ipv4only client.

SSDPRawSearch:

Env: Router(ipv4+ipv6) , Client(ipv4)
With the same USN, ipv4Response was replaced by ipv6Response, which is not effected for ipv4only client.
This will be fixed by change seenUSNs[usn] with seenUSNs[location.String()+"/"+usn].

Code:

usn := response.Header.Get("USN")
location, err := response.Location()
if err != nil {
	continue
}
locusn := location.String() + "/" + usn
if _, alreadySeen := seenUSNs[locusn]; !alreadySeen {
	seenUSNs[locusn] = true
	responses = append(responses, response)
}

Fail on http post request to router.

스크린샷 2019-09-15 오전 3 12 05

In this image, it shows that device(ipTIME N104R3) is detected but http post request was fail.
I have a long time to find why my router doesn't response on post request. so I have took a specification about my router but there are no statement related to soap... so I have no idea whether my router cannot response or other problem is there...

Definition of my function

func AddPortMapping_ver1(PrivateIP string, ExternalPort uint16, InternalPort uint16, Protocol string) {
	clients, errors, err := internetgateway1.NewWANIPConnection1Clients()

	if errors != nil {
		return
	}
	if err != nil {
		return
	}
	for _, client := range clients {
		if err := client.AddPortMapping(PrivateIP, ExternalPort, Protocol, InternalPort, PrivateIP, true, "test", 0); err != nil {
			fmt.Println(err.Error())
		}
	}
}

And call AddPortMapping_ver1() in main function

AddPortMapping_ver1("192.168.0.2", 7871, 7871, "TCP") // my computer address is 192.168.0.2 and 192.168.0.1 is address of router

Your library says
스크린샷 2019-09-15 오전 3 22 02

Do you have any idea about this problem?

Sorry for my English.

Contexts on HTTP calls

I was wondering whether it would be possible to add contexts to any client calls, to make it more idiomatic. It would be easy to implement as a breaking change, as you could just stick a context into the codegen template, but that's definitely painful to old users of the package. I think it also may be a lot of bloat to add a new set of methods for context, but I was wondering what you thought of it.

Could you specify some examples?

I see that there are tons of different functions and I really don't know where to start implementing a simple "hello world" connections between 2 peers

Thanks

Service requests against Fritz!Box devices fail

I am trying a very simple test against a Fritz!Box device:

package main

import (
    "fmt"
    "log"
    "github.com/huin/goupnp/dcps/internetgateway1"
)


func main() {
    clients, _, err := internetgateway1.NewWANIPConnection1Clients ()
    if err != nil {
        log.Fatal(err)
    }
    for _, client := range clients {
        status, _, _, err := client.GetStatusInfo()
        if err != nil {
            log.Fatal(err)
        }
        fmt.Println(status)
    }
}

but this always fails:

2014/06/05 11:30:25 goupnp: SOAP request got HTTP 500 Internal Server Error

Windows / OSX support

I apologize if this is more of a support question than an actual Issue, although I would expect this to work properly on OSX and Windows out of the box.

I've created a very bare-bones simple SSDP test to verify SSDP discovery of roku devices

package main

import (
        "fmt"
        "github.com/huin/goupnp/httpu"
        "github.com/huin/goupnp/ssdp"
)

func main() {
        fmt.Println("Searching")
        httpu_client, _ := httpu.NewHTTPUClient()
        responses, _ := ssdp.SSDPRawSearch(httpu_client, "roku:ecp", 2, 3)

        for _, response := range responses {
                fmt.Println(response)
        }
}

When I compile and run this on my linux box (Ubuntu 17.04) it works no problem and I get one discovered roku device response

Searching...
&{200 OK 200 HTTP/1.1 1 1 map[Server:[Roku UPnP/1.0 Roku/7.7.0] Location:[http://192.168.1.10:8060/] Wakeup:[MAC=08:05:81:25:89:51;Timeout=10] Cache-Control:[max-age=3600] St:[roku:ecp] Usn:[uuid:roku:ecp:YY005F185283] Ext:[]] 0xc42005e200 -1 [] true false map[] 0xc420104000 <nil>}

But when I compile and run the same thing on my macbook and two other windows machines on my network, I get no response back.

My guess as to what's happening is that there are already services listening on port 1900, but looking at the HTTPU code, it looks like it's just binding to any available ephemeral port, not 1900, so it should work just fine.

Any ideas? I want to be able to do device discovery from any of those OSes without requiring disabling the network discovery service (or whatever may be bound to port 1900 already)

Thanks!

Discover UPnP as not active if UPnP not ON in device

Most google fiber routers come with their UPnP turned off by default. I am still a newbie and trying to figure out if it is possible to know that my router indeed has UPnP but currently turned off. As opposed to just not finding it, and not knowing that my router has such capabilities.

goupnp.go:109: undefined: charset.NewReaderByNam

when running the following:
go get -u github.com/huin/goupnp
I am getting an error on mac yosemite latest version

github.com/huin/goupnp

/usr/local/bin/src/github.com/huin/goupnp/goupnp.go:109: undefined: charset.NewReaderByNam

Provide an API to use specific ip addresses for discovery

Hi !

I need to test upnp connectivity over virtual "any addresses" IE 0.0.0.0.

The current API auto detects and auto selects the IPs based on the output of net.Interface which does not include those.

For consistency this line might be an issue

if a, ok := httpu.conn.LocalAddr().(*net.UDPAddr); ok {

Indeed, when listening upon v4AnyAddr, here at least, it returns AnyAddrV6, ie [::].... I am not looking forward for ipv6 support.

get the IP associated with the interface used to successfully discover the upnp setup ?

Hi,

In order to perform a PortMapping, the computer IP to route the traffic to, seems to be required (the remote does not appear capable of figuring that out by itself upon a query), otherwise a soap fault is encountered.

In this code,

func GetIPAndForwardPort(ctx context.Context, lPort, rPort int, proto string) error {
	client, err := PickRouterClient(ctx)
	if err != nil {
		return err
	}

...

	return client.AddPortMapping(
...
		// Internal address on the LAN we want to forward to.
		"", // <- how to fill this value
...
	)
}

I was hoping that the ssdp discovery result would contain the IP used to perform the successful query, but I was not able to locate it. ​

https://github.com/huin/goupnp/blob/master/network.go#L21

My setup is like that

$ ifconfig
enp58s0f1: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
       ​ether 80:fa:5b:43:59:24  txqueuelen 1000  (Ethernet)

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
       ​inet 127.0.0.1  netmask 255.0.0.0
       ​loop  txqueuelen 1000  (Boucle locale)

tun0: flags=4305<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST>  mtu 1331
       ​inet 198.18.80.9  netmask 255.255.248.0  destination 198.18.80.9
       ​unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  txqueuelen 100  (UNSPEC)

wlp59s0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
       ​inet 192.168.1.78  netmask 255.255.255.0  broadcast 192.168.1.255
       ​ether 00:28:f8:4b:d0:b1  txqueuelen 1000  (Ethernet)

I find it hard to guess but maybe i am missing something obvious ? ><

update the guide

at https://github.com/huin/goupnp/blob/main/GUIDE.md

we can change the example to use the LocalAddr() method :D

type RouterClient interface {
	AddPortMapping(
		NewRemoteHost string,
		NewExternalPort uint16,
		NewProtocol string,
		NewInternalPort uint16,
		NewInternalClient string,
		NewEnabled bool,
		NewPortMappingDescription string,
		NewLeaseDuration uint32,
	) (err error)

	LocalAddr() net.IP

	GetExternalIPAddress() (
		NewExternalIPAddress string,
		err error,
	)
}

//....
	return client.AddPortMapping(
		"",
		// External port number to expose to Internet:
		1234,
		// Forward TCP (this could be "UDP" if we wanted that instead).
		"TCP",
		// Internal port number on the LAN to forward to.
		// Some routers might not support this being different to the external
		// port number.
		1234,
		// Internal address on the LAN we want to forward to.
		client.LocalAddr().String(),
		// Enabled:
		true,
		// Informational description for the client requesting the port forwarding.
		"MyProgramName",
		// How long should the port forward last for in seconds.
		// If you want to keep it open for longer and potentially across router
		// resets, you might want to periodically request before this elapses.
		3600,
	)

Incorrect err (nil) returned incase of timeout in httpu

Problem:
err returned in the following code

goupnp/httpu/httpu.go

Lines 130 to 132 in 167b976

}
return responses, err
}

points to ResolveUDPAddr err object.

goupnp/httpu/httpu.go

Lines 83 to 84 in 167b976

destAddr, err := net.ResolveUDPAddr("udp", req.Host)
if err != nil {

Scope of ReadFrom err is only in the for loop. Due to which if ReadFrom throws timeout error, for loop breaks but the error returned is not the one generated by ReadFrom instead it is the one generated by ResolveUDPAddr hence nil.

goupnp/httpu/httpu.go

Lines 105 to 112 in 167b976

for {
// 2048 bytes should be sufficient for most networks.
n, _, err := httpu.conn.ReadFrom(responseBytes)
if err != nil {
if err, ok := err.(net.Error); ok {
if err.Timeout() {
break
}

httpu: error while parsing response

What is the ideal response format of httpu.conn.ReadFrom? Can someone give me a example?

I am trying to connect to my Yeelight(https://www.yeelight.com/download/Yeelight_Inter-Operation_Spec.pdf) that respond in this way (I copied this from ResponseBytes.string() of VSCode debugger):

HTTP/1.1 200 OK\r\nCache-Control: max-age=3584\r\nDate: \r\nExt: \r\nLocation: yeelight://192.168.1.2:123456\r\nServer: POSIX UPnP/1.0 YGLC/1\r\nid: 0x0000000007fe523f\r\nmodel: color\r\nfw_ver: 26\r\nsupport: get_prop set_default set_power toggle set_bright start_cf stop_cf set_scene cron_add cron_get cron_del set_ct_abx set_rgb set_hsv set_adjust adjust_bright adjust_ct adjust_color set_music set\r\npower: off\r\nbright: 100\r\ncolor_mode: 2\r\nct: 2899\r\nrgb: 16711680\r\nhue: 359\r\nsat: 100\r\nname: \r\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00

But every time I fall into "httpu: error while parsing response: unexpected EOF".

I tried to make a fake response only to test, but I keep falling in "httpu: error while parsing response: unexpected EOF". Here is the change that I made to test with the fake response:

buf := []byte("HTTP/1.1 200 OK\r\n")
response, err := http.ReadResponse(bufio.NewReader(bytes.NewBuffer(buf)), req)
if err != nil {
	log.Printf("httpu: error while parsing response: %v", err)
	continue
}

String conversion issue

Hi
I try know to use search criteria with my upnp server.
with curl I've got the expected results :
curl -v -H 'SOAPACTION: "urn:schemas-upnp-org:service:ContentDirectory:1#Search"' -H 'content-type: text/xml ;charset="utf-8"' "http://10.188.2.125:8200/ctl/ContentDir" -d "@search.xml"

with search file content :
<?xml version="1.0" encoding="utf-8"?> <s:Envelope xmlns:ns0="urn:schemas-upnp-org:service:ContentDirectory:1" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"> <s:Body> <ns0:Search> <Filter>*</Filter> <ContainerID>*</ContainerID> <SearchCriteria>(dc:title contains "star wars") and (upnp:class derivedfrom "object.item.videoItem")</SearchCriteria> <StartingIndex>0</StartingIndex> <RequestedCount>0</RequestedCount> <SortCriteria/> </ns0:Search> </s:Body> </s:Envelope>

When I use the goupnp api like this :
result, returnedNumber, totalMatches, _, err := client.Search("*", "(dc:title contains \"star wars\") and (upnp:class derivedfrom \"object.item.videoItem\")", "*", 0, 0, "")

the quotes are interpreted as html in my upnp server, here the log of the query :
[2017/11/03 12:27:43] sql.c:88: error: prepare failed: near "&": syntax error SELECT (select count(distinct DETAIL_ID) from OBJECTS o left join DETAILS d on (o.DETAIL_ID = d.ID) where (OBJECT_ID glob '*$*') and ((d.TITLE like &#34;star wars&#34;) and (o.CLASS like &#34;object.item.videoItem&#34;) )) + (select count(*) from OBJECTS o left join DETAILS d on (o.DETAIL_ID = d.ID) where (OBJECT_ID = '*') and ((d.TITLE like &#34;star wars&#34;) and (o.CLASS like &#34;object.item.videoItem&#34;) )) [2017/11/03 12:27:43] upnpsoap.c:123: warn: Returning UPnPError 708: Unsupported or invalid search criteria

the quotes are replaced by the html code.

I tried to find a workaround with runes, but I am still the same issue.

I have you got any advises ?
Best regards

Jerome

Not a issue but an ad request

Hi
I would like to create a simple app to display all items stored on a media server.
To discover media server, I just wrote this simple code :
`package main

import (
"flag"
"log"
"github.com/huin/goupnp"
)

var servers = flag.Bool("servers",true,"list all the dlna servers availabled.")
var list = flag.String("list","","get content from server uri")

func main() {
flag.Parse()
if *servers == true {
devices, err := goupnp.DiscoverDevices("urn:schemas-upnp-org:device:MediaServer:1")
if err != nil {
log.Printf("error %v",err.Error())
} else {
for _,d := range devices {
log.Printf("Device %v,%v",d.Root,d.Location)

		}
	}
} else {
	flag.Usage()
}

}`

Now to display the items content from a media server I call those requests :
curl -v -H 'SOAPACTION: "urn:schemas-upnp-org:service:ContentDirectory:1#Browse"' -H 'content-type: text/xml ;charset="utf-8"' "http://10.188.2.125:8200/ctl/ContentDir" -d "@browse.xml"

and the browse.xml content is :
<?xml version="1.0" encoding="utf-8"?> <s:Envelope xmlns:ns0="urn:schemas-upnp-org:service:ContentDirectory:1" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"> <s:Body> <ns0:Browse> <ObjectID>0</ObjectID> <BrowseFlag>BrowseDirectChildren</BrowseFlag> <Filter>*</Filter> <StartingIndex>0</StartingIndex> <RequestedCount>0</RequestedCount> <SortCriteria/> </ns0:Browse> </s:Body> </s:Envelope>

My question is how can I do by code the same feature ?

Best regards

Jerome

Is it possible to open a Location directly, without multicast discovery?

It seems to take about 2.2 seconds to go through the discovery process, here. Could I store a Location after a successful discovery, and just open it directly on subsequent runs? I don't quite see how that'd be done with the apis, DiscoverDevices seems to do some xml fetching and parsing that isn't exposed separately.

feat: context everywhere and non-blocking results

First, thanks for this lib, it's quite amazing how much goes into something like this.

I'm planning to use it for my project for (surprise) port-mapping, and ran some quick experiments to see how it'd fit. I'll be taking different actions depending on status, and in some cases I'll use short lease time.

Issue: The lack of context (or a Close() call) makes it hard to quickly interrupt and shut down ongoing client operations. My project uses a lot of goroutines and I'm really meticulous about teardown logic. Would it be possible to add context to all remaining client calls, such as httpu?

Issue: Even without context, my understanding is that the search functions cannot return until the timeout was reached, even if available sooner. Perhaps this is only true for certain calls like ssdp.SSDPRawSearch? Note: I ran the experiments with the wrapper lib libp2p/go-nat. I'm planning to solicit quick responses and use a fallback otherwise, so any delay will also delay the fallback. Would it be possible to return search results as they come available instead of all-at-once?

Question: The 2s default timeout on SSDP seems like a lot when dealing with local-only connections. How was this determined? Do you have any real-life data points? I may want to set a different default timeout, and I'm curious on how to set it best for my purposes.

I'm happy to contribute if needed, and thanks again.

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.