国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

Home php教程 PHP開發(fā) GIT transfer protocol implementation

GIT transfer protocol implementation

Nov 23, 2016 pm 02:18 PM

GIT transfer protocol implementation

Among the three mainstream transfer protocols of GIT, HTTP SSH GIT, the GIT protocol is the least used protocol (that is, the protocol whose URL starts with git://). This is because the git protocol has almost no permission control, either all can be read, all can be written, or all can be read and written. So for code hosting platforms, the purpose of the git protocol is only to support read-only access to public projects.

Among the various transmission protocols of git, the git protocol is undoubtedly the most efficient. HTTP is limited by the characteristics of HTTP, and the transmission process requires the construction of HTTP requests and responses. If it is HTTPS, encryption and decryption are also involved. In addition, HTTP timeout settings and packet size limits will affect user experience.

The performance issues of the SSH protocol mainly focus on encryption and decryption. Of course, these costs are acceptable compared to the user's information security.

The git protocol is actually equivalent to SSH without encryption and verification, so there is no way to talk about permission control. However, in fact, if some synchronization services within the code hosting platform are implemented using the git protocol, the performance will be greatly improved.

Transfer protocol specifications

The technical documentation of the git protocol can be found from Documentation/technical in the git source code directory, that is, Packfile transfer protocols After creating a TCP connection, the git client takes the lead in sending the request body. The request format is described based on BNF as follows:

git-proto-request = request-command SP pathname NUL [ host-parameter NUL ]
request-command   = "git-upload-pack" / "git-receive-pack" / "git-upload-archive"   ; case sensitive
pathname          = *( %x01-ff ) ; exclude NUL
host-parameter    = "host=" hostname [ ":" port ]

An example is as follows:

0033git-upload-pack /project.git

在 C 語言中,有 popen 函數(shù),可以創(chuàng)建一個進程,并將進程的標準輸出或標準輸入創(chuàng)建成一個文件指針,即 FILE*其他可以使用 C 函數(shù)的語言很多也提供了類似的實現(xiàn),比如 Ruby,基于 Ruby 的 git HTTP 服務(wù)器 grack 正是使用 的 popen,相比與其他語言改造的 popen,C 語言中 popen 存在了一些缺陷,比如無法同時讀寫,如果要輸出標準 錯誤,需要在命令參數(shù)中額外的將標準錯誤重定向到標準輸出。

在 musl libc 的中,popen 的實現(xiàn)如下:

FILE *popen(const char *cmd, const char *mode)
{
    int p[2], op, e;
    pid_t pid;
    FILE *f;
    posix_spawn_file_actions_t fa;

    if (*mode == 'r') {
        op = 0;
    } else if (*mode == 'w') {
        op = 1;
    } else {
        errno = EINVAL;
        return 0;
    }

    if (pipe2(p, O_CLOEXEC)) return NULL;
    f = fdopen(p[op], mode);
    if (!f) {
        __syscall(SYS_close, p[0]);
        __syscall(SYS_close, p[1]);
        return NULL;
    }
    FLOCK(f);

    /* If the child's end of the pipe happens to already be on the final
     * fd number to which it will be assigned (either 0 or 1), it must
     * be moved to a different fd. Otherwise, there is no safe way to
     * remove the close-on-exec flag in the child without also creating
     * a file descriptor leak race condition in the parent. */
    if (p[1-op] == 1-op) {
        int tmp = fcntl(1-op, F_DUPFD_CLOEXEC, 0);
        if (tmp < 0) {
            e = errno;
            goto fail;
        }
        __syscall(SYS_close, p[1-op]);
        p[1-op] = tmp;
    }

    e = ENOMEM;
    if (!posix_spawn_file_actions_init(&fa)) {
        if (!posix_spawn_file_actions_adddup2(&fa, p[1-op], 1-op)) {
            if (!(e = posix_spawn(&pid, "/bin/sh", &fa, 0,
                (char *[]){ "sh", "-c", (char *)cmd, 0 }, __environ))) {
                posix_spawn_file_actions_destroy(&fa);
                f->pipe_pid = pid;
                if (!strchr(mode, &#39;e&#39;))
                    fcntl(p[op], F_SETFD, 0);
                __syscall(SYS_close, p[1-op]);
                FUNLOCK(f);
                return f;
            }
        }
        posix_spawn_file_actions_destroy(&fa);
    }
fail:
    fclose(f);
    __syscall(SYS_close, p[1-op]);

    errno = e;
    return 0;
}

在 Windows Visual C++ 中,popen 源碼在?C:\Program Files (x86)\Windows Kits\10\Source\${SDKVersion}\ucrt\conio\popen.cpp?, 按照 MSDN 文檔說明,Windows 32 GUI 程序,即 subsystem 是 Windows 的程序,使用 popen 可能導(dǎo)致程序無限失去響應(yīng)。

所以在筆者實現(xiàn) git-daemon 及其他 git 服務(wù)器時,都不會使用 popen 這個函數(shù)。

為了支持跨平臺和簡化編程,筆者在實現(xiàn) svn 代理服務(wù)器時就使用了 Boost Asio 庫,后來也用 Asio 實現(xiàn)過一個 git 遠程命令服務(wù), 每一個客戶端與服務(wù)器連接后,服務(wù)器啟動程序,需要創(chuàng)建 3 條管道,分別是 子進程的標準輸入 輸出 錯誤,即 stdout stdin stderr, 然后注冊讀寫異步事件,將子進程的輸出與錯誤寫入到 socket 發(fā)送出去,讀取 socket 寫入到子進程的標準輸入中。

在 POSIX 系統(tǒng)中,boost 有一個文件描述符類?boost::asio::posix::stream_descriptor?這個類不能是常規(guī)文件,以前用 go 做 HTTP 前端 沒注意就 coredump 掉。

在 Windows 系統(tǒng)中,boost 有文件句柄類?boost::asio::windows::stream_handle?此處的文件應(yīng)當支持隨機讀取,比如命名管道(當然 在 Windows 系統(tǒng)的,匿名管道實際上也是命名管道的一種特例實現(xiàn))。

以上兩種類都支持?async_read?async_write?,所以可以很方便的實現(xiàn)異步的讀取。

上面的做法,唯一的缺陷是性能并不是非常高,代碼邏輯也比較復(fù)雜,當然好處是,錯誤異??煽匾恍?。

在 Linux 網(wǎng)絡(luò)通信中,類似與 git 協(xié)議這樣讀取子進程輸入輸出的服務(wù)程序的傳統(tǒng)做法是,將 子進程的 IO 重定向到 socket, 值得注意的是 boost 中 socket 是異步非阻塞的,然而,git 命令的標準輸入標準錯誤標準輸出都是同步的,所以在 fork 子進程之 前,需要將 socket 設(shè)置為同步阻塞,當 fork 失敗時,要設(shè)置回來。

socket_.native_non_blocking(false);

另外,為了記錄子進程是否異常退出,需要注冊信號 SIGCHLD 并且使用 waitpid 函數(shù)去等待,boost 就有?boost::asio::signal_set::async_wait?當然,如果你開發(fā)這樣一個服務(wù),會發(fā)現(xiàn),頻繁的啟動子進程,響應(yīng)信號,管理連接,這些操作才是性能的短板。

一般而言,Windows 平臺的 IO 并不能重定向到 socket,實際上,你如果使用 IOCP 也可以達到相應(yīng)的效率。還有,Windows 的 socket API WSASocket WSADuplicateSocket 復(fù)制句柄 DuplicateHandle ,這些可以好好利用。

其他

對于非代碼托管平臺的從業(yè)者來說,上面的相關(guān)內(nèi)容可能顯得無足輕重,不過,網(wǎng)絡(luò)編程都是殊途同歸,最后核心理念都是類似的。關(guān)于 git-daemon 如果筆者有時間會實現(xiàn)一個跨平臺的簡易版并開源。


Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undress AI Tool

Undress AI Tool

Undress images for free

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)