/* This one is actually pretty simple... Might get more calls if we can't write the whole request at once. */ static gboolean http_connected( gpointer data, int source, b_input_condition cond ) { struct http_request *req = data; int st; if( source < 0 ) goto error; if( req->inpa > 0 ) b_event_remove( req->inpa ); sock_make_nonblocking( req->fd ); if( req->ssl ) { st = ssl_write( req->ssl, req->request + req->bytes_written, req->request_length - req->bytes_written ); if( st < 0 ) { if( ssl_errno != SSL_AGAIN ) { ssl_disconnect( req->ssl ); goto error; } } } else { st = write( source, req->request + req->bytes_written, req->request_length - req->bytes_written ); if( st < 0 ) { if( !sockerr_again() ) { closesocket( req->fd ); goto error; } } } if( st > 0 ) req->bytes_written += st; if( req->bytes_written < req->request_length ) req->inpa = b_input_add( source, req->ssl ? ssl_getdirection( req->ssl ) : B_EV_IO_WRITE, http_connected, req ); else req->inpa = b_input_add( source, B_EV_IO_READ, http_incoming_data, req ); return FALSE; error: if( req->status_string == NULL ) req->status_string = g_strdup( "Error while writing HTTP request" ); req->func( req ); http_free( req ); return FALSE; }
static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond ) { struct scd *conn = data; if( source == -1 ) { conn->func( conn->data, 0, NULL, cond ); g_free( conn ); return FALSE; } ssl_init(); gnutls_init( &conn->session, GNUTLS_CLIENT ); if( conn->verify ) gnutls_session_set_ptr( conn->session, (void *) conn->hostname ); #if GNUTLS_VERSION_NUMBER < 0x020c00 gnutls_transport_set_lowat( conn->session, 0 ); #endif gnutls_set_default_priority( conn->session ); gnutls_credentials_set( conn->session, GNUTLS_CRD_CERTIFICATE, xcred ); sock_make_nonblocking( conn->fd ); gnutls_transport_set_ptr( conn->session, (gnutls_transport_ptr) GNUTLS_STUPID_CAST conn->fd ); return ssl_handshake( data, source, cond ); }
static gboolean ssl_connected(gpointer data, gint source, b_input_condition cond) { struct scd *conn = data; if (conn->verify) { /* Right now we don't have any verification functionality for OpenSSL. */ conn->func(conn->data, 1, NULL, cond); if (source >= 0) { closesocket(source); } ssl_conn_free(conn); return FALSE; } if (source == -1) { goto ssl_connected_failure; } if (!initialized) { ssl_init(); } if (ssl_ctx == NULL) { goto ssl_connected_failure; } conn->ssl = SSL_new(ssl_ctx); if (conn->ssl == NULL) { goto ssl_connected_failure; } /* We can do at least the handshake with non-blocking I/O */ sock_make_nonblocking(conn->fd); SSL_set_fd(conn->ssl, conn->fd); if (conn->hostname && !g_ascii_isdigit(conn->hostname[0])) { SSL_set_tlsext_host_name(conn->ssl, conn->hostname); } return ssl_handshake(data, source, cond); ssl_connected_failure: conn->func(conn->data, 0, NULL, cond); ssl_disconnect(conn); return FALSE; }
static int proxy_connect_none(const char *host, unsigned short port, struct PHB *phb) { struct sockaddr_in *sin; struct sockaddr_in me; int fd = -1; if (!(sin = gaim_gethostbyname(host, port))) { g_free(phb); return -1; } if ((fd = socket(sin->sin_family, SOCK_STREAM, 0)) < 0) { g_free(phb); return -1; } sock_make_nonblocking(fd); if( global.conf->iface_out ) { me.sin_family = AF_INET; me.sin_port = 0; me.sin_addr.s_addr = inet_addr( global.conf->iface_out ); if( bind( fd, (struct sockaddr *) &me, sizeof( me ) ) != 0 ) event_debug( "bind( %d, \"%s\" ) failure\n", fd, global.conf->iface_out ); } event_debug("proxy_connect_none( \"%s\", %d ) = %d\n", host, port, fd); if (connect(fd, (struct sockaddr *)sin, sizeof(*sin)) < 0 && !sockerr_again()) { closesocket(fd); g_free(phb); return -1; } else { phb->inpa = b_input_add(fd, GAIM_INPUT_WRITE, gaim_io_connected, phb); phb->fd = fd; return fd; } }
irc_t *irc_new(int fd) { irc_t *irc; struct sockaddr_storage sock; socklen_t socklen = sizeof(sock); char *host = NULL, *myhost = NULL; irc_user_t *iu; GSList *l; set_t *s; bee_t *b; irc = g_new0(irc_t, 1); irc->fd = fd; sock_make_nonblocking(irc->fd); irc->r_watch_source_id = b_input_add(irc->fd, B_EV_IO_READ, bitlbee_io_current_client_read, irc); irc->status = USTATUS_OFFLINE; irc->last_pong = gettime(); irc->nick_user_hash = g_hash_table_new(g_str_hash, g_str_equal); irc->watches = g_hash_table_new(g_str_hash, g_str_equal); irc->iconv = (GIConv) - 1; irc->oconv = (GIConv) - 1; if (global.conf->hostname) { myhost = g_strdup(global.conf->hostname); } else if (getsockname(irc->fd, (struct sockaddr*) &sock, &socklen) == 0) { char buf[NI_MAXHOST + 1]; if (getnameinfo((struct sockaddr *) &sock, socklen, buf, NI_MAXHOST, NULL, 0, 0) == 0) { myhost = g_strdup(ipv6_unwrap(buf)); } } if (getpeername(irc->fd, (struct sockaddr*) &sock, &socklen) == 0) { char buf[NI_MAXHOST + 1]; if (getnameinfo((struct sockaddr *) &sock, socklen, buf, NI_MAXHOST, NULL, 0, 0) == 0) { host = g_strdup(ipv6_unwrap(buf)); } } if (host == NULL) { host = g_strdup("localhost.localdomain"); } if (myhost == NULL) { myhost = g_strdup("localhost.localdomain"); } if (global.conf->ping_interval > 0 && global.conf->ping_timeout > 0) { irc->ping_source_id = b_timeout_add(global.conf->ping_interval * 1000, irc_userping, irc); } irc_connection_list = g_slist_append(irc_connection_list, irc); b = irc->b = bee_new(); b->ui_data = irc; b->ui = &irc_ui_funcs; s = set_add(&b->set, "allow_takeover", "true", set_eval_bool, irc); s = set_add(&b->set, "away_devoice", "true", set_eval_bw_compat, irc); s->flags |= SET_HIDDEN; s = set_add(&b->set, "away_reply_timeout", "3600", set_eval_int, irc); s = set_add(&b->set, "charset", "utf-8", set_eval_charset, irc); s = set_add(&b->set, "default_target", "root", NULL, irc); s = set_add(&b->set, "display_namechanges", "false", set_eval_bool, irc); s = set_add(&b->set, "display_timestamps", "true", set_eval_bool, irc); s = set_add(&b->set, "handle_unknown", "add_channel", NULL, irc); s = set_add(&b->set, "last_version", "0", NULL, irc); s->flags |= SET_HIDDEN; s = set_add(&b->set, "nick_format", "%-@nick", NULL, irc); s = set_add(&b->set, "nick_lowercase", "false", set_eval_bool, irc); s = set_add(&b->set, "nick_underscores", "false", set_eval_bool, irc); s = set_add(&b->set, "offline_user_quits", "true", set_eval_bool, irc); s = set_add(&b->set, "ops", "both", set_eval_irc_channel_ops, irc); s = set_add(&b->set, "paste_buffer", "false", set_eval_bool, irc); s->old_key = g_strdup("buddy_sendbuffer"); s = set_add(&b->set, "paste_buffer_delay", "200", set_eval_int, irc); s->old_key = g_strdup("buddy_sendbuffer_delay"); s = set_add(&b->set, "password", NULL, set_eval_password, irc); s->flags |= SET_NULL_OK | SET_PASSWORD; s = set_add(&b->set, "private", "true", set_eval_bool, irc); s = set_add(&b->set, "query_order", "lifo", NULL, irc); s = set_add(&b->set, "root_nick", ROOT_NICK, set_eval_root_nick, irc); s->flags |= SET_HIDDEN; s = set_add(&b->set, "show_offline", "false", set_eval_bw_compat, irc); s->flags |= SET_HIDDEN; s = set_add(&b->set, "self_messages", "true", set_eval_self_messages, irc); s = set_add(&b->set, "simulate_netsplit", "true", set_eval_bool, irc); s = set_add(&b->set, "timezone", "local", set_eval_timezone, irc); s = set_add(&b->set, "to_char", ": ", set_eval_to_char, irc); s = set_add(&b->set, "typing_notice", "false", set_eval_bool, irc); s = set_add(&b->set, "utf8_nicks", "false", set_eval_utf8_nicks, irc); irc->root = iu = irc_user_new(irc, ROOT_NICK); iu->host = g_strdup(myhost); iu->fullname = g_strdup(ROOT_FN); iu->f = &irc_user_root_funcs; iu = irc_user_new(irc, NS_NICK); iu->host = g_strdup(myhost); iu->fullname = g_strdup(ROOT_FN); iu->f = &irc_user_root_funcs; irc->user = g_new0(irc_user_t, 1); irc->user->host = g_strdup(host); conf_loaddefaults(irc); /* Evaluator sets the iconv/oconv structures. */ set_eval_charset(set_find(&b->set, "charset"), set_getstr(&b->set, "charset")); irc_write(irc, ":%s NOTICE * :%s", irc->root->host, "BitlBee-IRCd initialized, please go on"); if (isatty(irc->fd)) { irc_write(irc, ":%s NOTICE * :%s", irc->root->host, "If you read this, you most likely accidentally " "started BitlBee in inetd mode on the command line. " "You probably want to run it in (Fork)Daemon mode. " "See doc/README for more information."); } g_free(myhost); g_free(host); /* libpurple doesn't like fork()s after initializing itself, so this is the right moment to initialize it. */ #ifdef WITH_PURPLE nogaim_init(); #endif /* SSL library initialization also should be done after the fork, to avoid shared CSPRNG state. This is required by NSS, which refuses to work if a fork is detected */ ssl_init(); for (l = irc_plugins; l; l = l->next) { irc_plugin_t *p = l->data; if (p->irc_new) { p->irc_new(irc); } } return irc; }
static int proxy_connect_none(const char *host, unsigned short port_, struct PHB *phb) { struct sockaddr_in me; int fd = -1; if (phb->gai_cur == NULL) { int ret; char port[6]; struct addrinfo hints; g_snprintf(port, sizeof(port), "%d", port_); memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICSERV; if (!(ret = getaddrinfo(host, port, &hints, &phb->gai))) phb->gai_cur = phb->gai; else event_debug("gai(): %s\n", gai_strerror(ret)); } for (; phb->gai_cur; phb->gai_cur = phb->gai_cur->ai_next) { if ((fd = socket(phb->gai_cur->ai_family, phb->gai_cur->ai_socktype, phb->gai_cur->ai_protocol)) < 0) { event_debug( "socket failed: %d\n", errno); continue; } sock_make_nonblocking(fd); if (global.conf->iface_out) { me.sin_family = AF_INET; me.sin_port = 0; me.sin_addr.s_addr = inet_addr( global.conf->iface_out ); if (bind(fd, (struct sockaddr *) &me, sizeof(me)) != 0) event_debug("bind( %d, \"%s\" ) failure\n", fd, global.conf->iface_out); } event_debug("proxy_connect_none( \"%s\", %d ) = %d\n", host, port_, fd); if (connect(fd, phb->gai_cur->ai_addr, phb->gai_cur->ai_addrlen) < 0 && !sockerr_again()) { event_debug( "connect failed: %s\n", strerror(errno)); closesocket(fd); fd = -1; continue; } else { phb->inpa = b_input_add(fd, B_EV_IO_WRITE, gaim_io_connected, phb); phb->fd = fd; break; } } if(fd < 0 && host) g_free(phb); return fd; }