void sess_init(struct irc_session *sess, const char *server, uint16_t port, const char *nick, const char *user, const char *real, const char *pass) { memset(sess, 0, sizeof(*sess)); sess->channels = hashtable_new_with_free( ascii_hash, ascii_equal, free, irc_channel_free); sess->capabilities = hashtable_new_with_free( ascii_hash, ascii_equal, free, free); sess->start = time(NULL); strncpy(sess->hostname, server, sizeof(sess->hostname) - 1); sess->portno = port; strncpy(sess->nick, nick, sizeof(sess->nick) - 1); strncpy(sess->user, user, sizeof(sess->user) - 1); strncpy(sess->real, real, sizeof(sess->real) - 1); strncpy(sess->serverpass, pass, sizeof(sess->serverpass) - 1); tokenbucket_init(&sess->quota, FLOODPROT_CAPACITY, FLOODPROT_RATE); }
bool sockobj_open(struct sockobj * const obj) { bool ret = false; int32_t portsize = 0, flags; struct addrinfo *alist = NULL, *anext = NULL, ahints; socklen_t optlen, optval; char ipport[6]; if (UTILDEBUG_VERIFY(obj != NULL)) { memset(&ahints, 0, sizeof(struct addrinfo)); ahints.ai_family = obj->conf.family; ahints.ai_socktype = obj->conf.type; ahints.ai_flags = AI_V4MAPPED | AI_ADDRCONFIG; ahints.ai_protocol = 0; ahints.ai_canonname = NULL; ahints.ai_addr = NULL; ahints.ai_next = NULL; portsize = snprintf(ipport, 6, "%d", obj->conf.ipport); if ((portsize > 0) && (portsize < 6) && (getaddrinfo(obj->conf.ipaddr, ipport, &ahints, &alist) == 0)) { for (anext = alist; anext != NULL; anext = anext->ai_next) { if ((anext->ai_family == obj->conf.family) && ((obj->fd = socket(anext->ai_family, anext->ai_socktype, anext->ai_protocol)) != -1)) { obj->addrself.sockaddr.ss_family = anext->ai_family; inet_pton(obj->addrself.sockaddr.ss_family, obj->conf.ipaddr, utilinet_getaddrfromstorage(&obj->addrself.sockaddr)); *utilinet_getportfromstorage(&obj->addrself.sockaddr) = htons(obj->conf.ipport); obj->addrself.addrlen = anext->ai_addrlen; obj->addrpeer.sockaddr.ss_family = anext->ai_family; inet_pton(obj->addrpeer.sockaddr.ss_family, obj->conf.ipaddr, utilinet_getaddrfromstorage(&obj->addrpeer.sockaddr)); *utilinet_getportfromstorage(&obj->addrpeer.sockaddr) = htons(obj->conf.ipport); obj->addrpeer.addrlen = anext->ai_addrlen; optlen = sizeof(obj->info.recv.winsize); optval = 1; obj->event.ops.fion_insertfd(&obj->event, obj->fd); flags = fcntl(obj->fd, F_GETFL, 0); if (!obj->event.ops.fion_setflags(&obj->event)) { logger_printf(LOGGER_LEVEL_ERROR, "%s: socket %u event creation failed\n", __FUNCTION__, obj->sid, errno); sockobj_close(obj); } else if (fcntl(obj->fd, F_SETFL, flags | O_NONBLOCK) != 0) { logger_printf(LOGGER_LEVEL_ERROR, "%s: socket %u O_NONBLOCK option failed (%d)\n", __FUNCTION__, obj->sid, errno); } // @todo - SO_LINGER? etc else if (setsockopt(obj->fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) != 0) { logger_printf(LOGGER_LEVEL_ERROR, "%s: socket %u SO_REUSEADDR option failed (%d)\n", __FUNCTION__, obj->sid, errno); sockobj_close(obj); } #if defined(SO_REUSEPORT) else if (setsockopt(obj->fd, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval)) != 0) { logger_printf(LOGGER_LEVEL_ERROR, "%s: socket %u SO_REUSEPORT option failed (%d)\n", __FUNCTION__, obj->sid, errno); sockobj_close(obj); } #endif #if defined(__APPLE__) else if (setsockopt(obj->fd, SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval)) != 0) { logger_printf(LOGGER_LEVEL_ERROR, "%s: socket %u SO_NOSIGPIPE option failed (%d)\n", __FUNCTION__, obj->sid, errno); sockobj_close(obj); } #endif else if (getsockopt(obj->fd, SOL_SOCKET, SO_RCVBUF, &obj->info.recv.winsize, &optlen) != 0) { logger_printf(LOGGER_LEVEL_ERROR, "%s: socket %u SO_RCVBUF option failed (%d)\n", __FUNCTION__, obj->sid, errno); sockobj_close(obj); } else if (getsockopt(obj->fd, SOL_SOCKET, SO_SNDBUF, &obj->info.send.winsize, &optlen) != 0) { logger_printf(LOGGER_LEVEL_ERROR, "%s: socket %u SO_SNDBUF option failed (%d)\n", __FUNCTION__, obj->sid, errno); sockobj_close(obj); } else { tokenbucket_init(&obj->tb, obj->conf.ratelimitbps); obj->state = SOCKOBJ_STATE_OPEN; ret = true; } break; } } freeaddrinfo(alist); } else { logger_printf(LOGGER_LEVEL_ERROR, "%s: failed to get address information (%d)\n", __FUNCTION__, errno); } } return ret; }