#include "copyright.h"
#include "config.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#include <sys/wait.h>
#include <signal.h>
#include <errno.h>
#include <netdb.h>
#include <arpa/inet.h>
#include "externs.h"
Include dependency graph for network.c:
Go to the source code of this file.
Data Structures | |
struct | listening_socket_t |
Functions | |
int | network_init (int port) |
static void | network_accept_client (int fd, short event, void *arg) |
static int | network_bind_port (struct sockaddr *addr, int salen) |
static void | network_make_nonblocking (int socket) |
static void | network_make_blocking (int socket) |
DESC * | network_initialize_socket (int socket, struct sockaddr *saddr, int addrlen) |
void | network_choke_socket (DESC *desc) |
void | network_release_socket (DESC *desc) |
static void | network_client_input (int fd, short event, void *arg) |
void | network_write (DESC *client, char *buffer, int length) |
Variables | |
listening_socket_t * | listening_sockets |
DESC * | descriptor_list = NULL |
static void network_accept_client | ( | int | fd, | |
short | event, | |||
void * | arg | |||
) | [static] |
Definition at line 207 of file network.c.
References desc, log_printf(), and network_initialize_socket().
Referenced by network_bind_port().
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 }
static int network_bind_port | ( | struct sockaddr * | addr, | |
int | salen | |||
) | [static] |
Definition at line 39 of file network.c.
References listening_socket_t::addr, listening_socket_t::ev, listening_socket_t::fd, listening_sockets, log_perror(), network_accept_client(), network_make_nonblocking(), listening_socket_t::next, and listening_socket_t::salen.
Referenced by network_init().
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 }
void network_choke_socket | ( | DESC * | desc | ) |
Definition at line 172 of file network.c.
References 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 /* Nothing! */ 00183 #endif 00184 } 00185 desc->chokes++; 00186 }
static void network_client_input | ( | int | fd, | |
short | event, | |||
void * | arg | |||
) | [static] |
Definition at line 281 of file network.c.
References dprintk, descriptor_data::fd, handle_errno, and telnet_read_ring().
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 }
int network_init | ( | int | port | ) |
Definition at line 88 of file network.c.
References log_printf(), and network_bind_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 * "res" has a chain of addrinfo structure filled with 00112 * 0.0.0.0 (for IPv4), 0:0:0:0:0:0:0:0 (for IPv6) and alike, 00113 * with port filled for "myservice". 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 }
DESC * network_initialize_socket | ( | int | socket, | |
struct sockaddr * | saddr, | |||
int | addrlen | |||
) |
Definition at line 224 of file network.c.
References desc, descriptor_data::descriptor, descriptor_list, confdata::idle_timeout, log_printf(), mudconf, mudstate, NETWORK_HOSTNAME_MAX, network_make_nonblocking(), NETWORK_PORTNAME_MAX, statedata::now, descriptor_data::remoteport, confdata::retry_limit, telnet_init(), and welcome_user().
Referenced by network_accept_client().
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 }
static void network_make_blocking | ( | int | socket | ) | [static] |
Definition at line 154 of file network.c.
References log_perror().
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 }
static void network_make_nonblocking | ( | int | socket | ) | [static] |
Definition at line 137 of file network.c.
References log_perror().
Referenced by network_bind_port(), and network_initialize_socket().
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 }
void network_release_socket | ( | DESC * | desc | ) |
Definition at line 188 of file network.c.
References 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 /* Nothing! */ 00203 #endif 00204 } 00205 }
void network_write | ( | DESC * | client, | |
char * | buffer, | |||
int | length | |||
) |
Definition at line 326 of file network.c.
References descriptor_data::output_tot.
Referenced by telnet_send_req(), telnet_send_subop(), and telnet_write().
00327 { 00328 bufferevent_write(d->sock_buff, buffer, length); 00329 client->output_tot += length; 00330 }
DESC* descriptor_list = NULL |
struct listening_socket_t * listening_sockets |
Referenced by network_bind_port().