00001
00002
00003
00004
00005 #include "copyright.h"
00006 #include "config.h"
00007
00008 #include <sys/types.h>
00009 #include <sys/stat.h>
00010 #include <unistd.h>
00011 #include <sys/file.h>
00012 #include <sys/ioctl.h>
00013 #include <sys/wait.h>
00014 #include <signal.h>
00015 #include <errno.h>
00016 #include <netdb.h>
00017 #include <arpa/inet.h>
00018 #include "externs.h"
00019
00020 struct listening_socket_t {
00021 int fd;
00022 struct sockaddr_storage addr;
00023 int salen;
00024 struct event ev;
00025 struct listening_socket_t *next;
00026 } *listening_sockets = NULL;
00027
00028 DESC *descriptor_list = NULL;
00029
00030 int network_init(int port);
00031
00032 static void network_accept_client(int fd, short event, void *arg);
00033 static int network_bind_port(struct sockaddr *addr, int salen);
00034 static void network_make_nonblocking(int socket);
00035 static void network_make_blocking(int socket);
00036 DESC *network_initialize_socket(int socket, struct sockaddr *saddr,
00037 int addrlen);
00038
00039 static int network_bind_port(struct sockaddr *addr, int salen)
00040 {
00041 int one = 1;
00042 struct listening_socket_t *lst = NULL;
00043
00044 lst = malloc(sizeof(struct listening_socket_t));
00045 memset(lst, 0, sizeof(struct listening_socket_t));
00046
00047 lst->fd = socket(addr->sa_family, SOCK_STREAM, 0);
00048 if(lst->fd < 0) {
00049 log_perror("NET", "FAIL", "network_bind_port", "socket");
00050 goto error;
00051 }
00052
00053 if(setsockopt(lst->fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) < 0) {
00054 log_perror("NET", "WARN", "network_bind_port", "setsockopt");
00055 }
00056
00057 memcpy(&lst->addr, addr, salen);
00058 lst->salen = salen;
00059
00060 if(bind(lst->fd, (struct sockaddr *) &lst->addr, lst->salen) < 0) {
00061 log_perror("NET", "FAIL", "network_bind_port", "bind");
00062 goto error;
00063 }
00064
00065 if(listen(lst->fd, 0) < 0) {
00066 log_perror("NET", "FAIL", "network_bind_port", "listen");
00067 goto error;
00068 }
00069
00070 network_make_nonblocking(lst->fd);
00071
00072 event_set(&lst->ev, lst->fd, EV_READ | EV_PERSIST, network_accept_client,
00073 lst);
00074 event_add(&lst->ev, NULL);
00075
00076 lst->next = listening_sockets;
00077 listening_sockets = lst;
00078 return 1;
00079
00080 error:
00081 if(lst->fd >= 0) {
00082 close(lst->fd);
00083 }
00084 memset(lst, 0, sizeof(struct listening_socket_t));
00085 return 0;
00086 }
00087
00088 int network_init(int port)
00089 {
00090 struct addrinfo hints;
00091 struct addrinfo *res, *walk;
00092 char myservice[128];
00093 char hostname[1025];
00094 int error;
00095
00096 snprintf(myservice, 32, "%d", port + 10);
00097
00098 signal(SIGPIPE, SIG_IGN);
00099
00100 memset(&hints, 0, sizeof(hints));
00101 hints.ai_family = AF_UNSPEC;
00102 hints.ai_flags =
00103 AI_PASSIVE | AI_NUMERICSERV | AI_ADDRCONFIG | AI_ALL | AI_V4MAPPED;
00104 hints.ai_socktype = SOCK_STREAM;
00105 error = getaddrinfo(NULL, myservice, &hints, &res);
00106 walk = res;
00107 if(error)
00108 perror(gai_strerror(error));
00109 else {
00110
00111
00112
00113
00114
00115 while (walk) {
00116 if(getnameinfo(walk->ai_addr, walk->ai_addrlen, hostname, 1025,
00117 myservice, 128, NI_NUMERICSERV)) {
00118 log_printf("network] serious problem in getnameinfo().");
00119 }
00120 if(network_bind_port(walk->ai_addr, walk->ai_addrlen) == 0) {
00121 log_printf("network] binding to %s %s %s failed.",
00122 (walk->ai_family == AF_INET6 ? "IPv6" : "IPv4"),
00123 hostname, myservice);
00124 } else {
00125 log_printf("network] bound to %s %s %s. ",
00126 (walk->ai_family == AF_INET6 ? "IPv6" : "IPv4"),
00127 hostname, myservice);
00128 }
00129
00130 walk = walk->ai_next;
00131 }
00132 }
00133 freeaddrinfo(res);
00134 return 1;
00135 }
00136
00137 static void network_make_nonblocking(int s)
00138 {
00139 long flags = 0;
00140
00141 if(fcntl(s, F_GETFL, &flags) < 0) {
00142 log_perror("NET", "FAIL", "make_nonblocking", "fcntl F_GETFL");
00143 }
00144 flags |= O_NONBLOCK;
00145 if(fcntl(s, F_SETFL, flags) < 0) {
00146 log_perror("NET", "FAIL", "make_nonblocking", "fcntl F_SETFL");
00147 }
00148 flags = 1;
00149 if(setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &flags, sizeof(flags)) < 0) {
00150 log_perror("NET", "FAIL", "make_nonblocking", "setsockopt NDELAY");
00151 }
00152 }
00153
00154 static void network_make_blocking(int s)
00155 {
00156 long flags = 0;
00157
00158 if(fcntl(s, F_GETFL, &flags) < 0) {
00159 log_perror("NET", "FAIL", "make_blocking", "fcntl F_GETFL");
00160 }
00161 flags &= ~O_NONBLOCK;
00162 if(fcntl(s, F_SETFL, flags) < 0) {
00163 log_perror("NET", "FAIL", "make_blocking", "fcntl F_SETFL");
00164 }
00165 flags = 0;
00166 if(setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &flags, sizeof(flags)) < 0) {
00167 log_perror("NET", "FAIL", "make_blocking", "setsockopt NDELAY");
00168 }
00169 }
00170
00171
00172 void network_choke_socket(DESC * desc)
00173 {
00174 int eins = 1;
00175
00176 if(desc->chokes == 0) {
00177 #if defined(TCP_CORK) // Linux 2.4, 2.6
00178 setsockopt(d->fd, IPPROTO_TCP, TCP_CORK, &eins, sizeof(eins));
00179 #elif defined(TCP_NOPUSH) // *BSD, Mac OS X
00180 setsockopt(d->fd, IPPROTO_TCP, TCP_NOPUSH, &eins, sizeof(eins));
00181 #else // else
00182
00183 #endif
00184 }
00185 desc->chokes++;
00186 }
00187
00188 void network_release_socket(DESC * desc)
00189 {
00190 int null = 0;
00191
00192 desc->chokes--;
00193 if(desc->chokes < 0)
00194 desc->chokes = 0;
00195
00196 if(desc->chokes == 0) {
00197 #if defined(TCP_CORK) // Linux 2.4, 2.6
00198 setsockopt(d->fd, IPPROTO_TCP, TCP_CORK, &null, sizeof(null));
00199 #elif defined(TCP_NOPUSH) // *BSD, Mac OS X
00200 setsockopt(d->fd, IPPROTO_TCP, TCP_NOPUSH, &null, sizeof(null));
00201 #else // else
00202
00203 #endif
00204 }
00205 }
00206
00207 static void network_accept_client(int fd, short event, void *arg)
00208 {
00209 int newfd;
00210 struct sockaddr_storage addr;
00211 unsigned int addrlen = sizeof(struct sockaddr_storage);
00212 struct descriptor_data *desc;
00213
00214 newfd = accept(fd, (struct sockaddr *) addr, &addrlen);
00215 if(newfd < 0) {
00216 log_printf("network] accept on %d failed with '%s'", fd,
00217 strerror(errno));
00218 return;
00219 }
00220 desc = network_initialize_socket(newfd, addr, addrlen);
00221 log_printf("network] connection from %s %d", desc->ip, desc->port);
00222 }
00223
00224 DESC *network_initialize_socket(int socket, struct sockaddr * addr,
00225 int addrlen)
00226 {
00227 char remotehost[NETWORK_HOSTNAME_MAX];
00228 char remoteport[NETWORK_PORTNAME_MAX];
00229 DESC *desc;
00230
00231 desc = malloc(sizeof(DESC));
00232 memset(desc, 0, sizeof(DESC));
00233
00234 desc->fd = socket;
00235
00236 memcpy(desc->saddr, addr, addrlen);
00237
00238 if(getnameinfo(addr, addrlen, remotehost, NETWORK_HOSTNAME_MAX,
00239 remoteport, NETWORK_PORTNAME_MAX,
00240 NI_NUMERICSERV | NI_NUMERICHOST)) {
00241 log_printf("network] getnameinfo failed!");
00242 desc->ip = strdup("unspec");
00243 desc->port = -1;
00244 } else {
00245 desc->ip = strdup(remotehost);
00246 desc->port = itoa(remoteport);
00247 }
00248
00249 network_make_nonblocking(socket);
00250
00251 desc->connected_at = mudstate.now;
00252 desc->retries_left = mudconf.retry_limit;
00253 desc->timeout = mudconf.idle_timeout;
00254 desc->host_info = 1;
00255 desc->next = descriptor_list;
00256 descriptor->list = desc;
00257
00258 desc->sock_buff = bufferevent_new(desc->fd, network_write_callback,
00259 network_read_callback,
00260 network_error_callback, NULL);
00261 bufferevent_disable(desc->sock_buff, EV_READ);
00262 bufferevent_enable(desc->sock_buff, EV_WRITE);
00263 event_set(&desc->sock_ev, desc->fd, EV_READ | EV_PERSIST,
00264 network_accept_input, d);
00265 event_add(&desc->sock_ev, NULL);
00266 telnet_init(desc);
00267
00268 welcome_user(desc);
00269
00270 return desc;
00271 }
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281 static void network_client_input(int fd, short event, void *arg)
00282 {
00283 struct DESC *client = (DESC *) arg;
00284 int avail, net_length;
00285
00286 dprintk("fd = %d, head = %d, tail = %d", client->fd, client->ringhead,
00287 client->ringtail);
00288 if(client->ringtail < client->ringhead) {
00289 avail = client->ringhead - client->ringtail;
00290 handle_errno(net_length = read(client->fd,
00291 client->ringbuffer + client->ringtail,
00292 avail));
00293 } else {
00294 if(client->ringhead == 0) {
00295 avail = RING_LENGTH - client->ringtail;
00296 handle_errno(net_length = read(client->fd,
00297 client->ringbuffer +
00298 client->ringtail, avail));
00299 client->ringtail = (client->ringtail + net_length) % RING_LENGTH;
00300 } else {
00301 avail = RING_LENGTH - client->ringtail;
00302 handle_errno(net_length = read(client->fd,
00303 client->ringbuffer +
00304 client->ringtail, avail));
00305 client->ringtail = (client->ringtail + net_length) % RING_LENGTH;
00306 if(net_length && net_length == avail) {
00307 handle_errno(net_length += read(client->fd,
00308 client->ringbuffer,
00309 client->ringhead - 1));
00310 client->ringtail += net_length - avail;
00311 }
00312 }
00313 }
00314
00315 dprintk("net_length = %d", net_length);
00316
00317 if(net_length == 0) {
00318 printf(" client disconnected.\n");
00319 client_disconnect(client);
00320 return;
00321 }
00322
00323 telnet_read_ring(client);
00324 }
00325
00326 void network_write(DESC * client, char *buffer, int length)
00327 {
00328 bufferevent_write(d->sock_buff, buffer, length);
00329 client->output_tot += length;
00330 }