-int socket_loop(int timeout_seconds) {
- if(sockets == NULL) return 0;
- int is_synchronized = 1;
- SYNCHRONIZE(synchronized_recv);
- fd_set fds;
- struct timeval timeout;
- struct ClientSocket *sock, *next;
- int ret = 0, bytes, i;
-
- FD_ZERO(&fds);
- for (sock = sockets->data; sock; sock = sock->next) {
- if(!(sock->flags & SOCKET_FLAG_CONNECTED)) continue; //skip disconnected sockets
- FD_SET(sock->sock, &fds);
- if(sock->sock > ret)
- ret = sock->sock;
- }
- timeout.tv_sec = timeout_seconds;
- timeout.tv_usec = 0;
- ret = select(ret + 1, &fds, NULL, NULL, &timeout);
- if(ret == 0) {
- DESYNCHRONIZE(synchronized_recv);
- return 1;
- }
- for (sock = sockets->data; sock; sock = next) {
- next = sock->next;
- if((sock->flags & (SOCKET_FLAG_CONNECTED | SOCKET_FLAG_QUITTED)) == SOCKET_FLAG_CONNECTED && FD_ISSET(sock->sock, &fds)) {
- if(sock->bufferpos != 0) {
- if(!(sock->flags & SOCKET_FLAG_HAVE_SSL) || (bytes = ssl_read(sock, buffer, sizeof(buffer))) == -2) {
- #ifdef WIN32
- bytes = recv(sock->sock, buffer, sizeof(buffer), 0);
- #else
- bytes = read(sock->sock, buffer, sizeof(buffer));
- #endif
- }
- if(bytes > 0) {
- for(i = 0; i < bytes; i++) {
- if(sock->bufferpos + i == BUF_SIZ*2) break; //buffer overflow
- sock->buffer[sock->bufferpos + i] = buffer[i];
- }
- sock->bufferpos += i;
- }
- } else {
- if(!(sock->flags & SOCKET_FLAG_HAVE_SSL) || (bytes = ssl_read(sock, sock->buffer, sizeof(sock->buffer))) == -2) {
- #ifdef WIN32
- bytes = recv(sock->sock, sock->buffer, sizeof(sock->buffer), 0);
- #else
- bytes = read(sock->sock, sock->buffer, sizeof(sock->buffer));
- #endif
- }
- if(bytes > 0)
- sock->bufferpos = bytes;
- }
- if(bytes <= 0) {
- //error
- sock->flags |= SOCKET_FLAG_QUITTED;
- } else {
- sock->traffic_in += bytes;
- #ifdef HAVE_THREADS
- char linesbuf[BUF_SIZ*2];
- strcpy(linesbuf, sock->buffer);
- int used = 0;
- for(i = 0; i < sock->bufferpos; i++) {
- if(sock->buffer[i] == '\n') {
- used = i+1;
- }
- }
- if(used == sock->bufferpos + 1) {
- //used all bytes so just reset the bufferpos
- sock->bufferpos = 0;
- } else {
- for(i = 0; i < sock->bufferpos - used; i++) {
- sock->buffer[i] = sock->buffer[i+used];
- }
- sock->bufferpos -= used;
- }
- is_synchronized = 0;
- unsigned int tid = (unsigned int) pthread_self_tid();
- clientsocket_start_of_recv(tid);
- DESYNCHRONIZE(synchronized_recv);
- parse_lines(sock, linesbuf, used);
- clientsocket_end_of_recv(tid);
- #else
- int used = parse_lines(sock, sock->buffer, sock->bufferpos);
- if(used == sock->bufferpos + 1) {
- //used all bytes so just reset the bufferpos
- sock->bufferpos = 0;
- } else {
- for(i = 0; i < sock->bufferpos - used; i++) {
- sock->buffer[i] = sock->buffer[i+used];
- }
- sock->bufferpos -= used;
- }
- is_synchronized = 0;
- DESYNCHRONIZE(synchronized_recv);
- #endif
- #ifdef HAVE_THREADS
- FD_ZERO(&fds); //zero out all other pending sockets here (we have other threads receiving from them)
- #endif
- }
- } else if((sock->flags & (SOCKET_FLAG_CONNECTED | SOCKET_FLAG_RECONNECT)) == SOCKET_FLAG_RECONNECT) {
- if(time(0) - sock->connection_time >= SOCKET_RECONNECT_TIME) {
- connect_socket(sock);
- }
- }
- if((sock->flags & SOCKET_FLAG_QUITTED)) {
- sock->flags &= ~SOCKET_FLAG_QUITTED;
- destroy_socket(sock, (sock->flags & SOCKET_FLAG_DEAD));
+static IOHANDLER_CALLBACK(socket_callback) {
+ struct ClientSocket *client = event->iofd->data;
+ #ifdef HAVE_THREADS
+ unsigned int tid;
+ #endif
+ if(process_state.running == 0)
+ return; //just ignore the event (shutdown sequence)
+ switch(event->type) {
+ case IOEVENT_CONNECTED:
+ client->flags |= SOCKET_FLAG_CONNECTED;
+ if(client->pass && strcmp(client->pass, ""))
+ putsock(client, "PASS :%s", client->pass);
+ putsock(client, "USER %s 0 0 :%s", client->ident, client->realname);
+ putsock(client, "NICK %s", client->nick);
+ break;
+ case IOEVENT_NOTCONNECTED:
+ case IOEVENT_CLOSED:
+ _close_socket(client);
+ if(client->flags & SOCKET_FLAG_RECONNECT) {
+ struct timeval timeout;
+ gettimeofday(&timeout, NULL);
+ timeout.tv_sec += SOCKET_RECONNECT_TIME;
+ client->iofd = iohandler_timer(timeout, socket_callback);
+ client->iofd->data = client;