123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159 |
- /* This file is part of libepistle.
- *
- * libepistle is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * libepistle is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with libepistle. If not, see <http://www.gnu.org/licenses/>.
- */
- #include <unistd.h>
- #include <sys/epoll.h>
- #include "err.h"
- #include "polling.h"
- #include "msg_server.h"
- struct tmp_extra {
- Msg_server *server;
- Add_msgr add;
- Remove_msgr remove;
- React_msg react;
- void *extra;
- };
- int
- msg_server_init(Msg_server *server, int epoll_fd, uint32_t max_len,
- Disposer *extra_dspr, Err *err)
- {
- server->max_len = max_len;
- if (msgrs_init(&server->msgrs, extra_dspr, err) < 0)
- return -1;
- if (epoll_fd < 0 && (epoll_fd = epoll_create1(0)) < 0) {
- err_std(err);
- map_dispose(&server->msgrs);
- return -1;
- }
- server->epoll_fd = epoll_fd;
- return 0;
- }
- void
- msg_server_dispose(Msg_server *server)
- {
- close(server->epoll_fd);
- map_dispose(&server->msgrs);
- }
- int
- msg_server_on(Msg_server *server, int socket, Err *err)
- {
- return poll_add(server->epoll_fd, socket, err);
- }
- int
- msg_server_off(Msg_server *server, int socket, Err *err)
- {
- return poll_remove(server->epoll_fd, socket, err);
- }
- static int
- s_check(int fd, void *extra)
- {
- struct tmp_extra *tmp_extra = extra;
- /* If msgrs doesn't contains the fd it is a server */
- return !set_contains(&tmp_extra->server->msgrs, sizeof(fd), &fd);
- }
- static int
- msg_react(int epoll_fd, int fd, int server_fd, int pm_event,
- Err *err, void *extra)
- {
- struct tmp_extra *tmp_extra = extra;
- Msg_server *server = tmp_extra->server;
- Msgr *msgr;
- (void) epoll_fd;
- switch (pm_event) {
- case PM_ADD:
- return tmp_extra->add(server, fd, server_fd,
- err, tmp_extra->extra);
- case PM_REMOVE:
- return tmp_extra->remove(server, fd, err,
- tmp_extra->extra);
- case PM_INPUT:
- msgr = msgr_get(&server->msgrs, sizeof(fd), &fd);
- /* we haven't yet dealt with previous message! */
- if (msgr->wip && msg_tnsfd(msgr->wip))
- return tmp_extra->react(server, msgr, err,
- tmp_extra->extra);
- if (msgr_recv(msgr, server->max_len, 0, err) < 0)
- return tmp_extra->remove(server, fd, err,
- tmp_extra->extra);
- if (msgr->wip && msg_tnsfd(msgr->wip))
- return tmp_extra->react(server, msgr, err,
- tmp_extra->extra);
- return POLLING_OKAY;
- case PM_OUTPUT:
- msgr = msgr_get(&server->msgrs, sizeof(fd), &fd);
- if (msgr_send(msgr, server->epoll_fd, 0, err) < 0)
- return tmp_extra->remove(server, fd, err,
- tmp_extra->extra);
- return POLLING_OKAY;
- }
- err_epistle(err, EPISTLE_ERR_TYPE);
- return POLLING_FATAL;
- }
- Msgr *
- msg_server_add(Msg_server *server, int fd, void *extra, Err *err)
- {
- return msgr_add(&server->msgrs, sizeof(fd),
- &fd, fd, server->epoll_fd, extra, err);
- }
- int
- msg_server_remove(Msg_server *server, int fd, void **extra, Err *err)
- {
- return msgr_remove(&server->msgrs, sizeof(fd), &fd, extra, err);
- }
- Msgr *
- msg_server_get(Msg_server *server, int fd)
- {
- return msgr_get(&server->msgrs, sizeof(fd), &fd);
- }
- int
- msg_server(Msg_server *server, Add_msgr add, Remove_msgr remove,
- React_msg react, Err *err, void *extra)
- {
- struct tmp_extra tmp_extra = {
- .server = server, .add = add, .remove = remove,
- .react = react, .extra = extra
- };
- return polling_mode(msg_react, &server->epoll_fd,
- NULL, s_check, err, &tmp_extra);
- }
|