Coverage Report

Created: 2024-09-19 07:08

/src/fluent-bit/lib/monkey/plugins/liana/liana.c
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3
/*  Monkey HTTP Server
4
 *  ==================
5
 *  Copyright 2001-2017 Eduardo Silva <eduardo@monkey.io>
6
 *
7
 *  Licensed under the Apache License, Version 2.0 (the "License");
8
 *  you may not use this file except in compliance with the License.
9
 *  You may obtain a copy of the License at
10
 *
11
 *      http://www.apache.org/licenses/LICENSE-2.0
12
 *
13
 *  Unless required by applicable law or agreed to in writing, software
14
 *  distributed under the License is distributed on an "AS IS" BASIS,
15
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
 *  See the License for the specific language governing permissions and
17
 *  limitations under the License.
18
 */
19
20
#define _GNU_SOURCE
21
22
#include <stdio.h>
23
#include <string.h>
24
25
#include <sys/types.h>
26
#include <fcntl.h>
27
28
#ifdef _WIN32
29
#include <winsock2.h>
30
#else
31
#include <arpa/inet.h>
32
#include <sys/socket.h>
33
#include <netdb.h>
34
#endif
35
36
#if defined (__linux__)
37
#include <sys/sendfile.h>
38
#endif
39
40
#include <monkey/mk_api.h>
41
42
int mk_liana_plugin_init(struct mk_plugin *plugin, char *confdir)
43
0
{
44
0
    (void) confdir;
45
0
    (void) plugin;
46
47
0
    return 0;
48
0
}
49
50
int mk_liana_plugin_exit(struct mk_plugin *plugin)
51
0
{
52
0
    (void) plugin;
53
54
0
    return 0;
55
0
}
56
57
int mk_liana_read(struct mk_plugin *plugin, int socket_fd, void *buf, int count)
58
0
{
59
0
    (void) plugin;
60
61
0
    return recv(socket_fd, (void*)buf, count, 0);
62
0
}
63
64
int mk_liana_write(struct mk_plugin *plugin, int socket_fd, const void *buf, size_t count )
65
0
{
66
0
    ssize_t bytes_sent = -1;
67
68
0
    (void) plugin;
69
70
0
    bytes_sent = send(socket_fd, buf, count, 0);
71
72
0
    return bytes_sent;
73
0
}
74
75
int mk_liana_writev(struct mk_plugin *plugin, int socket_fd, struct mk_iov *mk_io)
76
0
{
77
0
    ssize_t bytes_sent = -1;
78
79
0
    (void) plugin;
80
81
0
    bytes_sent = plugin->api->iov_send(socket_fd, mk_io);
82
83
0
    return bytes_sent;
84
0
}
85
86
int mk_liana_close(struct mk_plugin *plugin, int socket_fd)
87
0
{
88
0
    (void) plugin;
89
90
#ifdef _WIN32
91
    return closesocket(socket_fd);
92
#else
93
0
    return close(socket_fd);
94
0
#endif
95
0
}
96
97
int mk_liana_send_file(struct mk_plugin *plugin, int socket_fd, int file_fd, off_t *file_offset,
98
                       size_t file_count)
99
0
{
100
0
    ssize_t ret = -1;
101
102
0
    (void) plugin;
103
104
0
#if defined (__linux__)
105
0
    ret = sendfile(socket_fd, file_fd, file_offset, file_count);
106
0
    if (ret == -1 && errno != EAGAIN) {
107
0
        PLUGIN_TRACE("[FD %i] error from sendfile(): %s",
108
0
                     socket_fd, strerror(errno));
109
0
    }
110
0
    return ret;
111
#elif defined (__APPLE__)
112
    off_t offset = *file_offset;
113
    off_t len = (off_t) file_count;
114
115
    ret = sendfile(file_fd, socket_fd, offset, &len, NULL, 0);
116
    if (ret == -1 && errno != EAGAIN) {
117
        PLUGIN_TRACE("[FD %i] error from sendfile(): %s",
118
                     socket_fd, strerror(errno));
119
    }
120
    else if (len > 0) {
121
        *file_offset += len;
122
        return len;
123
    }
124
    return ret;
125
#elif defined (__FreeBSD__)
126
    off_t offset = *file_offset;
127
    off_t len = (off_t) file_count;
128
129
    ret = sendfile(file_fd, socket_fd, offset, len, NULL, 0, 0);
130
    if (ret == -1 && errno != EAGAIN) {
131
        PLUGIN_TRACE("[FD %i] error from sendfile(): %s",
132
                     socket_fd, strerror(errno));
133
    }
134
    else if (len > 0) {
135
        *file_offset += len;
136
        return len;
137
    }
138
    return ret;
139
#else
140
    #pragma message ("This is a terrible sendfile \"implementation\" and just a crutch")
141
142
    ssize_t bytes_written = 0;
143
    ssize_t to_be_sent = -1;
144
    ssize_t send_ret = -1;
145
    uint8_t temporary_buffer[1024];
146
147
    if (NULL != file_offset) {
148
        lseek(file_fd, *file_offset, SEEK_SET);
149
    }
150
151
    while (1) {
152
        memset(temporary_buffer, 0, sizeof(temporary_buffer));
153
154
        ret = read(file_fd, temporary_buffer, sizeof(temporary_buffer));
155
156
        if (0 == ret)
157
        {
158
            return bytes_written;
159
        }
160
        else if (0 > ret)
161
        {
162
            return -1;
163
        }
164
        else if (0 < ret)
165
        {
166
            to_be_sent = ret;
167
168
            while (to_be_sent > 0)
169
            {
170
                send_ret = send(file_fd, &temporary_buffer[ret - to_be_sent], to_be_sent, 0);
171
172
                if (-1 == send_ret)
173
                {
174
                    if (EAGAIN != errno &&
175
                        EWOULDBLOCK != errno)
176
                    {
177
                        return -1;
178
                    }
179
                }
180
                else
181
                {
182
                    bytes_written += send_ret;
183
                    to_be_sent -= send_ret;
184
                }
185
            }
186
        }
187
    }
188
#endif
189
0
}
190
191
/* Network Layer plugin Callbacks */
192
struct mk_plugin_network mk_plugin_network_liana = {
193
    .read          = mk_liana_read,
194
    .write         = mk_liana_write,
195
    .writev        = mk_liana_writev,
196
    .close         = mk_liana_close,
197
    .send_file     = mk_liana_send_file,
198
    .buffer_size   = MK_REQUEST_CHUNK
199
};
200
201
struct mk_plugin mk_plugin_liana = {
202
    /* Identification */
203
    .shortname     = "liana",
204
    .name          = "Liana Network Layer",
205
    .version       = MK_VERSION_STR,
206
    .hooks         = MK_PLUGIN_NETWORK_LAYER,
207
208
    /* Init / Exit */
209
    .init_plugin   = mk_liana_plugin_init,
210
    .exit_plugin   = mk_liana_plugin_exit,
211
212
    /* Init Levels */
213
    .master_init   = NULL,
214
    .worker_init   = NULL,
215
216
    /* Type */
217
    .network       = &mk_plugin_network_liana,
218
219
    /* Capabilities */
220
    .capabilities  = MK_CAP_SOCK_PLAIN
221
};