/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* Monkey HTTP Server * ================== * Copyright 2001-2017 Eduardo Silva * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _GNU_SOURCE #include #include #include #include #ifdef _WIN32 #include #else #include #include #include #endif #if defined (__linux__) #include #endif #include int mk_liana_plugin_init(struct mk_plugin *plugin, char *confdir) { (void) confdir; (void) plugin; return 0; } int mk_liana_plugin_exit(struct mk_plugin *plugin) { (void) plugin; return 0; } int mk_liana_read(struct mk_plugin *plugin, int socket_fd, void *buf, int count) { (void) plugin; return recv(socket_fd, (void*)buf, count, 0); } int mk_liana_write(struct mk_plugin *plugin, int socket_fd, const void *buf, size_t count ) { ssize_t bytes_sent = -1; (void) plugin; bytes_sent = send(socket_fd, buf, count, 0); return bytes_sent; } int mk_liana_writev(struct mk_plugin *plugin, int socket_fd, struct mk_iov *mk_io) { ssize_t bytes_sent = -1; (void) plugin; bytes_sent = plugin->api->iov_send(socket_fd, mk_io); return bytes_sent; } int mk_liana_close(struct mk_plugin *plugin, int socket_fd) { (void) plugin; #ifdef _WIN32 return closesocket(socket_fd); #else return close(socket_fd); #endif } int mk_liana_send_file(struct mk_plugin *plugin, int socket_fd, int file_fd, off_t *file_offset, size_t file_count) { ssize_t ret = -1; (void) plugin; #if defined (__linux__) ret = sendfile(socket_fd, file_fd, file_offset, file_count); if (ret == -1 && errno != EAGAIN) { PLUGIN_TRACE("[FD %i] error from sendfile(): %s", socket_fd, strerror(errno)); } return ret; #elif defined (__APPLE__) off_t offset = *file_offset; off_t len = (off_t) file_count; ret = sendfile(file_fd, socket_fd, offset, &len, NULL, 0); if (ret == -1 && errno != EAGAIN) { PLUGIN_TRACE("[FD %i] error from sendfile(): %s", socket_fd, strerror(errno)); } else if (len > 0) { *file_offset += len; return len; } return ret; #elif defined (__FreeBSD__) off_t offset = *file_offset; off_t len = (off_t) file_count; ret = sendfile(file_fd, socket_fd, offset, len, NULL, 0, 0); if (ret == -1 && errno != EAGAIN) { PLUGIN_TRACE("[FD %i] error from sendfile(): %s", socket_fd, strerror(errno)); } else if (len > 0) { *file_offset += len; return len; } return ret; #else #pragma message ("This is a terrible sendfile \"implementation\" and just a crutch") ssize_t bytes_written = 0; ssize_t to_be_sent = -1; ssize_t send_ret = -1; uint8_t temporary_buffer[1024]; if (NULL != file_offset) { lseek(file_fd, *file_offset, SEEK_SET); } while (1) { memset(temporary_buffer, 0, sizeof(temporary_buffer)); ret = read(file_fd, temporary_buffer, sizeof(temporary_buffer)); if (0 == ret) { return bytes_written; } else if (0 > ret) { return -1; } else if (0 < ret) { to_be_sent = ret; while (to_be_sent > 0) { send_ret = send(file_fd, &temporary_buffer[ret - to_be_sent], to_be_sent, 0); if (-1 == send_ret) { if (EAGAIN != errno && EWOULDBLOCK != errno) { return -1; } } else { bytes_written += send_ret; to_be_sent -= send_ret; } } } } #endif } /* Network Layer plugin Callbacks */ struct mk_plugin_network mk_plugin_network_liana = { .read = mk_liana_read, .write = mk_liana_write, .writev = mk_liana_writev, .close = mk_liana_close, .send_file = mk_liana_send_file, .buffer_size = MK_REQUEST_CHUNK }; struct mk_plugin mk_plugin_liana = { /* Identification */ .shortname = "liana", .name = "Liana Network Layer", .version = MK_VERSION_STR, .hooks = MK_PLUGIN_NETWORK_LAYER, /* Init / Exit */ .init_plugin = mk_liana_plugin_init, .exit_plugin = mk_liana_plugin_exit, /* Init Levels */ .master_init = NULL, .worker_init = NULL, /* Type */ .network = &mk_plugin_network_liana, /* Capabilities */ .capabilities = MK_CAP_SOCK_PLAIN };