1#include "fdevent.h" 2#include "buffer.h" 3#include "log.h" 4 5#include <sys/types.h> 6 7#include <unistd.h> 8#include <stdlib.h> 9#include <stdio.h> 10#include <string.h> 11#include <errno.h> 12#include <signal.h> 13#include <fcntl.h> 14 15#ifdef USE_SOLARIS_PORT 16 17static const int SOLARIS_PORT_POLL_READ = POLLIN; 18static const int SOLARIS_PORT_POLL_WRITE = POLLOUT; 19static const int SOLARIS_PORT_POLL_READ_WRITE = POLLIN & POLLOUT; 20 21static int fdevent_solaris_port_event_del(fdevents *ev, int fde_ndx, int fd) { 22 if (fde_ndx < 0) return -1; 23 24 if (0 != port_dissociate(ev->port_fd, PORT_SOURCE_FD, fd)) { 25 log_error_write(ev->srv, __FILE__, __LINE__, "SSS", 26 "port_dissociate failed: ", strerror(errno), ", dying"); 27 28 SEGFAULT(); 29 30 return 0; 31 } 32 33 return -1; 34} 35 36static int fdevent_solaris_port_event_set(fdevents *ev, int fde_ndx, int fd, int events) { 37 const int* user_data = NULL; 38 39 if ((events & FDEVENT_IN) && (events & FDEVENT_OUT)) { 40 user_data = &SOLARIS_PORT_POLL_READ_WRITE; 41 } else if (events & FDEVENT_IN) { 42 user_data = &SOLARIS_PORT_POLL_READ; 43 } else if (events & FDEVENT_OUT) { 44 user_data = &SOLARIS_PORT_POLL_WRITE; 45 } 46 47 if (0 != port_associate(ev->port_fd, PORT_SOURCE_FD, fd, *user_data, (void*) user_data)) { 48 log_error_write(ev->srv, __FILE__, __LINE__, "SSS", 49 "port_associate failed: ", strerror(errno), ", dying"); 50 51 SEGFAULT(); 52 53 return 0; 54 } 55 56 return fd; 57} 58 59static int fdevent_solaris_port_event_get_revent(fdevents *ev, size_t ndx) { 60 int events = 0, e; 61 62 e = ev->port_events[ndx].portev_events; 63 if (e & POLLIN) events |= FDEVENT_IN; 64 if (e & POLLOUT) events |= FDEVENT_OUT; 65 if (e & POLLERR) events |= FDEVENT_ERR; 66 if (e & POLLHUP) events |= FDEVENT_HUP; 67 if (e & POLLPRI) events |= FDEVENT_PRI; 68 if (e & POLLNVAL) events |= FDEVENT_NVAL; 69 70 return e; 71} 72 73static int fdevent_solaris_port_event_get_fd(fdevents *ev, size_t ndx) { 74 return ev->port_events[ndx].portev_object; 75} 76 77static int fdevent_solaris_port_event_next_fdndx(fdevents *ev, int ndx) { 78 size_t i; 79 80 UNUSED(ev); 81 82 i = (ndx < 0) ? 0 : ndx + 1; 83 84 return i; 85} 86 87static void fdevent_solaris_port_free(fdevents *ev) { 88 close(ev->port_fd); 89 free(ev->port_events); 90} 91 92/* if there is any error it will return the return values of port_getn, otherwise it will return number of events **/ 93static int fdevent_solaris_port_poll(fdevents *ev, int timeout_ms) { 94 int i = 0; 95 int ret; 96 unsigned int available_events, wait_for_events = 0; 97 const int *user_data; 98 99 struct timespec timeout; 100 101 timeout.tv_sec = timeout_ms/1000L; 102 timeout.tv_nsec = (timeout_ms % 1000L) * 1000000L; 103 104 /* get the number of file descriptors with events */ 105 if ((ret = port_getn(ev->port_fd, ev->port_events, 0, &wait_for_events, &timeout)) < 0) return ret; 106 107 /* wait for at least one event */ 108 if (0 == wait_for_events) wait_for_events = 1; 109 110 available_events = wait_for_events; 111 112 /* get the events of the file descriptors */ 113 if ((ret = port_getn(ev->port_fd, ev->port_events, ev->maxfds, &available_events, &timeout)) < 0) { 114 /* if errno == ETIME and available_event == wait_for_events we didn't get any events */ 115 /* for other errors we didn't get any events either */ 116 if (!(errno == ETIME && wait_for_events != available_events)) return ret; 117 } 118 119 for (i = 0; i < available_events; ++i) { 120 user_data = (const int *) ev->port_events[i].portev_user; 121 122 if ((ret = port_associate(ev->port_fd, PORT_SOURCE_FD, ev->port_events[i].portev_object, 123 *user_data, (void*) user_data)) < 0) { 124 log_error_write(ev->srv, __FILE__, __LINE__, "SSS", 125 "port_associate failed: ", strerror(errno), ", dying"); 126 127 SEGFAULT(); 128 129 return 0; 130 } 131 } 132 133 return available_events; 134} 135 136int fdevent_solaris_port_init(fdevents *ev) { 137 ev->type = FDEVENT_HANDLER_SOLARIS_PORT; 138#define SET(x) \ 139 ev->x = fdevent_solaris_port_##x; 140 141 SET(free); 142 SET(poll); 143 144 SET(event_del); 145 SET(event_set); 146 147 SET(event_next_fdndx); 148 SET(event_get_fd); 149 SET(event_get_revent); 150 151 if ((ev->port_fd = port_create()) < 0) { 152 log_error_write(ev->srv, __FILE__, __LINE__, "SSS", 153 "port_create() failed (", strerror(errno), "), try to set server.event-handler = \"poll\" or \"select\""); 154 155 return -1; 156 } 157 158 ev->port_events = malloc(ev->maxfds * sizeof(*ev->port_events)); 159 160 return 0; 161} 162 163#else 164int fdevent_solaris_port_init(fdevents *ev) { 165 UNUSED(ev); 166 167 log_error_write(ev->srv, __FILE__, __LINE__, "S", 168 "solaris-eventports not supported, try to set server.event-handler = \"poll\" or \"select\""); 169 170 return -1; 171} 172#endif 173