void irc_destroy_session (irc_session_t * session) { free_ircsession_strings( session ); // The CTCP VERSION must be freed only now if ( session->ctcp_version ) free (session->ctcp_version); if ( session->sock >= 0 ) socket_close (&session->sock); #if defined (ENABLE_THREADS) libirc_mutex_destroy (&session->mutex_session); #endif #if defined (ENABLE_SSL) if ( session->ssl ) SSL_free( session->ssl ); #endif /* * delete DCC data * libirc_remove_dcc_session removes the DCC session from the list. */ while ( session->dcc_sessions ) libirc_remove_dcc_session (session, session->dcc_sessions, 0); libirc_mutex_destroy (&session->mutex_dcc); free (session); }
void irc_destroy_session(irc_session_t * session) { free_ircsession_strings(session); if (session->sock >= 0) socket_close(&session->sock); #if defined (ENABLE_THREADS) libirc_mutex_destroy(&session->mutex_session); #endif while (session->dcc_sessions) libirc_remove_dcc_session(session, session->dcc_sessions, 0); free_line_parser(session->line_parser); fdwatch_free(); #ifdef ENABLE_SSL if (session->ssl) SSL_free(session->ssl); #endif free(session); }
int irc_connect_generic(irc_session_t * session, const char * server, unsigned short port, const char * server_password, const char * nick, const char * username, const char * realname, int protocol_family) { struct irc_addr_t **addresses; int numAddresses = 0; if (!server || !nick) { session->lasterror = LIBIRC_ERR_INVAL; return 1; } if (session->state != LIBIRC_STATE_INIT) { session->lasterror = LIBIRC_ERR_STATE; return 1; } // Free the strings if defined; may be the case when the session is reused after the connection fails free_ircsession_strings(session); if (server[0] == SSL_PREFIX) { #if defined (ENABLE_SSL) server++; session->flags |= SESSIONFL_SSL_CONNECTION; #else session->lasterror = LIBIRC_ERR_SSL_NOT_SUPPORTED; return 1; #endif } if (username) session->username = strdup(username); if (server_password) session->server_password = strdup(server_password); if (realname) session->realname = strdup(realname); session->nick = strdup(nick); session->server = strdup(server); addresses = resolve_hostname_by_dns(session->server, &numAddresses, protocol_family); if (addresses == NULL) { session->lasterror = LIBIRC_ERR_RESOLV; return 1; } int selectedAddress = rand_range(0, numAddresses - 1); // and connect to the IRC server for (; addresses[selectedAddress] != NULL; selectedAddress++) { struct irc_addr_t *currentAddress = addresses[selectedAddress]; int ret = -1; if (currentAddress->family == AF_INET) ret = try_to_connect_ipv4(session, currentAddress, port); #if defined (ENABLE_IPV6) else if (currentAddress->family == AF_INET6) ret = try_to_connect_ipv6(session, currentAddress, port); #endif if (ret == -1) { goto err_out; } if (hasConnection(session)) { break; } else { socket_close(&session->sock); } } if (addresses[selectedAddress] == NULL) { session->lasterror = LIBIRC_ERR_CONNECT; goto err_out; } logprintf(LOG_INFO, "Connection successful!"); free_addresses(addresses); session->state = LIBIRC_STATE_CONNECTING; if (protocol_family == AF_INET6) session->flags |= SESSIONFL_USES_IPV6; return 0; err_out: free_addresses(addresses); return 1; }
int irc_connect6 (irc_session_t * session, const char * server, unsigned short port, const char * server_password, const char * nick, const char * username, const char * realname) { #if defined (ENABLE_IPV6) struct sockaddr_in6 saddr; struct addrinfo ainfo, *res = NULL; char portStr[32], *p; #if defined (_WIN32) int addrlen = sizeof(saddr); HMODULE hWsock; getaddrinfo_ptr_t getaddrinfo_ptr; freeaddrinfo_ptr_t freeaddrinfo_ptr; int resolvesuccess = 0; #endif // Check and copy all the specified fields if ( !server || !nick ) { session->lasterror = LIBIRC_ERR_INVAL; return 1; } if ( session->state != LIBIRC_STATE_INIT ) { session->lasterror = LIBIRC_ERR_STATE; return 1; } // Free the strings if defined; may be the case when the session is reused after the connection fails free_ircsession_strings( session ); // Handle the server # prefix (SSL) if ( server[0] == SSL_PREFIX ) { #if defined (ENABLE_SSL) server++; session->flags |= SESSIONFL_SSL_CONNECTION; #else session->lasterror = LIBIRC_ERR_SSL_NOT_SUPPORTED; return 1; #endif } if ( username ) session->username = strdup (username); if ( server_password ) session->server_password = strdup (server_password); if ( realname ) session->realname = strdup (realname); session->nick = strdup (nick); session->server = strdup (server); // If port number is zero and server contains the port, parse it if ( port == 0 && (p = strchr( session->server, ':' )) != 0 ) { // Terminate the string and parse the port number *p++ = '\0'; port = atoi( p ); } memset( &saddr, 0, sizeof(saddr) ); saddr.sin6_family = AF_INET6; saddr.sin6_port = htons (port); sprintf( portStr, "%u", (unsigned)port ); #if defined (_WIN32) if ( WSAStringToAddressA( (LPSTR)session->server, AF_INET6, NULL, (struct sockaddr *)&saddr, &addrlen ) == SOCKET_ERROR ) { hWsock = LoadLibraryA("ws2_32"); if (hWsock) { /* Determine functions at runtime, because windows systems < XP do not * support getaddrinfo. */ getaddrinfo_ptr = (getaddrinfo_ptr_t)GetProcAddress(hWsock, "getaddrinfo"); freeaddrinfo_ptr = (freeaddrinfo_ptr_t)GetProcAddress(hWsock, "freeaddrinfo"); if (getaddrinfo_ptr && freeaddrinfo_ptr) { memset(&ainfo, 0, sizeof(ainfo)); ainfo.ai_family = AF_INET6; ainfo.ai_socktype = SOCK_STREAM; ainfo.ai_protocol = 0; if ( getaddrinfo_ptr(session->server, portStr, &ainfo, &res) == 0 && res ) { resolvesuccess = 1; memcpy( &saddr, res->ai_addr, res->ai_addrlen ); freeaddrinfo_ptr( res ); } } FreeLibrary(hWsock); } if (!resolvesuccess) { session->lasterror = LIBIRC_ERR_RESOLV; return 1; } } #else if ( inet_pton( AF_INET6, session->server, (void*) &saddr.sin6_addr ) <= 0 ) { memset( &ainfo, 0, sizeof(ainfo) ); ainfo.ai_family = AF_INET6; ainfo.ai_socktype = SOCK_STREAM; ainfo.ai_protocol = 0; if ( getaddrinfo( session->server, portStr, &ainfo, &res ) || !res ) { session->lasterror = LIBIRC_ERR_RESOLV; return 1; } memcpy( &saddr, res->ai_addr, res->ai_addrlen ); freeaddrinfo( res ); } #endif // create the IRC server socket if ( socket_create( PF_INET6, SOCK_STREAM, &session->sock) || socket_make_nonblocking (&session->sock) ) { session->lasterror = LIBIRC_ERR_SOCKET; return 1; } #if defined (ENABLE_SSL) // Init the SSL stuff if ( session->flags & SESSIONFL_SSL_CONNECTION ) { int rc = ssl_init( session ); if ( rc != 0 ) return rc; } #endif // and connect to the IRC server if ( socket_connect (&session->sock, (struct sockaddr *) &saddr, sizeof(saddr)) ) { session->lasterror = LIBIRC_ERR_CONNECT; return 1; } session->state = LIBIRC_STATE_CONNECTING; session->flags = 0; // reset in case of reconnect return 0; #else session->lasterror = LIBIRC_ERR_NOIPV6; return 1; #endif }
int irc_connect (irc_session_t * session, const char * server, unsigned short port, const char * server_password, const char * nick, const char * username, const char * realname) { struct sockaddr_in saddr; char * p; // Check and copy all the specified fields if ( !server || !nick ) { session->lasterror = LIBIRC_ERR_INVAL; return 1; } if ( session->state != LIBIRC_STATE_INIT ) { session->lasterror = LIBIRC_ERR_STATE; return 1; } // Free the strings if defined; may be the case when the session is reused after the connection fails free_ircsession_strings( session ); // Handle the server # prefix (SSL) if ( server[0] == SSL_PREFIX ) { #if defined (ENABLE_SSL) server++; session->flags |= SESSIONFL_SSL_CONNECTION; #else session->lasterror = LIBIRC_ERR_SSL_NOT_SUPPORTED; return 1; #endif } if ( username ) session->username = strdup (username); if ( server_password ) session->server_password = strdup (server_password); if ( realname ) session->realname = strdup (realname); session->nick = strdup (nick); session->server = strdup (server); // If port number is zero and server contains the port, parse it if ( port == 0 && (p = strchr( session->server, ':' )) != 0 ) { // Terminate the string and parse the port number *p++ = '\0'; port = atoi( p ); } // IPv4 address resolving memset( &saddr, 0, sizeof(saddr) ); saddr.sin_family = AF_INET; saddr.sin_port = htons (port); saddr.sin_addr.s_addr = inet_addr( session->server ); if ( saddr.sin_addr.s_addr == INADDR_NONE ) { struct hostent *hp; #if defined HAVE_GETHOSTBYNAME_R int tmp_errno; struct hostent tmp_hostent; char buf[2048]; if ( gethostbyname_r (session->server, &tmp_hostent, buf, sizeof(buf), &hp, &tmp_errno) ) hp = 0; #else hp = gethostbyname (session->server); #endif // HAVE_GETHOSTBYNAME_R if ( !hp ) { session->lasterror = LIBIRC_ERR_RESOLV; return 1; } memcpy (&saddr.sin_addr, hp->h_addr, (size_t) hp->h_length); } // create the IRC server socket if ( socket_create( PF_INET, SOCK_STREAM, &session->sock) || socket_make_nonblocking (&session->sock) ) { session->lasterror = LIBIRC_ERR_SOCKET; return 1; } #if defined (ENABLE_SSL) // Init the SSL stuff if ( session->flags & SESSIONFL_SSL_CONNECTION ) { int rc = ssl_init( session ); if ( rc != 0 ) { session->lasterror = rc; return 1; } } #endif // and connect to the IRC server if ( socket_connect (&session->sock, (struct sockaddr *) &saddr, sizeof(saddr)) ) { session->lasterror = LIBIRC_ERR_CONNECT; return 1; } session->state = LIBIRC_STATE_CONNECTING; session->flags = SESSIONFL_USES_IPV6; // reset in case of reconnect return 0; }