Giter Site home page Giter Site logo

swow / swow Goto Github PK

View Code? Open in Web Editor NEW
1.1K 51.0 107.0 5.56 MB

Coroutine-based cross-platform concurrent I/O engine.

License: Apache License 2.0

PHP 19.66% Shell 0.17% M4 0.54% C 72.07% Assembly 7.25% JavaScript 0.33%
coroutine async php asynchronous coroutines

swow's Introduction

English | 中文

Swow Logo
🚀 Swow is a multi-platform support and coroutine-based engine with a focus on concurrent I/O

license ci codecov release ❤️ php platform architecture

👾 Design Philosophy

Swow is committed to using the smallest C core and most of the PHP code to support PHP high-performance network programming, which determines that it is more about providing powerful secondary development capabilities by seamlessly integrating PHP code and C kernel, while ensuring critical performance.

In addition, it provides a variety of debugging mechanisms and powerful and low-threshold debugging tools, which can ensure that developers are free from the trouble of BUGs as much as possible, and ordinary developers can also have the ability to debug near the level of experts with the help of tools, so as to maximize development efficiency.

🎮 Installation

Like any open source project, Swow always provides the strongest stability and features in the newest release, please try to ensure that you are using the latest version.

🔎 Requirements

  • Common operating systems such as Linux, Windows, macOS, etc. Almost same as libuv
  • PHP 8.0.0 or above, the latest version is recommended

👨‍🎤 By Composer

pull source code:

composer require swow/swow

Then run the automatic installer swow-builder under the vendor/bin directory to start the installation:

./vendor/bin/swow-builder --install

After you update the source code of Swow, you should use the rebuild option to recompile Swow and then install it:

./vendor/bin/swow-builder --rebuild --install

More information about swow-builder can be found in Extension installation document - By Composer.

🐧 Manual installation (UNIX-like)

clone the Swow (You can also import it through Composer, and then cd to vendor/swow/swow/ext and install manually):

git clone https://github.com/swow/swow.git

Well-known building procedure. Install to the system with root privileges:

cd swow/ext && \
phpize && ./configure && make && \
sudo make install

Ⓜ️ Manual installation (Windows)

See Installation document - Manual compilation installation (Windows).

You can also download DLL directly in Latest Release.

🔰️ Security issues

Security issues should be reported privately, via email, to [email protected]. You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message.

🖊️ Contribution

Your contribution to Swow development is very welcome!

You may contribute in the following ways:

❤️ Contributors

PHP high-performance coroutine network communication engine development road is too high to be popular, It's a lonely open source work at the top.

Thank you very much to the following partners for the contribution of the Swow project, without you there is no Swow now.

Contributors

💬 Development & Discussion

📃 License

Swow is available under the Apache License Version 2.0. Swow also includes external libraries that are available under a variety of licenses. See LICENSES.full for the full license text.

swow's People

Contributors

aurorayolo avatar childeden avatar dixyes avatar duxphp avatar her-cat avatar huanghantao avatar huangzhhui avatar ikilobyte avatar limingxinleo avatar nauxliu avatar pandaliu-1111 avatar sy-records avatar thinker-gao avatar twose avatar woodongwong avatar xtyxtyx avatar xuanyanwow avatar yulei745 avatar yurunsoft 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

swow's Issues

[discussion] (PHP代码实现的功能能不能单列出来)

  1. lib 库里PHP代码的功能和扩展实现的功能都在一个命名空间下,搞不清楚是扩展提供的还是PHP库提供的
  2. 如果开发者不喜欢PHP库的一些实现方式,它就显得有点多余。只要有足够健壮高效的底层,大家都喜欢造上层轮子
  3. 为什么不作为单独的官方库实现,可以composer引入使用,也可以作为框架开发者的参考

我使用 MAC OS 构建时发生了错误

环境:

$> sw_vers
ProductName:	Mac OS X
ProductVersion:	10.13.6
BuildVersion:	17G65

$> php -v
PHP 7.4.10 (cli) (built: Sep  3 2020 18:20:30) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
    with Zend OPcache v7.4.10, Copyright (c), by Zend Technologies

我执行php ./vendor/bin/swow-builder 命令进行构建时发生报错如下:

6tLfk6.png

然后我又重新编译并且打印出日志 php ./vendor/bin/swow-builder --rebuild --show-log

6tOQBR.png

发现 ./vendor/swow/swow/ext/deps/libcat/tools/cpu_count.sh , ./vendor/swow/swow/ext/clean.sh , ./vendor/swow/swow/ext/deps/libcat/tools/cleaner.sh
文件的换行符为CRLF (\r\n) 并非 LF (\n) 所以导致我无法完成编译

然后我使用dos2unix 命令,进行换行符转换,就可以正常编译了

dos2unix ./vendor/swow/swow/ext/deps/libcat/tools/cpu_count.sh
dos2unix ./vendor/swow/swow/ext/clean.sh
dos2unix ./vendor/swow/swow/ext/deps/libcat/tools/cleaner.sh

不知道我能不能直接将这三个文件的换行符转换为 LF,我抽空测试下转换后在 windows 下编译是否正常

大佬们看看有没有啥更好的解决方案

希望编译扩展的时候,可以把php也静态编译

cli模式下更希望是可以像nodegolang那样纯静态编译,带着有swow扩展的纯静态编译php-cli,发送给其它的机器也能运行,而不需要在机器上安装php环境,虽然有docker,但一通操作下载,镜像大小也要上GB,不知道我这样表达的是否清楚,欢迎讨论

[discussion] (建议废弃lib下面的内容,这些完全让php开发者自己去实现。专心维护ext的稳定性、性能、兼容性)

这是只是一个建议,要长远的支持下去,做的太多耗费的精力太多了,做的太多也容易产生更多的bug,即使很努力 也容易会给人一种很不稳定的影响。 建议尽量的少,保持非常好的灵活、稳定性、兼容性(类似workerman php5.3+都能用 ,并不是说需要支持5.x 只是表达着个库|扩展不挑环境 适应性很强)

关于stream_set_blocking阻塞疑惑

你好,关于stream_set_blocking设置为非阻塞之后还是阻塞的问题,我看了一下swow的代码,发现:

static int swow_stream_set_option(php_stream *stream, int option, int value, void *ptrparam) {
    // 省略
    /* always blocked */
    return PHP_STREAM_OPTION_RETURN_OK;  这里是没有操作的
}

我又看了一下php8这部分的源码,这里是:
oldmode = sock->is_blocked;
if (SUCCESS == php_set_sock_blocking(sock->socket, value)) {
sock->is_blocked = value;
return oldmode;
}
return PHP_STREAM_OPTION_RETURN_ERR;

php_set_sock_blocking 也是直接执行fcntl修改套接字的属性,请问这里为啥不能直接copy过去呢?

什么时候准备出一个think-swow

例如像think-swoole一样,因为这个在thinkphp6中使用多应用时无法正常路由,听说swow很强,希望以后能用上 think-swow 提供 windows和linux的高性能接口服务

为什么不用ffi呢?

为什么不直接使用php7.4以上的FFI直接调用,这样就可以完全用composer安装了。

[bug] win7 64 位环境下PHP8.0加上swow扩展会报错 无法定位程序输入点GetHostNameW于动态链接库WS2_32.dll上

Describe the bug / 问题描述
win7 64 位环境下PHP8.0加上swow扩展会报错
报错内容是: 无法定位程序输入点GetHostNameW于动态链接库WS2_32.dll上
image

To Reproduce / 如何复现

  1. 从php官方下载8.0的php包 https://windows.php.net/download#php-8.0
  2. 下载对应swow release的php扩展
  3. cd 到php包根目录:执行 php-v 就出现报错

Expected behavior / 正确的行为

无报错

Outputs / 程序输出

image

Runtime Environment / 运行环境

OS:

Caption=Microsoft Windows 7 旗舰版
CSDVersion=Service Pack 1
OSArchitecture=64-bit
OSLanguage=2052
TotalVisibleMemorySize=4193784
Version=6.1.7601

Architecture=9
Caption=Intel64 Family 6 Model 85 Stepping 7
Name=Intel(R) Xeon(R) Gold 6238L CPU @ 2.10GHz
NumberOfCores=1
NumberOfLogicalProcessors=1


Architecture=9
Caption=Intel64 Family 6 Model 85 Stepping 7
Name=Intel(R) Xeon(R) Gold 6238L CPU @ 2.10GHz
NumberOfCores=1
NumberOfLogicalProcessors=1

PHP:

Swow:
PHP 8.0.20 (cli) (built: Jun 8 2022 09:10:24) ( NTS Visual C++ 2019 x64 )
Copyright (c) The PHP Group
Zend Engine v4.0.20, Copyright (c) Zend Technologies

Additional context / 补充说明

扩展注释掉之后,就无报错了。应该跟扩展有关系

configure error: invalid-pp-token

checking for -single_module linker flag... In file included from :365:
:2:17: warning: missing terminating '"' character [-Winvalid-pp-token]
#define CAT_VM "zend"

Configuration File (php.ini) Path: /Applications/MAMP/bin/php/php7.4.2/conf
Loaded Configuration File: /Library/Application Support/appsolute/MAMP PRO/conf/php7.4.2.ini
Scan for additional .ini files in: (none)
Additional .ini files parsed: (none)

Channels

Hi, thanks for supplying nice stuff.

Just tried the example for channels and selectors and doesn't work for me.
But the coroutines are just fine.

Does the examples are up to date with current version of code ?

README中路径问题

使用此方式安装时,最后一步程序会提示输入密码以使用root权限安装到系统,你可以选择不输入,安装程序仍会提供类似于以下的运行命令:

/usr/bin/env php -n -d extension=/path/to/vendor/swow/swow/ext/.build/swow.so --ri swow

即扩展的so文件输出到了你项目的vendor目录下,相当于扩展也拥有了版本控制,你可以为你的每个项目指定不同版本的Swow,而无需全局使用同一个扩展so。

实际 swow.so 路径,是否为 /path/to/vendor/swow/swow/modules/swow.so。并未看到有 .build 文件夹
image

fibers会被合并到php 8.1,swow怎么办

fibers会被合并到php 8.1,不知道swow后面的路怎么走呢?个人感觉应该是php8.1出来之后,比如 mysql、mongdo、redis之类的软件肯定会出适配8.1的协程驱动,这是一种趋势,也是把php蛋糕做大的唯一途径,也是官方希望看到的。扩展毕竟非官方,没有官方支持很难去推广和普及,相比作者应该有自己的想法吧,可否一起讨论下

Mac编译时提示waring,执行php -m提示协程与操作opcode部分扩展不兼容

PHP:7.4.7
系统:Mac os Big Sur 11.2.3
编译提示的错误信息:

....
configure: patching config.h.in
configure: creating ./config.status
config.status: creating config.h
src/swow_fs.c:378:57: warning: missing field 'error' initializer [-Wmissing-field-initializers]
struct _swow_fs_open_s data = {-1, NULL, flags, 0666};
^
1 warning generated.

✅ Make complete

...

执行php-m提示的错误信息:
PHP Fatal error: Coroutine module is incompatible with some extensions that setup exit user opcode handler in Unknown on line 0

Fatal error: Coroutine module is incompatible with some extensions that setup exit user opcode handler in Unknown on line 0

[bug] 执行 swow-builder 报错

版本:v0.2.0-alpha.1

$ ./vendor/bin/swow-builder

Fatal error: Uncaught Error: Call to undefined function Swow\Utils\passthru() in /Users/hdj/gitroot/test/vendor/swow/swow/ext/bin/swow-builder:54
Stack trace:
#0 /Users/hdj/gitroot/test/vendor/swow/swow/ext/bin/swow-builder(97): {closure}('Configure', Array)
#1 /Users/hdj/gitroot/test/vendor/bin/swow-builder(120): include('/Users/hdj/gitr...')
#2 {main}
  thrown in /Users/hdj/gitroot/test/vendor/swow/swow/ext/bin/swow-builder on line 54

[bug] channel pop execution does not respond

Describe the bug / 问题描述

在向channel->push后使用pop取出数据程序疑似无响应
To Reproduce / 如何复现

image

  1. ws收到信息后将message push到channel
    image

  2. 然后在service取出数据走到pop后程序疑似无响应了 拿不到数据 也不执行之后的代码 同时其他无异常例如 http 继续发送信息无异常

Expected behavior / 正确的行为

正确取出pop数据发送给ws客户端
image

Outputs / 程序输出

image

Runtime Environment / 运行环境

OS:

Linux LAPTOP-9EPBATCU 4.4.0-22000-Microsoft #1-Microsoft Fri Jun 04 16:28:00 PST 2021 x86_64 x86_64 x86_64 GNU/Linux
fill here with your OS version / 在这填入你的OS信息
NAME="Ubuntu"
VERSION="20.04.2 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04.2 LTS"
VERSION_ID="20.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=focal
UBUNTU_CODENAME=focal

PHP:

PHP 8.0.15 (cli) (built: Feb 11 2022 16:08:55) ( NTS )
Copyright (c) The PHP Group
Zend Engine v4.0.15, Copyright (c) Zend Technologies
    with Zend OPcache v8.0.15, Copyright (c), by Zend Technologies
    with Yasd v0.3.9-alpha, Our Copyright, by codinghuang

Swow:


Swow

Status => enabled
Author => Swow Team
Link => https://github.com/swow/swow
Contact => Twosee <[email protected]>
Version => 0.1.0-487abd24 ( NTS )
Built => Apr  3 2022 11:44:04
Context => boost-context
Scheduler => libuv-event
With => OpenSSL 1.1.1f  31 Mar 2020, cURL 7.68.0

Additional context / 补充说明

[bug] Bug when used with Symfony HttpClient

Describe the bug / 问题描述

Warning: [Fatal error in R2] Uncaught Symfony\Component\HttpClient\Exception\TransportException: Transfer closed with outstanding data remaining from chunked response. in /home/gingdev/code/gingdev/telebot/vendor/symfony/http-client/Response/NativeResponse.php:311
Stack trace:
#0 /home/gingdev/code/gingdev/telebot/vendor/symfony/http-client/Response/TransportResponseTrait.php(176): Symfony\Component\HttpClient\Response\NativeResponse::perform(Object(Symfony\Component\HttpClient\Internal\NativeClientState), Array)
#1 /home/gingdev/code/gingdev/telebot/vendor/symfony/http-client/Response/CommonResponseTrait.php(68): Symfony\Component\HttpClient\Response\NativeResponse::stream(Array)
#2 /home/gingdev/code/gingdev/telebot/momo.php(16): Symfony\Component\HttpClient\Response\NativeResponse->getContent()
#3 [internal function]: {closure}()
#4 {main}

Next Symfony\Component\HttpClient\Exception\TransportException: Transfer closed with outstanding data remaining from chunked response. in /home/gingdev/code/gingdev/telebot/vendor/symfony/http-client/Chunk/ErrorChunk.php:89
Stack trace:
#0 /home/gingdev/code/gingdev/telebot/vendor/symfony/http-client/Response/TransportResponseTrait.php(285): Symfony\Component\HttpClient\Chunk\ErrorChunk->getContent()
#1 /home/gingdev/code/gingdev/telebot/vendor/symfony/http-client/Response/CommonResponseTrait.php(68): Symfony\Component\HttpClient\Response\NativeResponse::stream(Array)
#2 /home/gingdev/code/gingdev/telebot/momo.php(16): Symfony\Component\HttpClient\Response\NativeResponse->getContent()
#3 [internal function]: {closure}()
#4 {main}

To Reproduce / 如何复现

<?php

// >_ php -n -d extension=./vendor/swow/swow/ext/modules/swow.so

use Swow\Coroutine;
use Swow\Sync\WaitReference;
use Symfony\Component\HttpClient\HttpClient;

require __DIR__.'/vendor/autoload.php';

$wr = new WaitReference();

Coroutine::run(static function () use ($wr) {
    $client = HttpClient::create();
    $resp = $client->request('GET', 'https://www.baidu.com');
    echo $resp->getContent();
});

WaitReference::wait($wr);
  1. Do something first / 先做了什么
  2. Then do another / 然后做了什么
  3. Finally the software blew up / 它炸了

Expected behavior / 正确的行为

Outputs / 程序输出

Runtime Environment / 运行环境

OS:

Ubuntu 22.04

PHP: 8.1

Swow:

Swow
Status => enabled
Author => Swow Team
Link => https://github.com/swow/swow
Contact => Twosee <[email protected]>
Version => 0.1.0 ( NTS )
Built => Jun 14 2022 08:33:53
Context => boost-context
Scheduler => libuv-event
With => OpenSSL 3.0.2 15 Mar 2022, cURL 7.81.0

Additional context / 补充说明

KillException maybe exposed in some context

composer update                                                                                                                   1048421:28:051/7:	https://mirrors.aliyun.com/composer/p/provider-2020-04$9d5875688eb0173ed3a3bd7736714f8e0089b22d39813bae80225c15f6784d75.json
    2/7:	https://mirrors.aliyun.com/composer/p/provider-2019$6ebeb3ded28e7f31d592ac046d365f96608c211aa9798d17436f049cbee79cd7.json
    3/7:	https://mirrors.aliyun.com/composer/p/provider-latest$d3fee4277adf3081ca6b9dd840ac580e4f2360cc6f82352554686054ec987831.json
    4/7:	https://mirrors.aliyun.com/composer/p/provider-2020-10$07a0ff65ebc73524e2eb43efa26f5c2f7eae6d749f4daa50380e0773d2f5eefa.json
    5/7:	https://mirrors.aliyun.com/composer/p/provider-2020-01$fb275eee009e055f7b093e26c2111e55d2dd023ee39b712d90360bedc79327d5.json
    6/7:	https://mirrors.aliyun.com/composer/p/provider-2018$4394b7a1e2e8a179041c01f47ab33cb09453ced2451ffab08bd00b8e33969283.json
    7/7:	https://mirrors.aliyun.com/composer/p/provider-2020-07$1170c8d10bed574df78005bbd1c4ed3c81ac5ddc7f8751a50326a15a3368769f.json
    Finished: success: 7, skipped: 0, failure: 0, total: 7
Loading composer repositories with package information
Updating dependencies (including require-dev)
    1/9:	https://mirrors.aliyun.com/composer/dists/phpunit/phpunit/3866b2eeeed21b1b099c4bc0b7a1690ac6fd5baa.zip
    2/9:	https://mirrors.aliyun.com/composer/dists/league/mime-type-detection/353f66d7555d8a90781f6f5e7091932f9a4250aa.zip
    3/9:	https://mirrors.aliyun.com/composer/dists/filp/whoops/2ec31f3adc54c71a59c5e3c2143d7a0e2f8899f8.zip
    4/9:	https://mirrors.aliyun.com/composer/dists/laravel/sanctum/43f05df591e5099563520ab018cca4ac383681cd.zip
    5/9:	https://mirrors.aliyun.com/composer/dists/laravel/framework/8d1f25fb8d124d5a24df9714ed8d481c43f9efe6.zip
    6/9:	https://mirrors.aliyun.com/composer/dists/facade/flare-client-php/fd688d3c06658f2b3b5f7bb19f051ee4ddf02492.zip
    7/9:	https://mirrors.aliyun.com/composer/dists/laravel/jetstream/5a1967bb1f0f73620313b9b9431ac122ef20c79c.zip
    8/9:	https://mirrors.aliyun.com/composer/dists/laravel/fortify/55e4b0fc750d3d2abed4c314105db269043e6cb7.zip
    9/9:	https://mirrors.aliyun.com/composer/dists/nesbot/carbon/6571aec754a648ef476a8d8f57993f7bc965afe4.zip
    Finished: success: 9, skipped: 0, failure: 0, total: 9
Package operations: 0 installs, 9 updates, 0 removals
  - Updating nesbot/carbon (2.41.3 => 2.41.4): Loading from cache
  - Updating league/mime-type-detection (1.5.0 => 1.5.1): Loading from cache
  - Updating laravel/framework (v8.10.0 => v8.11.2): Loading from cache
  - Updating laravel/fortify (v1.6.1 => v1.6.2): Loading from cache
  - Updating laravel/jetstream (v1.4.1 => v1.5.1): Loading from cache
  - Updating laravel/sanctum (v2.6.0 => v2.7.0): Loading from cache
  - Updating phpunit/phpunit (9.4.1 => 9.4.2): Loading from cache
  - Updating facade/flare-client-php (1.3.6 => 1.3.7): Loading from cache
  - Updating filp/whoops (2.8.0 => 2.9.0): Loading from cache
Writing lock file
Generating optimized autoload files
> Illuminate\Foundation\ComposerScripts::postAutoloadDump
> @php artisan package:discover --ansi
Discovered Package: facade/ignition
Discovered Package: fideloper/proxy
Discovered Package: fruitcake/laravel-cors
Discovered Package: jenssegers/agent
Discovered Package: laravel/fortify
Discovered Package: laravel/jetstream
Discovered Package: laravel/sanctum
Discovered Package: laravel/tinker
Discovered Package: livewire/livewire
Discovered Package: nesbot/carbon
Discovered Package: nunomaduro/collision
Package manifest generated successfully.

   Swow\Coroutine\KillException



  at artisan:53
     49▕ */
     5051$kernel->terminate($input, $status);
     52▕
  ➜  53▕ exit($status);
     5475 packages you are using are looking for funding.
Use the `composer fund` command to find out more!

[bug] (Fatal error: Uncaught Error: Call to undefined function iconv()) swow和iconv共同使用,提示iconv函数不存在.

问题描述

swow和iconv共同使用,提示iconv函数不存在.
(Fatal error: Uncaught Error: Call to undefined function iconv())

复现代码

<?php
declare(strict_types = 1);

$text = "This is the Euro symbol '€'.";

echo 'Original : ', $text, PHP_EOL;
echo 'TRANSLIT : ', \iconv('UTF-8', 'ISO-8859-1//TRANSLIT', $text), PHP_EOL;
exit;

环境,系统

Macos,
PHP:
PHP 8.0.6 (cli) (built: May 19 2021 15:29:07) ( NTS )
Copyright (c) The PHP Group
Zend Engine v4.0.6, Copyright (c) Zend Technologies

Swow:(最新版本)
Status => enabled
Author => twosee [email protected]
Version => 0.1.0-6e21004c ( NTS )
Context => boost-context
Scheduler => libuv-event

Iconv:
iconv support => enabled
iconv implementation => libiconv
iconv library version => 1.11

Directive => Local Value => Master Value
iconv.input_encoding => no value => no value
iconv.output_encoding => no value => no value
iconv.internal_encoding => no value => no value

Ability to cancel I/O bound operations

Hello! Do you have any plans to implement ability to cancel I / O operations like GoLang does?

https://golang.org/pkg/context/

Package context defines the Context type, which carries deadlines, cancellation signals, and other request-scoped values across API boundaries and between processes.

I think it should be a core ability. It can be useful for services graceful shutdown and can be more consistent with I / O operations (like context.WithTimeout () can be used to cancel any I / O operation by timeout only in one way instead of many setTimeout APIs on Socket and etc.)

编译报错

./confingure 正常 make 报错

src/swow_stream.c: In function ‘swow_stream_socket_factory’:
src/swow_stream.c:108:40: error: macro "strncmp" requires 3 arguments, but only 2 given
     if (strncmp(proto, ZEND_STRL("ssl")) == 0 ||
                                        ^
src/swow_stream.c:108:42: warning: the comparison will always evaluate as ‘false’ for the address of ‘strncmp’ will never be NULL [-Waddress]
     if (strncmp(proto, ZEND_STRL("ssl")) == 0 ||
                                          ^
src/swow_stream.c:109:40: error: macro "strncmp" requires 3 arguments, but only 2 given
         strncmp(proto, ZEND_STRL("tls")) == 0 ||
                                        ^
src/swow_stream.c:109:42: warning: the comparison will always evaluate as ‘false’ for the address of ‘strncmp’ will never be NULL [-Waddress]
         strncmp(proto, ZEND_STRL("tls")) == 0 ||
                                          ^
src/swow_stream.c:110:42: error: macro "strncmp" requires 3 arguments, but only 2 given
         strncmp(proto, ZEND_STRL("https")) == 0 ||
                                          ^
src/swow_stream.c:110:44: warning: the comparison will always evaluate as ‘false’ for the address of ‘strncmp’ will never be NULL [-Waddress]
         strncmp(proto, ZEND_STRL("https")) == 0 ||
                                            ^
src/swow_stream.c:111:41: error: macro "strncmp" requires 3 arguments, but only 2 given
         strncmp(proto, ZEND_STRL("ftps")) == 0) {
                                         ^
src/swow_stream.c:111:43: warning: the comparison will always evaluate as ‘false’ for the address of ‘strncmp’ will never be NULL [-Waddress]
         strncmp(proto, ZEND_STRL("ftps")) == 0) {
                                           ^
make: *** [src/swow_stream.lo] Error 1
PHP 7.4.11 (cli) (built: Oct 22 2020 17:01:28) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies

cc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-39)
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

windows10,php 7.4开启swow拓展,composer有点小问题

windows10,php 7.4开启swow拓展 (v0.1.0-nightly20210910版本)
composer create-project hyperf/swow-skeleton
composer创建项目会有小问题,慢,且常报curl错误,关闭swow.dll拓展,composer使用正常。
然后再开启swow,可正常使用swow的hyperf

[bug] Warning: Uncaught Error: Xdebug has detected a possible infinite loop, and aborted your script with a stack depth of '256' frames in [no active file]:0

Describe the bug / 问题描述
ab 压力测试swow https://github.com/swow-cloud/websocket-server

该项目启动命令
php bin/swow-cloud server:start

ab测试命令
ab -n 200000 -c 100 -k http://127.0.0.1:9502/

抛出如下信息:

PHP   8. Symfony\Component\Console\Application->doRun($input = class Symfony\Component\Console\Input\ArgvInput { protected $definition = class Symfony\Component\Console\Input\InputDefinition { private $arguments = [...]; private $requiredCount = 1; private $lastArrayArgument = NULL; private $lastOptionalArgument = NULL; private $options = [...]; private $negations = [...]; private $shortcuts = [...] }; protected $stream = NULL; protected $options = []; protected $arguments = ['command' => 'server:start']; protected $interactive = TRUE; private $tokens = [0 => 'server:start']; private $parsed = [] }, $output = class Symfony\Component\Console\Output\ConsoleOutput { private ${Symfony\Component\Console\Output\Output}verbosity = 32; private ${Symfony\Component\Console\Output\Output}formatter = class Symfony\Component\Console\Formatter\OutputFormatter { private $decorated = TRUE; private $styles = [...]; private $styleStack = class Symfony\Component\Console\Formatter\OutputFormatterStyleStack { ... } }; private ${SPHP   9. Symfony\Component\Console\Application->doRunCommand($command = class SwowCloud\WsServer\Console\ServerCommand { private ${Symfony\Component\Console\Command\Command}application = class SwowCloud\WsServer\Application { private ${Symfony\Component\Console\Application}commands = [...]; private ${Symfony\Component\Console\Application}wantHelps = FALSE; private ${Symfony\Component\Console\Application}runningCommand = ...; private ${Symfony\Component\Console\Application}name = 'MusicServer Console Tool...'; private ${Symfony\Component\Console\Application}version = 'UNKNOWN'; private ${Symfony\Component\Console\Application}commandLoader = NULL; private ${Symfony\Component\Console\Application}catchExceptions = FALSE; private ${Symfony\Component\Console\Application}autoExit = TRUE; private ${Symfony\Component\Console\Application}definition = class Symfony\Component\Console\Input\InputDefinition { ... }; private ${Symfony\Component\Console\Application}helperSet = class Symfony\Component\Console\Helper\HelperSetPHP  11. Symfony\Component\Console\Command\Command->run($input = class Symfony\Component\Console\Input\ArgvInput { protected $definition = class Symfony\Component\Console\Input\InputDefinition { private $arguments = [...]; private $requiredCount = 1; private $lastArrayArgument = NULL; private $lastOptionalArgument = NULL; private $options = [...]; private $negations = [...]; private $shortcuts = [...] }; protected $stream = NULL; protected $options = []; protected $arguments = ['command' => 'server:start']; protected $interactive = TRUE; private $tokens = [0 => 'server:start']; private $parsed = [] }, $output = class Symfony\Component\Console\Style\SymfonyStyle { private ${Symfony\Component\Console\Style\OutputStyle}output = class Symfony\Component\Console\Output\ConsoleOutput { private ${Symfony\Component\Console\Output\Output}verbosity = 32; private ${Symfony\Component\Console\Output\Output}formatter = class Symfony\Component\Console\Formatter\OutputFormatter { ... }; private ${Symfony\Component\Console\OutPHP  12. SwowCloud\WsServer\Console\Command->execute($input = class Symfony\Component\Console\Input\ArgvInput { protected $definition = class Symfony\Component\Console\Input\InputDefinition { private $arguments = [...]; private $requiredCount = 1; private $lastArrayArgument = NULL; private $lastOptionalArgument = NULL; private $options = [...]; private $negations = [...]; private $shortcuts = [...] }; protected $stream = NULL; protected $options = []; protected $arguments = ['command' => 'server:start']; protected $interactive = TRUE; private $tokens = [0 => 'server:start']; private $parsed = [] }, $output = class Symfony\Component\Console\Style\SymfonyStyle { private ${Symfony\Component\Console\Style\OutputStyle}output = class Symfony\Component\Console\Output\ConsoleOutput { private ${Symfony\Component\Console\Output\Output}verbosity = 32; private ${Symfony\Component\Console\Output\Output}formatter = class Symfony\Component\Console\Formatter\OutputFormatter { ... }; private ${Symfony\Component\Console\OutputPHP  14. call($callback = [0 => class SwowCloud\WsServer\Console\ServerCommand { private ${Symfony\Component\Console\Command\Command}application = class SwowCloud\WsServer\Application { ... }; private ${Symfony\Component\Console\Command\Command}name = 'server:start'; private ${Symfony\Component\Console\Command\Command}processTitle = NULL; private ${Symfony\Component\Console\Command\Command}aliases = [...]; private ${Symfony\Component\Console\Command\Command}definition = class Symfony\Component\Console\Input\InputDefinition { ... }; private ${Symfony\Component\Console\Command\Command}hidden = FALSE; private ${Symfony\Component\Console\Command\Command}help = 'This command allows you start MusicServer...'; private ${Symfony\Component\Console\Command\Command}description = 'Start WebSocket Server'; private ${Symfony\Component\Console\Command\Command}fullDefinition = class Symfony\Component\Console\Input\InputDefinition { ... }; private ${Symfony\Component\Console\Command\Command}ignoreValidationErrors = FALSE; pri
Warning: Uncaught Error: Xdebug has detected a possible infinite loop, and aborted your script with a stack depth of '256' frames in [no active file]:0
Stack trace:
#0 {main}

  thrown in [no active file] on line 0

Call Stack:
    0.0004     406320   1. {main}() /Users/heping/PhpWorkSpace/swow-cloud/websocket-server/bin/swow-cloud:0
    0.0296    5924768   2. {closure:/Users/heping/PhpWorkSpace/swow-cloud/websocket-server/bin/swow-cloud:36-70}() /Users/heping/PhpWorkSpace/swow-cloud/websocket-server/bin/swow-cloud:70
    0.0430    7025232   3. Hyperf\Di\Container->get($id = 'SwowCloud\\WsServer\\Application') /Users/heping/PhpWorkSpace/swow-cloud/websocket-server/bin/swow-cloud:67
    0.0430    7025232   4. Hyperf\Di\Container->make($name = 'SwowCloud\\WsServer\\Application', $parameters = ???) /Users/heping/PhpWorkSpace/swow-cloud/websocket-server/vendor/hyperf/di/src/Container.php:116
    0.0441    7294936   5. Hyperf\Di\Container->resolveDefinition($definition = class Hyperf\Di\Definition\ObjectDefinition { protected ?Hyperf\Di\Definition\MethodInjection $constructorInjection = class Hyperf\Di\Definition\MethodInjection { private string $methodName = '__construct'; private array $parameters = [...] }; private ?string $className = 'SwowCloud\\WsServer\\Application'; private bool $classExists = TRUE; private bool $instantiable = TRUE; private string $name = 'SwowCloud\\WsServer\\Application' }, $parameters = []) /Users/heping/PhpWorkSpace/swow-cloud/websocket-server/vendor/hyperf/di/src/Container.php:71
    0.6175    8614712   6. Symfony\Component\Console\Application->run($input = ???, $output = ???) /Users/heping/PhpWorkSpace/swow-cloud/websocket-server/bin/swow-cloud:69
    0.6175    8614712   7. Symfony\Component\Console\Terminal->getHeight() /Users/heping/PhpWorkSpace/swow-cloud/websocket-server/vendor/symfony/console/Application.php:140
    0.6319    8940352   8. Symfony\Component\Console\Application->doRun($input = class Symfony\Component\Console\Input\ArgvInput { protected $definition = class Symfony\Component\Console\Input\InputDefinition { private $arguments = [...]; private $requiredCount = 1; private $lastArrayArgument = NULL; private $lastOptionalArgument = NULL; private $options = [...]; private $negations = [...]; private $shortcuts = [...] }; protected $stream = NULL; protected $options = []; protected $arguments = ['command' => 'server:start']; protected $interactive = TRUE; private $tokens = [0 => 'server:start']; private $parsed = [] }, $output = class Symfony\Component\Console\Output\ConsoleOutput { private ${Symfony\Component\Console\Output\Output}verbosity = 32; private ${Symfony\Component\Console\Output\Output}formatter = class Symfony\Component\Console\Formatter\OutputFormatter { private $decorated = TRUE; private $styles = [...]; private $styleStack = class Symfony\Component\Console\Formatter\OutputFormatterStyleStack { ... } }; private ${Symfony\Component\Console\Output\StreamOutput}stream = resource(2) of type (stream); private $stderr = class Symfony\Component\Console\Output\StreamOutput { private ${Symfony\Component\Console\Output\Output}verbosity = 32; private ${Symfony\Component\Console\Output\Output}formatter = class Symfony\Component\Console\Formatter\OutputFormatter { ... }; private $stream = resource(3) of type (stream) }; private $consoleSectionOutputs = [0 => class Symfony\Component\Console\Output\ConsoleSectionOutput { ... }] }) /Users/heping/PhpWorkSpace/swow-cloud/websocket-server/vendor/symfony/console/Application.php:171

系统:MacOs 12.4 m1

[discussion] swow 能与 workerman 搭配使用吗?

期望的效果

目前最期望的是 swow 的 coroutine 能和 workerman 搭配使用,如果能像 goroutines 那样方便就好了。

遇到的问题

在实际使用中,workerman timer 下使用 swow coroutine 协程化封装后的 socket 连接,

要么无法连接到 workerman 的 tcp server, 要么就是连上了无法发送出去数据。

我不太确定是不是我的姿势不对,还是说 swow 不能用于类似 workerman 这种用 pcntl fork 出来的多进程 worker 模式。

测试代码

PHP: 8.1.4
Swow: latest
Workerman: 4.0.33
Composer: 2.3.4

composer require workerman/workerman
composer require swow/swow:dev-develop
use Swow\Coroutine;
use Workerman\Timer;
use Workerman\Worker;
use Workerman\Protocols\Text;

require_once __DIR__ . '/vendor/autoload.php';

// ------------------------------------------------------------------------------

$tcpAddr   = 'tcp://127.0.0.1:1234';
$tcpWorker = new Worker($tcpAddr);
$tcpWorker->count = 4;

$tcpWorker->onConnect = static function ($connection)
{
    echo "New Connection\n";
};

$tcpWorker->onClose = static function ($connection)
{
    echo "Connection closed\n";
};

$tcpWorker->onMessage = static function ($connection, $data)
{
    echo "Message received\n";

    Coroutine::run(static function () use ($connection, $data)
    {
        echo "Received data: $data\n";

        $connection->send("Hello $data \n");
    });
};

// ------------------------------------------------------------------------------

$task = new Worker();
$task->onWorkerStart = static function ($task) use ($tcpAddr)
{
    $timeInterval = 0.1;

    Timer::add($timeInterval, static function () use ($tcpAddr)
    {
        Coroutine::run(static function () use ($tcpAddr)
        {
            $client = stream_socket_client($tcpAddr, $code, $err, 3);

            if (!is_resource($client))
            {
                echo "Connection failed\n";
                return;
            }

            $data   = Text::encode(microtime(true));
            $length = strlen($data);
            $sended = fwrite($client, $data, $length);

            if ($sended !== $length)
            {
                echo "Send failed: $data\n";
            }

            $message = fread($client, 1024);

            echo "Finished: $message\n";

            fclose($client);
        });
    });
};

// ------------------------------------------------------------------------------

Worker::runAll();
php index.php start

New Connection
New Connection
New Connection
....

Warning: [Warning in R225] stream_socket_client(): Unable to connect to tcp://127.0.0.1:1234 (Socket connect has been canceled)
Stack trace:
#0 /.../test_swow/index.php(49): stream_socket_client('tcp://127.0.0.1...', 0, '', 3)
#1 [internal function]: {closure}()
#2 {main}
  triggered in /.../test_swow/index.php on line 49
....

服务启动之后一直打印 New Connection,但是无其他输出。
直到手动停止服务时,会打印出大量的 Socket connect has been canceled 的警告

补充说明

项目实际环境远比上述代码复杂

但是很期望 swow corountine 能像 goroutines 一样简单省心

希望大佬们能给点指点

[discussion] 能否把这个拓展无缝替换swoole

能否不改变目前用到swoole项目代码的情况下直接加swow拓展行不行?我们目前有几个遗留项目使用的easy-swoole框架,其他是golang和laravel项目,我的点奥配置不好,用了两年的电脑丢掉挺可惜。因此想直接在windows下面不用docker,wsl,虚拟机,cygwin的情况下,只要满足开发需求即可,不需要实际linux的效果,因为最终测试和压测都是在部署环境进行。

[bug] (使用 ab 命令测试时 php进程自动结束)

Describe the bug / 问题描述
使用 ab 命令进行测试,ab命令输出: apr_socket_recv: 远程主机强迫关闭了一个现有的连接。 (730054),并且php进程自动结束

To Reproduce / 如何复现

  1. php index.php
  2. .\ab.exe -n 1000 -c 60 http://127.0.0.1:8088/

Expected behavior / 正确的行为

ab命令不报错,php进程不自动结束

Outputs / 程序输出

php进程结束无任何输出

Runtime Environment / 运行环境

OS:

Caption=Microsoft Windows 10 家庭中文版
CSDVersion=
OSArchitecture=64 位
OSLanguage=2052
TotalVisibleMemorySize=16571704
Version=10.0.19042

Architecture=9
Caption=Intel64 Family 6 Model 140 Stepping 1
Name=11th Gen Intel(R) Core(TM) i5-1135G7 @ 2.40GHz
NumberOfCores=4
NumberOfLogicalProcessors=8

PHP:
PHP 7.4.8 (cli) (built: Jul 9 2020 11:30:33) ( NTS Visual C++ 2017 x64 )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
with Xdebug v2.9.0, Copyright (c) 2002-2019, by Derick Rethans
Additional context / 补充说明

使用代码

<?php
require 'vendor/autoload.php';

use Swow\Coroutine;
use Swow\Http\Exception as HttpException;
use const Swow\Errno\EMFILE;
use const Swow\Errno\ENFILE;
use const Swow\Errno\ENOMEM;

ini_set('memory_limit', '1G');
$server = new Swow\Http\Server();
$server->bind("127.0.0.1", 8088)->listen();
while (true) {
    try {
        $session = $server->acceptSession();
        Coroutine::run(function (Swow\Http\Server\Session $session)  {
            try{
                while (true) {
                    try {
                        $request = null;
                        $request = $session->recvHttpRequest();
                        switch ($request->getPath()) {
                            case '/':
                            {
                                $session->respond("hello world");
                                break;
                            }
                            default:
                            {
                                $session->error(404);
                            }
                        }
                    } catch (HttpException $exception ) {
                        $session->error($exception->getCode(), $exception->getMessage());
                    }
                    if (!$request || !$request->getKeepAlive()) {
                        //echo "break\n";
                        break;
                    }
                }
            }catch (Exception $exception){
                echo  $exception->getMessage();
            } finally {
                $session->close();
            }
        },$session);
    } catch (Exception $exception) {
        if (in_array($exception->getCode(), [EMFILE, ENFILE, ENOMEM], true)) {
            sleep(1);
        } else {
            break;
        }
    }
}

[discussion] Starting a new project, should use Swow or Swoole?

Hello,

We're starting a new project that will include a number of microservices with critical performance requirements. Some HTTP servers and some WebSockets servers.

The question is, should we use Swow or Swoole since we have limited hardware resources and want to make the most of what we have and performance is of essence, and what should be the use cases for each of Swow and Swoole?

[bug] The pcntl_waitpid function causes Coroutine to degenerate into a synchronous function.

<?php

use Swow\Coroutine;
 
function startProcess(string $cmd)
{
    $_ = [];
    $proc = proc_open($cmd, [
        ['pipe', 'r'],
        ['pipe', 'w'],
        ['pipe', 'w'],
    ], $_);

    $pid = (proc_get_status($proc))['pid'];

    var_dump('Start cmd pid='.$pid);

    $status = null;
    $rPid = pcntl_waitpid($pid, $status, WUNTRACED); // Blockage !! 《《《《

    proc_terminate($proc);
    fclose($_[0]);
    fclose($_[1]);
    fclose($_[2]);
    proc_close($proc);

    if (pcntl_wexitstatus($status) !== 0 || $rPid === -1) {
        // --
    } else {
        // --
    }

    var_dump('Stop cmd');
}

Coroutine::run(function () {
    var_dump('start A');
    startProcess('sleep 30');
    var_dump('stop A');
});

Coroutine::run(function () {
    var_dump('start B');
    startProcess('sleep 10');
    var_dump('stop B');
});

Coroutine::run(function () {
    var_dump('start C');
    startProcess('sleep 2');
    var_dump('stop C');
});

sleep(1000);

[discussion] PHP8.0 cURL windows支持: curl_exec返回false

已知使用PHP8.0.2-8.0.6官方devel-pack构建(这个条件可能没有影响)的swow的dll

在官方二进制发布PHP8.0.0-8.0.3二进制下的curl_exec返回值有问题

推测是发生了神奇的ABI变化, 没法判断具体原因

前来看官方发布的PHP8.0.6二进制使用目前任意devel-pack构建的dll都没有问题

建议遇到类似问题的小伙伴更新php到最新的patch版本

在gh更新操作系统镜像中的php版本之前,ci中的windows 8.0测试可能还是会红

stream_set_blocking似乎没有hook到

使用freedsx/ldap包,其中的stream_set_blocking没有hook到,会挂起直到超时返回。
swoole低版本也有这个问题,最新4.5.5版本是OK的。

[bug] Swow\Psr7\Client\Client 不支持content-length为空的返回么?

环境:
macos
php8.1
"swow/swow": "dev-develop"

使用的是 php -S 127.0.0.1:8080 启的服务.

$client = new Client();
$domain = '127.0.0.1';
$request = Psr7::createRequest(method: 'GET', uri: '/index.php');
$response = $client
    ->connect($domain, 8080)
    ->sendRequest($request);

echo 'Response', Psr7::stringifyResponse($response);

返回异常.

Fatal error: Uncaught Swow\Http\ParserException: Expected MESSAGE_COMPLETE, got NONE in /Volumes/Data/PhpProject/Arkin/AcHyperf/vendor/swow/swow/lib/swow-library/src/Http/Protocol/ReceiverTrait.php:481
Stack trace:
#0 /Volumes/Data/PhpProject/Arkin/AcHyperf/vendor/swow/swow/lib/swow-library/src/Psr7/Client/Client.php(107): Swow\Psr7\Client\Client->recvMessageEntity()
#1 /Volumes/Data/PhpProject/Arkin/AcHyperf/vendor/swow/swow/lib/swow-library/src/Psr7/Client/Client.php(133): Swow\Psr7\Client\Client->recvResponseEntity()
#2 /Volumes/Data/PhpProject/Arkin/AcHyperf/bin/swow.php(18): Swow\Psr7\Client\Client->sendRequest(Object(Swow\Psr7\Message\Request))
#3 {main}

Next Swow\Psr7\Client\ClientRequestException: Protocol Parsing Error in /Volumes/Data/PhpProject/Arkin/AcHyperf/vendor/swow/swow/lib/swow-library/src/Http/Protocol/ReceiverTrait.php:517
Stack trace:
#0 /Volumes/Data/PhpProject/Arkin/AcHyperf/vendor/swow/swow/lib/swow-library/src/Psr7/Client/Client.php(107): Swow\Psr7\Client\Client->recvMessageEntity()
#1 /Volumes/Data/PhpProject/Arkin/AcHyperf/vendor/swow/swow/lib/swow-library/src/Psr7/Client/Client.php(133): Swow\Psr7\Client\Client->recvResponseEntity()
#2 /Volumes/Data/PhpProject/Arkin/AcHyperf/bin/swow.php(18): Swow\Psr7\Client\Client->sendRequest(Object(Swow\Psr7\Message\Request))
#3 {main}
  thrown in /Volumes/Data/PhpProject/Arkin/AcHyperf/vendor/swow/swow/lib/swow-library/src/Http/Protocol/ReceiverTrait.php on line 517

curl返回正常:

➜  8.1.12  curl -v http://127.0.0.1:8080/index.php
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to 127.0.0.1 (127.0.0.1) port 8080 (#0)
> GET /index.php HTTP/1.1
> Host: 127.0.0.1:8080
> User-Agent: curl/7.64.1
> Accept: */*
> 
< HTTP/1.1 200 OK
< Host: 127.0.0.1:8080
< Date: Thu, 24 Nov 2022 07:05:06 GMT
< Connection: close
< X-Powered-By: PHP/8.1.12
< Content-type: text/html; charset=UTF-8
< 
* Closing connection 0
ok%  

GuzzleHttp解析正常.
Postman浏览器解析正常.

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.