diff --git a/CMakeLists.txt b/CMakeLists.txt index 8696b94..14f1d69 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,11 +17,13 @@ add_library(libircclient ./libircclient/src/errors.c ./libircclient/src/libircclient.c ./libircclient/src/params.h + ./libircclient/src/portable.h ./libircclient/src/portable.c ./libircclient/src/session.h - ./libircclient/src/sockets.c + ./libircclient/src/sockets.h + ./libircclient/src/ssl.h ./libircclient/src/ssl.c - ./libircclient/src/utils.c + ./libircclient/src/utils.h ) target_include_directories(libircclient PUBLIC ./libircclient/include) diff --git a/libircclient/src/dcc.c b/libircclient/src/dcc.c index 2b9f11c..4ce6941 100644 --- a/libircclient/src/dcc.c +++ b/libircclient/src/dcc.c @@ -1,14 +1,14 @@ -/* +/* * Copyright (C) 2004-2012 George Yunaev gyunaev@ulduzsoft.com * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 3 of the License, or (at your + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at your * option) any later version. * - * This library is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. */ @@ -16,6 +16,11 @@ #define LIBIRC_DCC_SENDFILE 2 #define LIBIRC_DCC_RECVFILE 3 +#include "./session.h" +#include "./utils.h" + +#include +#include static irc_dcc_session_t * libirc_find_dcc_session (irc_session_t * session, irc_dcc_t dccid, int lock_list) { @@ -54,7 +59,7 @@ static void libirc_dcc_destroy_nolock (irc_session_t * session, irc_dcc_t dccid) } -static void libirc_remove_dcc_session (irc_session_t * session, irc_dcc_session_t * dcc, int lock_list) +void libirc_remove_dcc_session (irc_session_t * session, irc_dcc_session_t * dcc, int lock_list) { if ( dcc->sock >= 0 ) socket_close (&dcc->sock); @@ -91,7 +96,7 @@ static void libirc_remove_dcc_session (irc_session_t * session, irc_dcc_session_ } -static void libirc_dcc_add_descriptors (irc_session_t * ircsession, fd_set *in_set, fd_set *out_set, int * maxfd) +void libirc_dcc_add_descriptors (irc_session_t * ircsession, fd_set *in_set, fd_set *out_set, int * maxfd) { irc_dcc_session_t * dcc, *dcc_next; time_t now = time (0); @@ -129,8 +134,8 @@ static void libirc_dcc_add_descriptors (irc_session_t * ircsession, fd_set *in_s /* * If we're sending file, and the output buffer is empty, we need - * to provide some data. - */ + * to provide some data. + */ if ( dcc->state == LIBIRC_STATE_CONNECTED && dcc->dccmode == LIBIRC_DCC_SENDFILE && dcc->dccsend_file_fp @@ -141,7 +146,7 @@ static void libirc_dcc_add_descriptors (irc_session_t * ircsession, fd_set *in_s if ( len <= 0 ) { int err = (len < 0 ? LIBIRC_ERR_READ : 0); - + libirc_mutex_unlock (&ircsession->mutex_dcc); (*dcc->cb)(ircsession, dcc->id, err, dcc->ctx, 0, 0); @@ -189,17 +194,17 @@ static void libirc_dcc_add_descriptors (irc_session_t * ircsession, fd_set *in_s case LIBIRC_STATE_CONFIRM_SIZE: /* * If we're receiving file, then WE should confirm the transferred - * part (so we have to sent data). But if we're sending the file, - * then RECEIVER should confirm the packet, so we have to receive - * data. - * - * We don't need to LOCK_DCC_OUTBUF - during file transfer, buffers - * can't change asynchronously. - */ - if ( dcc->dccmode == LIBIRC_DCC_RECVFILE && dcc->outgoing_offset > 0 ) - libirc_add_to_set (dcc->sock, out_set, maxfd); + * part (so we have to sent data). But if we're sending the file, + * then RECEIVER should confirm the packet, so we have to receive + * data. + * + * We don't need to LOCK_DCC_OUTBUF - during file transfer, buffers + * can't change asynchronously. + */ + if ( dcc->dccmode == LIBIRC_DCC_RECVFILE && dcc->outgoing_offset > 0 ) + libirc_add_to_set (dcc->sock, out_set, maxfd); - if ( dcc->dccmode == LIBIRC_DCC_SENDFILE && dcc->incoming_offset < 4 ) + if ( dcc->dccmode == LIBIRC_DCC_SENDFILE && dcc->incoming_offset < 4 ) libirc_add_to_set (dcc->sock, in_set, maxfd); } } @@ -208,14 +213,14 @@ static void libirc_dcc_add_descriptors (irc_session_t * ircsession, fd_set *in_s } -static void libirc_dcc_process_descriptors (irc_session_t * ircsession, fd_set *in_set, fd_set *out_set) +void libirc_dcc_process_descriptors (irc_session_t * ircsession, fd_set *in_set, fd_set *out_set) { irc_dcc_session_t * dcc; /* * We need to use such a complex scheme here, because on every callback - * a number of DCC sessions could be destroyed. - */ + * a number of DCC sessions could be destroyed. + */ libirc_mutex_lock (&ircsession->mutex_dcc); for ( dcc = ircsession->dcc_sessions; dcc; dcc = dcc->next ) @@ -238,14 +243,14 @@ static void libirc_dcc_process_descriptors (irc_session_t * ircsession, fd_set * // On success, change the active socket and change the state if ( err == 0 ) { - // close the listen socket, and replace it by a newly + // close the listen socket, and replace it by a newly // accepted socket_close (&dcc->sock); dcc->sock = nsock; dcc->state = LIBIRC_STATE_CONNECTED; } - // If this is DCC chat, inform the caller about accept() + // If this is DCC chat, inform the caller about accept() // success or failure. // Otherwise (DCC send) there is no reason. if ( dcc->dccmode == LIBIRC_DCC_CHAT ) @@ -262,7 +267,7 @@ static void libirc_dcc_process_descriptors (irc_session_t * ircsession, fd_set * if ( dcc->state == LIBIRC_STATE_CONNECTING && FD_ISSET (dcc->sock, out_set) ) { - // Now we have to determine whether the socket is connected + // Now we have to determine whether the socket is connected // or the connect is failed struct sockaddr_in saddr; socklen_t slen = sizeof(saddr); @@ -295,7 +300,7 @@ static void libirc_dcc_process_descriptors (irc_session_t * ircsession, fd_set * if ( FD_ISSET (dcc->sock, in_set) ) { int length, offset = 0, err = 0; - + unsigned int amount = sizeof (dcc->incoming_buf) - dcc->incoming_offset; length = socket_recv (&dcc->sock, dcc->incoming_buf + dcc->incoming_offset, amount); @@ -303,7 +308,7 @@ static void libirc_dcc_process_descriptors (irc_session_t * ircsession, fd_set * if ( length < 0 ) { err = LIBIRC_ERR_READ; - } + } else if ( length == 0 ) { err = LIBIRC_ERR_CLOSED; @@ -325,9 +330,9 @@ static void libirc_dcc_process_descriptors (irc_session_t * ircsession, fd_set * /* * In LIBIRC_STATE_CONFIRM_SIZE state we don't call any - * callbacks (except there is an error). We just receive - * the data, and compare it with the amount sent. - */ + * callbacks (except there is an error). We just receive + * the data, and compare it with the amount sent. + */ if ( dcc->state == LIBIRC_STATE_CONFIRM_SIZE ) { if ( dcc->dccmode != LIBIRC_DCC_SENDFILE ) @@ -352,10 +357,10 @@ static void libirc_dcc_process_descriptors (irc_session_t * ircsession, fd_set * else { /* - * If it is DCC_CHAT, we send a 0-terminated string + * If it is DCC_CHAT, we send a 0-terminated string * (which is smaller than offset). Otherwise we send - * a full buffer. - */ + * a full buffer. + */ libirc_mutex_unlock (&ircsession->mutex_dcc); if ( dcc->dccmode != LIBIRC_DCC_CHAT ) @@ -365,21 +370,21 @@ static void libirc_dcc_process_descriptors (irc_session_t * ircsession, fd_set * (*dcc->cb)(ircsession, dcc->id, err, dcc->ctx, dcc->incoming_buf, offset); - /* - * If the session is not terminated in callback, - * put the sent amount into the sent_packet_size_net_byteorder - */ - if ( dcc->state != LIBIRC_STATE_REMOVED ) - { - dcc->state = LIBIRC_STATE_CONFIRM_SIZE; - dcc->file_confirm_offset += offset; - + /* + * If the session is not terminated in callback, + * put the sent amount into the sent_packet_size_net_byteorder + */ + if ( dcc->state != LIBIRC_STATE_REMOVED ) + { + dcc->state = LIBIRC_STATE_CONFIRM_SIZE; + dcc->file_confirm_offset += offset; + // Store as big endian dcc->outgoing_buf[0] = (char) dcc->file_confirm_offset >> 24; dcc->outgoing_buf[1] = (char) dcc->file_confirm_offset >> 16; dcc->outgoing_buf[2] = (char) dcc->file_confirm_offset >> 8; dcc->outgoing_buf[3] = (char) dcc->file_confirm_offset; - dcc->outgoing_offset = 4; + dcc->outgoing_offset = 4; } } else @@ -394,10 +399,10 @@ static void libirc_dcc_process_descriptors (irc_session_t * ircsession, fd_set * } } - /* - * If error arises somewhere above, we inform the caller - * of failure, and destroy this session. - */ + /* + * If error arises somewhere above, we inform the caller + * of failure, and destroy this session. + */ if ( err ) { libirc_mutex_unlock (&ircsession->mutex_dcc); @@ -407,30 +412,30 @@ static void libirc_dcc_process_descriptors (irc_session_t * ircsession, fd_set * } } - /* - * Session might be closed (with sock = -1) after the in_set - * processing, so before out_set processing we should check - * for this case + /* + * Session might be closed (with sock = -1) after the in_set + * processing, so before out_set processing we should check + * for this case */ if ( dcc->state == LIBIRC_STATE_REMOVED ) continue; /* * Write bit set - we can send() something, and it won't block. - */ + */ if ( FD_ISSET (dcc->sock, out_set) ) { int length, offset, err = 0; /* - * Because in some cases outgoing_buf could be changed - * asynchronously (by another thread), we should lock + * Because in some cases outgoing_buf could be changed + * asynchronously (by another thread), we should lock * it. - */ + */ libirc_mutex_lock (&dcc->mutex_outbuf); offset = dcc->outgoing_offset; - + if ( offset > 0 ) { length = socket_send (&dcc->sock, dcc->outgoing_buf, offset); @@ -445,7 +450,7 @@ static void libirc_dcc_process_descriptors (irc_session_t * ircsession, fd_set * * If this was DCC_SENDFILE, and we just sent a packet, * change the state to wait for confirmation (and store * sent packet size) - */ + */ if ( dcc->state == LIBIRC_STATE_CONNECTED && dcc->dccmode == LIBIRC_DCC_SENDFILE ) { @@ -465,27 +470,27 @@ static void libirc_dcc_process_descriptors (irc_session_t * ircsession, fd_set * dcc->outgoing_offset -= length; /* - * If we just sent the confirmation data, change state + * If we just sent the confirmation data, change state * back. - */ + */ if ( dcc->state == LIBIRC_STATE_CONFIRM_SIZE && dcc->dccmode == LIBIRC_DCC_RECVFILE && dcc->outgoing_offset == 0 ) { /* * If the file is already received, we should inform - * the caller, and close the session. - */ + * the caller, and close the session. + */ if ( dcc->received_file_size == dcc->file_confirm_offset ) - { + { libirc_mutex_unlock (&ircsession->mutex_dcc); libirc_mutex_unlock (&dcc->mutex_outbuf); (*dcc->cb)(ircsession, dcc->id, 0, dcc->ctx, 0, 0); libirc_dcc_destroy_nolock (ircsession, dcc->id); - } - else - { - /* Continue to receive the file */ + } + else + { + /* Continue to receive the file */ dcc->state = LIBIRC_STATE_CONNECTED; } } @@ -494,10 +499,10 @@ static void libirc_dcc_process_descriptors (irc_session_t * ircsession, fd_set * libirc_mutex_unlock (&dcc->mutex_outbuf); - /* - * If error arises somewhere above, we inform the caller - * of failure, and destroy this session. - */ + /* + * If error arises somewhere above, we inform the caller + * of failure, and destroy this session. + */ if ( err ) { libirc_mutex_unlock (&ircsession->mutex_dcc); @@ -578,7 +583,7 @@ static int libirc_new_dcc_session (irc_session_t * session, unsigned long ip, un memset (&dcc->remote_addr, 0, sizeof(dcc->remote_addr)); dcc->remote_addr.sin_family = AF_INET; dcc->remote_addr.sin_addr.s_addr = htonl (ip); // what idiot came up with idea to send IP address in host-byteorder? - dcc->remote_addr.sin_port = htons(port); + dcc->remote_addr.sin_port = htons(port); dcc->state = LIBIRC_STATE_INIT; } @@ -596,8 +601,8 @@ static int libirc_new_dcc_session (irc_session_t * session, unsigned long ip, un libirc_mutex_unlock (&session->mutex_dcc); - *pdcc = dcc; - return 0; + *pdcc = dcc; + return 0; cleanup_exit_error: if ( dcc->sock >= 0 ) @@ -710,7 +715,7 @@ int irc_dcc_msg (irc_session_t * session, irc_dcc_t dccid, const char * text) } -static void libirc_dcc_request (irc_session_t * session, const char * nick, const char * req) +void libirc_dcc_request (irc_session_t * session, const char * nick, const char * req) { char filenamebuf[256]; unsigned long ip, size; @@ -729,8 +734,8 @@ static void libirc_dcc_request (irc_session_t * session, const char * nick, cons return; } - (*session->callbacks.event_dcc_chat_req) (session, - nick, + (*session->callbacks.event_dcc_chat_req) (session, + nick, inet_ntoa (dcc->remote_addr.sin_addr), dcc->id); } @@ -750,8 +755,8 @@ static void libirc_dcc_request (irc_session_t * session, const char * nick, cons return; } - (*session->callbacks.event_dcc_send_req) (session, - nick, + (*session->callbacks.event_dcc_send_req) (session, + nick, inet_ntoa (dcc->remote_addr.sin_addr), filenamebuf, size, @@ -787,7 +792,7 @@ int irc_dcc_accept (irc_session_t * session, irc_dcc_t dccid, void * ctx, irc_dc dcc->ctx = ctx; // Initiate the connect - if ( socket_connect (&dcc->sock, (struct sockaddr *) &dcc->remote_addr, sizeof(dcc->remote_addr)) ) + if ( socket_connect (&dcc->sock, (struct sockaddr *) &dcc->remote_addr, sizeof(dcc->remote_addr)) ) { libirc_dcc_destroy_nolock (session, dccid); libirc_mutex_unlock (&session->mutex_dcc); diff --git a/libircclient/src/dcc.h b/libircclient/src/dcc.h index deb3355..3e61531 100644 --- a/libircclient/src/dcc.h +++ b/libircclient/src/dcc.h @@ -1,20 +1,27 @@ -/* +/* * Copyright (C) 2004-2012 George Yunaev gyunaev@ulduzsoft.com * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 3 of the License, or (at your + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at your * option) any later version. * - * This library is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. */ #ifndef INCLUDE_IRC_DCC_H #define INCLUDE_IRC_DCC_H +#include + +#include "../include/libircclient.h" + +#include "./sockets.h" +#include "./portable.h" +#include "./params.h" /* * This structure keeps the state of a single DCC connection. @@ -26,11 +33,11 @@ struct irc_dcc_session_s irc_dcc_t id; void * ctx; socket_t sock; /*!< DCC socket */ - int dccmode; /*!< Boolean value to differ chat vs send - requests. Changes the cb behavior - when - it is chat, data is sent by lines with - stripped CRLFs. In file mode, the data - is sent as-is */ + int dccmode; /*!< Boolean value to differ chat vs send + requests. Changes the cb behavior - when + it is chat, data is sent by lines with + stripped CRLFs. In file mode, the data + is sent as-is */ int state; time_t timeout; @@ -50,5 +57,9 @@ struct irc_dcc_session_s irc_dcc_callback_t cb; }; +void libirc_remove_dcc_session (irc_session_t * session, irc_dcc_session_t * dcc, int lock_list); +void libirc_dcc_add_descriptors (irc_session_t * ircsession, fd_set *in_set, fd_set *out_set, int * maxfd); +void libirc_dcc_request (irc_session_t * session, const char * nick, const char * req); +void libirc_dcc_process_descriptors (irc_session_t * ircsession, fd_set *in_set, fd_set *out_set); #endif /* INCLUDE_IRC_DCC_H */ diff --git a/libircclient/src/errors.c b/libircclient/src/errors.c index 6533b89..bcc2632 100644 --- a/libircclient/src/errors.c +++ b/libircclient/src/errors.c @@ -1,18 +1,21 @@ -/* +/* * Copyright (C) 2004-2012 George Yunaev gyunaev@ulduzsoft.com * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 3 of the License, or (at your + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at your * option) any later version. * - * This library is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. */ -static const char * libirc_strerror[LIBIRC_ERR_MAX] = +#include "../include/libircclient.h" +#include "./session.h" + +static const char * libirc_strerror[LIBIRC_ERR_MAX] = { "No error", "Invalid argument", diff --git a/libircclient/src/libircclient.c b/libircclient/src/libircclient.c index 0a753b9..aee8a67 100644 --- a/libircclient/src/libircclient.c +++ b/libircclient/src/libircclient.c @@ -14,17 +14,19 @@ #define IS_DEBUG_ENABLED(s) ((s)->options & LIBIRC_OPTION_DEBUG) -#include "portable.c" -#include "sockets.c" +#include "./portable.h" +#include "./sockets.h" -#include "libircclient.h" -#include "session.h" +#include "../include/libircclient.h" +#include "./session.h" -#include "utils.c" -#include "errors.c" -#include "colors.c" -#include "dcc.c" -#include "ssl.c" +#include "./utils.h" +/*#include "errors.c"*/ +/*#include "colors.c"*/ +#include "./dcc.h" +/*#include "dcc.c"*/ +/*#include "ssl.c"*/ +#include "./ssl.h" #ifdef _MSC_VER @@ -797,11 +799,11 @@ static void libirc_process_incoming_data (irc_session_t * session, size_t proces { ; /* ignore this event - not all servers generate this */ } - else + else { /* - * The "unknown" event is triggered upon receipt of any number of - * unclassifiable miscellaneous messages, which aren't handled by + * The "unknown" event is triggered upon receipt of any number of + * unclassifiable miscellaneous messages, which aren't handled by * the library. */ @@ -816,7 +818,7 @@ int irc_process_select_descriptors (irc_session_t * session, fd_set *in_set, fd_ { char buf[256], hname[256]; - if ( session->sock < 0 + if ( session->sock < 0 || session->state == LIBIRC_STATE_INIT || session->state == LIBIRC_STATE_DISCONNECTED ) { @@ -833,7 +835,7 @@ int irc_process_select_descriptors (irc_session_t * session, fd_set *in_set, fd_ // If the socket is not connected yet, wait longer - it is not an error if ( !FD_ISSET (session->sock, out_set) ) return 0; - + // Now we have to determine whether the socket is connected // or the connect is failed struct sockaddr_storage saddr, laddr; diff --git a/libircclient/src/portable.c b/libircclient/src/portable.c index 02ab041..69e1119 100644 --- a/libircclient/src/portable.c +++ b/libircclient/src/portable.c @@ -1,132 +1,18 @@ -/* +/* * Copyright (C) 2004-2012 George Yunaev gyunaev@ulduzsoft.com * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 3 of the License, or (at your + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at your * option) any later version. * - * This library is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. */ -#if !defined (_WIN32) - #include "config.h" - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - - #if defined (ENABLE_THREADS) - #include - typedef pthread_mutex_t port_mutex_t; - - #if !defined (PTHREAD_MUTEX_RECURSIVE) && defined (PTHREAD_MUTEX_RECURSIVE_NP) - #define PTHREAD_MUTEX_RECURSIVE PTHREAD_MUTEX_RECURSIVE_NP - #endif - #endif -#else - #include - #include - #include - #include - #include - #include - #include - #include - #include - - #if defined (ENABLE_THREADS) - typedef CRITICAL_SECTION port_mutex_t; - #endif - - #define inline - #define snprintf _snprintf - #define vsnprintf _vsnprintf - #define strncasecmp _strnicmp -#endif - - -#if defined (ENABLE_SSL) - #include - #include - #include -#endif - - -#if defined (ENABLE_THREADS) -static inline int libirc_mutex_init (port_mutex_t * mutex) -{ -#if defined (_WIN32) - InitializeCriticalSection (mutex); - return 0; -#elif defined (PTHREAD_MUTEX_RECURSIVE) - pthread_mutexattr_t attr; - - return (pthread_mutexattr_init (&attr) - || pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE) - || pthread_mutex_init (mutex, &attr)); -#else /* !defined (PTHREAD_MUTEX_RECURSIVE) */ - - return pthread_mutex_init (mutex, 0); - -#endif /* defined (_WIN32) */ -} - - -static inline void libirc_mutex_destroy (port_mutex_t * mutex) -{ -#if defined (_WIN32) - DeleteCriticalSection (mutex); -#else - pthread_mutex_destroy (mutex); -#endif -} - - -static inline void libirc_mutex_lock (port_mutex_t * mutex) -{ -#if defined (_WIN32) - EnterCriticalSection (mutex); -#else - pthread_mutex_lock (mutex); -#endif -} - - -static inline void libirc_mutex_unlock (port_mutex_t * mutex) -{ -#if defined (_WIN32) - LeaveCriticalSection (mutex); -#else - pthread_mutex_unlock (mutex); -#endif -} - -#else - - typedef void * port_mutex_t; - - static inline int libirc_mutex_init (port_mutex_t * mutex) { return 0; } - static inline void libirc_mutex_destroy (port_mutex_t * mutex) {} - static inline void libirc_mutex_lock (port_mutex_t * mutex) {} - static inline void libirc_mutex_unlock (port_mutex_t * mutex) {} - -#endif - +#include "./portable.h" /* * Stub for WIN32 dll to initialize winsock API diff --git a/libircclient/src/portable.h b/libircclient/src/portable.h new file mode 100644 index 0000000..f8a62df --- /dev/null +++ b/libircclient/src/portable.h @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2004-2012 George Yunaev gyunaev@ulduzsoft.com + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at your + * option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + */ + +#ifndef INCLUDE_IRC_PORTABLE_H +#define INCLUDE_IRC_PORTABLE_H + +#if !defined (_WIN32) + //#include "config.h" + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + + #if defined (ENABLE_THREADS) + #include + typedef pthread_mutex_t port_mutex_t; + + #if !defined (PTHREAD_MUTEX_RECURSIVE) && defined (PTHREAD_MUTEX_RECURSIVE_NP) + #define PTHREAD_MUTEX_RECURSIVE PTHREAD_MUTEX_RECURSIVE_NP + #endif + #endif +#else + #include + #include + #include + #include + #include + #include + #include + #include + #include + + #if defined (ENABLE_THREADS) + typedef CRITICAL_SECTION port_mutex_t; + #endif + + #define inline + #define snprintf _snprintf + #define vsnprintf _vsnprintf + #define strncasecmp _strnicmp +#endif + + +#if defined (ENABLE_SSL) + #include + #include + #include +#endif + + +#if defined (ENABLE_THREADS) +static inline int libirc_mutex_init (port_mutex_t * mutex) +{ +#if defined (_WIN32) + InitializeCriticalSection (mutex); + return 0; +#elif defined (PTHREAD_MUTEX_RECURSIVE) + pthread_mutexattr_t attr; + + return (pthread_mutexattr_init (&attr) + || pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE) + || pthread_mutex_init (mutex, &attr)); +#else /* !defined (PTHREAD_MUTEX_RECURSIVE) */ + + return pthread_mutex_init (mutex, 0); + +#endif /* defined (_WIN32) */ +} + + +static inline void libirc_mutex_destroy (port_mutex_t * mutex) +{ +#if defined (_WIN32) + DeleteCriticalSection (mutex); +#else + pthread_mutex_destroy (mutex); +#endif +} + + +static inline void libirc_mutex_lock (port_mutex_t * mutex) +{ +#if defined (_WIN32) + EnterCriticalSection (mutex); +#else + pthread_mutex_lock (mutex); +#endif +} + + +static inline void libirc_mutex_unlock (port_mutex_t * mutex) +{ +#if defined (_WIN32) + LeaveCriticalSection (mutex); +#else + pthread_mutex_unlock (mutex); +#endif +} + +#else + + typedef void * port_mutex_t; + + static inline int libirc_mutex_init (port_mutex_t * mutex) { return 0; } + static inline void libirc_mutex_destroy (port_mutex_t * mutex) {} + static inline void libirc_mutex_lock (port_mutex_t * mutex) {} + static inline void libirc_mutex_unlock (port_mutex_t * mutex) {} + +#endif + +#endif /* INCLUDE_IRC_PORTABLE_H */ diff --git a/libircclient/src/session.h b/libircclient/src/session.h index 7e13c8f..d1f830a 100644 --- a/libircclient/src/session.h +++ b/libircclient/src/session.h @@ -17,9 +17,9 @@ #define INCLUDE_IRC_SESSION_H -#include "params.h" -#include "dcc.h" -#include "libirc_events.h" +#include "./params.h" +#include "./dcc.h" +#include "../include/libirc_events.h" // Session flags diff --git a/libircclient/src/sockets.c b/libircclient/src/sockets.h similarity index 97% rename from libircclient/src/sockets.c rename to libircclient/src/sockets.h index 342d18d..5f0a7a5 100644 --- a/libircclient/src/sockets.c +++ b/libircclient/src/sockets.h @@ -12,6 +12,9 @@ * License for more details. */ +#ifndef INCLUDE_IRC_SOCKET_H +#define INCLUDE_IRC_SOCKET_H + /* * The sockets interface was moved out to simplify going OpenSSL integration. */ @@ -159,3 +162,5 @@ static int socket_send (socket_t * sock, const void *buf, size_t len) return length; } + +#endif /* INCLUDE_IRC_SOCKET_H */ diff --git a/libircclient/src/ssl.c b/libircclient/src/ssl.c index 8d6a584..24a5dc8 100644 --- a/libircclient/src/ssl.c +++ b/libircclient/src/ssl.c @@ -1,17 +1,21 @@ -/* +/* * Copyright (C) 2004-2012 George Yunaev gyunaev@ulduzsoft.com * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 3 of the License, or (at your + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at your * option) any later version. * - * This library is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. */ +#include "./ssl.h" + +#include "../include/libircclient.h" +#include "./session.h" #if defined (ENABLE_SSL) @@ -26,22 +30,22 @@ static CRITICAL_SECTION * mutex_buf = 0; // OpenSSL callback to utilize static locks static void cb_openssl_locking_function( int mode, int n, const char * file, int line ) { - if ( mode & CRYPTO_LOCK) - EnterCriticalSection( &mutex_buf[n] ); - else - LeaveCriticalSection( &mutex_buf[n] ); + if ( mode & CRYPTO_LOCK) + EnterCriticalSection( &mutex_buf[n] ); + else + LeaveCriticalSection( &mutex_buf[n] ); } // OpenSSL callback to get the thread ID static unsigned long cb_openssl_id_function(void) { - return ((unsigned long) GetCurrentThreadId() ); + return ((unsigned long) GetCurrentThreadId() ); } static int alloc_mutexes( unsigned int total ) { unsigned int i; - + // Enable thread safety in OpenSSL mutex_buf = (CRITICAL_SECTION*) malloc( total * sizeof(CRITICAL_SECTION) ); @@ -50,7 +54,7 @@ static int alloc_mutexes( unsigned int total ) for ( i = 0; i < total; i++) InitializeCriticalSection( &(mutex_buf[i]) ); - + return 0; } @@ -63,13 +67,13 @@ static pthread_mutex_t * mutex_buf = 0; // OpenSSL callback to utilize static locks static void cb_openssl_locking_function( int mode, int n, const char * file, int line ) { - (void)file; - (void)line; + (void)file; + (void)line; - if ( mode & CRYPTO_LOCK) - pthread_mutex_lock( &mutex_buf[n] ); - else - pthread_mutex_unlock( &mutex_buf[n] ); + if ( mode & CRYPTO_LOCK) + pthread_mutex_lock( &mutex_buf[n] ); + else + pthread_mutex_unlock( &mutex_buf[n] ); } // OpenSSL callback to get the thread ID @@ -82,7 +86,7 @@ static void cb_openssl_id_function( CRYPTO_THREADID * id ) static int alloc_mutexes( unsigned int total ) { unsigned i; - + // Enable thread safety in OpenSSL mutex_buf = (pthread_mutex_t*) malloc( total * sizeof(pthread_mutex_t) ); @@ -91,7 +95,7 @@ static int alloc_mutexes( unsigned int total ) for ( i = 0; i < total; i++) pthread_mutex_init( &(mutex_buf[i]), 0 ); - + return 0; } @@ -115,7 +119,7 @@ static int ssl_init_context( irc_session_t * session ) SSL_library_init(); #else OPENSSL_init_ssl(0, NULL); -#endif +#endif if ( RAND_status() == 0 ) return LIBIRC_ERR_SSL_INIT_FAILED; @@ -139,13 +143,13 @@ static int ssl_init_context( irc_session_t * session ) SSL_CTX_set_verify( ssl_context, SSL_VERIFY_NONE, 0 ); else SSL_CTX_set_verify( ssl_context, SSL_VERIFY_PEER, 0 ); - + // Disable session caching SSL_CTX_set_session_cache_mode( ssl_context, SSL_SESS_CACHE_OFF ); // Enable SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER so we can move the buffer during sending SSL_CTX_set_mode( ssl_context, SSL_CTX_get_mode(ssl_context) | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER | SSL_MODE_ENABLE_PARTIAL_WRITE ); - + return 0; } @@ -162,13 +166,13 @@ static int ssl_init_context( irc_session_t * session ) static int ssl_init( irc_session_t * session ) { static int ssl_context_initialized = 0; - + #if defined (_WIN32) static HANDLE initmutex = 0; - + // First time run? Create the mutex if ( initmutex == 0 ) - { + { HANDLE m = CreateMutex( 0, FALSE, 0 ); // Now we check if the mutex has already been created by another thread performing the init concurrently. @@ -180,28 +184,28 @@ static int ssl_init( irc_session_t * session ) #else static pthread_mutex_t initmutex = PTHREAD_MUTEX_INITIALIZER; #endif - + // This initialization needs to be performed only once. The problem is that it is called from // irc_connect() and this function may be called simultaneously from different threads. So we have - // to use mutex on Linux because it allows static mutex initialization. Windows doesn't, so here + // to use mutex on Linux because it allows static mutex initialization. Windows doesn't, so here // we do the sabre dance around it. SSLINIT_LOCK_MUTEX( initmutex ); if ( ssl_context_initialized == 0 ) { int res = ssl_init_context( session ); - + if ( res ) { SSLINIT_UNLOCK_MUTEX( initmutex ); return res; } - + ssl_context_initialized = 1; } - + SSLINIT_UNLOCK_MUTEX( initmutex ); - + // Get the SSL context session->ssl = SSL_new( ssl_context ); @@ -211,7 +215,7 @@ static int ssl_init( irc_session_t * session ) // Let OpenSSL use our socket if ( SSL_set_fd( session->ssl, session->sock) != 1 ) return LIBIRC_ERR_SSL_INIT_FAILED; - + // Since we're connecting on our own, tell openssl about it SSL_set_connect_state( session->ssl ); @@ -227,7 +231,7 @@ static void ssl_handle_error( irc_session_t * session, int ssl_error ) session->lasterror = LIBIRC_ERR_SSL_CERT_VERIFY_FAILED; return; } - + if ( ERR_GET_REASON(ssl_error) == SSL_R_UNKNOWN_PROTOCOL ) { session->lasterror = LIBIRC_ERR_CONNECT_SSL_FAILED; @@ -237,7 +241,7 @@ static void ssl_handle_error( irc_session_t * session, int ssl_error ) #if defined (ENABLE_DEBUG) if ( IS_DEBUG_ENABLED(session) ) - fprintf (stderr, "[DEBUG] SSL error: %s\n\t(%d, %d)\n", + fprintf (stderr, "[DEBUG] SSL error: %s\n\t(%d, %d)\n", ERR_error_string( ssl_error, NULL), ERR_GET_LIB( ssl_error), ERR_GET_REASON(ssl_error) ); #endif } @@ -246,42 +250,42 @@ static int ssl_recv( irc_session_t * session ) { int count; unsigned int amount = (sizeof (session->incoming_buf) - 1) - session->incoming_offset; - + ERR_clear_error(); // Read up to m_bufferLength bytes count = SSL_read( session->ssl, session->incoming_buf + session->incoming_offset, amount ); - if ( count > 0 ) + if ( count > 0 ) return count; else if ( count == 0 ) return -1; // remote connection closed else { int ssl_error = SSL_get_error( session->ssl, count ); - + // Handle SSL error since not all of them are actually errors - switch ( ssl_error ) - { - case SSL_ERROR_WANT_READ: - // This is not really an error. We received something, but - // OpenSSL gave nothing to us because all it read was - // internal data. Repeat the same read. + switch ( ssl_error ) + { + case SSL_ERROR_WANT_READ: + // This is not really an error. We received something, but + // OpenSSL gave nothing to us because all it read was + // internal data. Repeat the same read. return 0; - case SSL_ERROR_WANT_WRITE: - // This is not really an error. We received something, but - // now OpenSSL needs to send the data before returning any - // data to us (like negotiations). This means we'd need - // to wait for WRITE event, but call SSL_read() again. - session->flags |= SESSIONFL_SSL_READ_WANTS_WRITE; + case SSL_ERROR_WANT_WRITE: + // This is not really an error. We received something, but + // now OpenSSL needs to send the data before returning any + // data to us (like negotiations). This means we'd need + // to wait for WRITE event, but call SSL_read() again. + session->flags |= SESSIONFL_SSL_READ_WANTS_WRITE; return 0; } // This is an SSL error, handle it - ssl_handle_error( session, ERR_get_error() ); + ssl_handle_error( session, ERR_get_error() ); } - + return -1; } @@ -289,37 +293,37 @@ static int ssl_recv( irc_session_t * session ) static int ssl_send( irc_session_t * session ) { int count; - ERR_clear_error(); + ERR_clear_error(); count = SSL_write( session->ssl, session->outgoing_buf, session->outgoing_offset ); - if ( count > 0 ) + if ( count > 0 ) return count; - else if ( count == 0 ) + else if ( count == 0 ) return -1; - else - { + else + { int ssl_error = SSL_get_error( session->ssl, count ); - - switch ( ssl_error ) - { - case SSL_ERROR_WANT_READ: - // This is not really an error. We sent some internal OpenSSL data, - // but now it needs to read more data before it can send anything. - // Thus we wait for READ event, but will call SSL_write() again. - session->flags |= SESSIONFL_SSL_WRITE_WANTS_READ; + + switch ( ssl_error ) + { + case SSL_ERROR_WANT_READ: + // This is not really an error. We sent some internal OpenSSL data, + // but now it needs to read more data before it can send anything. + // Thus we wait for READ event, but will call SSL_write() again. + session->flags |= SESSIONFL_SSL_WRITE_WANTS_READ; return 0; - case SSL_ERROR_WANT_WRITE: - // This is not really an error. We sent some data, but now OpenSSL - // wants to send some internal data before sending ours. - // Repeat the same write. + case SSL_ERROR_WANT_WRITE: + // This is not really an error. We sent some data, but now OpenSSL + // wants to send some internal data before sending ours. + // Repeat the same write. return 0; - } - + } + // This is an SSL error, handle it - ssl_handle_error( session, ERR_get_error() ); - } + ssl_handle_error( session, ERR_get_error() ); + } return -1; } @@ -331,7 +335,7 @@ static int ssl_send( irc_session_t * session ) // Returns -1 in case there is an error and socket should be closed/connection terminated // Returns 0 in case there is a temporary error and the call should be retried (SSL_WANTS_WRITE case) // Returns a positive number if we actually read something -static int session_socket_read( irc_session_t * session ) +int session_socket_read( irc_session_t * session ) { int length; @@ -345,19 +349,19 @@ static int session_socket_read( irc_session_t * session ) ssl_send( session ); return 0; } - + return ssl_recv( session ); } #endif - - length = socket_recv( &session->sock, - session->incoming_buf + session->incoming_offset, - (sizeof (session->incoming_buf) - 1) - session->incoming_offset ); - + + length = socket_recv( &session->sock, + session->incoming_buf + session->incoming_offset, + (sizeof (session->incoming_buf) - 1) - session->incoming_offset ); + // There is no "retry" errors for regular sockets if ( length <= 0 ) return -1; - + return length; } @@ -365,7 +369,7 @@ static int session_socket_read( irc_session_t * session ) // Returns -1 in case there is an error and socket should be closed/connection terminated // Returns 0 in case there is a temporary error and the call should be retried (SSL_WANTS_WRITE case) // Returns a positive number if we actually sent something -static int session_socket_write( irc_session_t * session ) +int session_socket_write( irc_session_t * session ) { int length; @@ -379,16 +383,16 @@ static int session_socket_write( irc_session_t * session ) ssl_recv( session ); return 0; } - + return ssl_send( session ); } #endif - + length = socket_send (&session->sock, session->outgoing_buf, session->outgoing_offset); - + // There is no "retry" errors for regular sockets if ( length <= 0 ) return -1; - + return length; } diff --git a/libircclient/src/ssl.h b/libircclient/src/ssl.h new file mode 100644 index 0000000..4fa6ff2 --- /dev/null +++ b/libircclient/src/ssl.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2004-2012 George Yunaev gyunaev@ulduzsoft.com + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at your + * option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + */ + +#include "./session.h" + +#ifndef INCLUDE_IRC_SSL_H +#define INCLUDE_IRC_SSL_H + +int session_socket_read( irc_session_t * session ); +int session_socket_write( irc_session_t * session ); + +#endif /* INCLUDE_IRC_SSL_H */ diff --git a/libircclient/src/utils.c b/libircclient/src/utils.h similarity index 88% rename from libircclient/src/utils.c rename to libircclient/src/utils.h index 9305b91..7c01d83 100644 --- a/libircclient/src/utils.c +++ b/libircclient/src/utils.h @@ -1,17 +1,28 @@ -/* +/* * Copyright (C) 2004-2012 George Yunaev gyunaev@ulduzsoft.com * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 3 of the License, or (at your + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at your * option) any later version. * - * This library is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. */ +#ifndef INCLUDE_IRC_UTILS_H +#define INCLUDE_IRC_UTILS_H + +//#include + +#include +#include +#include + +#include "./session.h" + static void libirc_add_to_set (int fd, fd_set *set, int * maxfd) { FD_SET (fd, set); @@ -62,13 +73,13 @@ static int libirc_findcrlf_offset(const char *buf, int offset, const int length) static int libirc_findcrorlf (char * buf, int length) { int offset = 0; - for ( ; offset < length; offset++ ) + for ( ; offset < length; offset++ ) { if ( buf[offset] == 0x0D || buf[offset] == 0x0A ) { buf[offset++] = '\0'; - if ( offset < (length - 1) + if ( offset < (length - 1) && (buf[offset] == 0x0D || buf[offset] == 0x0A) ) offset++; @@ -108,7 +119,7 @@ static void libirc_event_ctcp_internal (irc_session_t * session, const char * ev } else if ( !strcmp (params[0], "FINGER") ) { - sprintf (textbuf, "FINGER %s (%s) Idle 0 seconds", + sprintf (textbuf, "FINGER %s (%s) Idle 0 seconds", session->username ? session->username : "nobody", session->realname ? session->realname : "noname"); @@ -128,3 +139,5 @@ static void libirc_event_ctcp_internal (irc_session_t * session, const char * ev } } } + +#endif /* INCLUDE_IRC_UTILS_H */