Permalink
Browse files

Asynchronous connect(), fixes, and liveness (unfinished)

  • Loading branch information...
1 parent e5964ee commit 5bd9397a22b2fea829de14bf9ba49e4190104664 Sound and Fury committed Sep 1, 2010
Showing with 160 additions and 119 deletions.
  1. +38 −31 buffer.c
  2. +1 −0 buffer.h
  3. +37 −13 irc.c
  4. +3 −1 irc.h
  5. +81 −74 quirc.c
View
@@ -16,9 +16,7 @@ int initialise_buffers(int buflines, char *nick)
init_buffer(0, STATUS, "status", buflines); // buf 0 is always STATUS
nbufs=1;
cbuf=0;
- bufs[0].nick=strdup(nick);
- if(!bufs[0].nick)
- return(1);
+ bufs[0].live=true; // STATUS is never dead
buf_print(0, c_status, GPL_MSG); // can't w_buf_print() it because it has embedded newlines
return(0);
}
@@ -45,47 +43,56 @@ int init_buffer(int buf, btype type, char *bname, int nlines)
bufs[buf].filled=false;
bufs[buf].alert=false;
bufs[buf].namreply=false;
+ bufs[buf].live=false;
return(0);
}
int free_buffer(int buf)
{
- free(bufs[buf].bname);
- name *curr=bufs[buf].nlist;
- while(curr)
- {
- name *next=curr->next;
- free(curr->data);
- free(curr);
- curr=next;
- }
- bufs[buf].nlist=NULL;
- free(bufs[buf].lc);
- int l;
- for(l=0;l<bufs[buf].nlines;l++)
- free(bufs[buf].lt[l]);
- free(bufs[buf].lt);
- free(bufs[buf].ts);
- if(cbuf>=buf)
- cbuf--;
- nbufs--;
- int b;
- for(b=buf;b<nbufs;b++)
+ if(bufs[buf].live)
{
- bufs[b]=bufs[b+1];
+ w_buf_print(b, c_err, "Buffer is still live!", "free_buffer:");
+ return(1);
}
- for(b=0;b<nbufs;b++)
+ else
{
- if(bufs[b].server==buf)
+ free(bufs[buf].bname);
+ name *curr=bufs[buf].nlist;
+ while(curr)
+ {
+ name *next=curr->next;
+ free(curr->data);
+ free(curr);
+ curr=next;
+ }
+ bufs[buf].nlist=NULL;
+ free(bufs[buf].lc);
+ int l;
+ for(l=0;l<bufs[buf].nlines;l++)
+ free(bufs[buf].lt[l]);
+ free(bufs[buf].lt);
+ free(bufs[buf].ts);
+ if(cbuf>=buf)
+ cbuf--;
+ nbufs--;
+ int b;
+ for(b=buf;b<nbufs;b++)
{
- bufs[b].server=0; // orphaned; should not happen
+ bufs[b]=bufs[b+1];
}
- else if(bufs[b].server>buf)
+ for(b=0;b<nbufs;b++)
{
- bufs[b].server--;
+ if(bufs[b].server==buf)
+ {
+ bufs[b].server=0; // orphaned; should not happen
+ }
+ else if(bufs[b].server>buf)
+ {
+ bufs[b].server--;
+ }
}
+ return(0);
}
- return(0);
}
int add_to_buffer(int buf, colour lc, char *lt)
View
@@ -48,6 +48,7 @@ typedef struct _buf
bool filled; // buffer has filled up and looped? (the buffers are circular in nature)
bool alert; // tab has new messages?
bool namreply; // tab is in the middle of reading a list of NAMES replies (RPL_NAMREPLY)?
+ bool live; // tab is connected? when checking in a CHANNEL, remember to AND it with the parent's live
}
buffer;
View
@@ -8,7 +8,7 @@
#include "irc.h"
-int irc_connect(char *server, char *portno, char *nick, char *username, char *fullname, fd_set *master, int *fdmax)
+int irc_connect(char *server, char *portno, fd_set *master, int *fdmax)
{
int serverhandle;
struct addrinfo hints, *servinfo;
@@ -19,7 +19,7 @@ int irc_connect(char *server, char *portno, char *nick, char *username, char *fu
int rv;
if((rv = getaddrinfo(server, portno, &hints, &servinfo)) != 0)
{
- fprintf(stderr, "getaddrinfo: %s\n\n", gai_strerror(rv));
+ w_buf_print(0, c_err, gai_strerror(rv), "getaddrinfo: ");
return(0); // 0 indicates failure as rv is new serverhandle value
}
char sip[INET_ADDRSTRLEN];
@@ -30,38 +30,50 @@ int irc_connect(char *server, char *portno, char *nick, char *username, char *fu
inet_ntop(p->ai_family, &(((struct sockaddr_in*)p->ai_addr)->sin_addr), sip, sizeof(sip));
if((serverhandle = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1)
{
- perror("socket");
- fprintf(stderr, "\n");
+ w_buf_print(0, c_err, strerror(errno), "socket: ");
continue;
}
- if(connect(serverhandle, p->ai_addr, p->ai_addrlen) == -1)
+ if(fcntl(serverhandle, F_SETFD, O_NONBLOCK) == -1)
{
close(serverhandle);
- perror("connect");
- fprintf(stderr, "\n");
+ w_buf_print(0, c_err, strerror(errno), "fcntl: ");
continue;
}
+ if(connect(serverhandle, p->ai_addr, p->ai_addrlen) == -1)
+ {
+ if(errno!=EINPROGRESS)
+ {
+ close(serverhandle);
+ w_buf_print(0, c_err, strerror(errno), "connect: ");
+ continue;
+ }
+ }
break;
}
if (p == NULL)
{
- fprintf(stderr, "failed to connect\n\n");
+ w_buf_print(0, c_err, "failed to connect to server", "/connect: ");
return(0); // 0 indicates failure as rv is new serverhandle value
}
freeaddrinfo(servinfo); // don't need this any more
FD_SET(serverhandle, master);
*fdmax=max(*fdmax, serverhandle);
-
+ return(serverhandle)
+}
+
+int irc_conn_rest(int b, char *nick, char *username, char *fullname)
+{
+ bufs[b].live==true; // mark it as live
char nickmsg[6+strlen(nick)];
sprintf(nickmsg, "NICK %s", nick);
- irc_tx(serverhandle, nickmsg);
+ irc_tx(bufs[b].handle, nickmsg);
struct utsname arch;
uname(&arch);
char usermsg[12+strlen(username)+strlen(arch.nodename)+strlen(fullname)];
sprintf(usermsg, "USER %s %s %s :%s", username, arch.nodename, arch.nodename, fullname);
- irc_tx(serverhandle, usermsg);
- return(serverhandle);
+ irc_tx(bufs[b].handle, usermsg);
+ return(0);
}
int autoconnect(fd_set *master, int *fdmax)
@@ -86,7 +98,7 @@ int autoconnect(fd_set *master, int *fdmax)
bufs[cbuf].nick=strdup(nick);
bufs[cbuf].server=1;
add_to_buffer(1, c_status, cstr);
- sprintf(cstr, "quIRC - connected to %s", server);
+ sprintf(cstr, "quIRC - connecting to %s", server);
settitle(cstr);
}
return(serverhandle);
@@ -128,6 +140,18 @@ int irc_rx(int fd, char ** data)
}
l++;
}
+ else if(bytes<0)
+ {
+ int b;
+ for(b=0;b<nbufs;b++)
+ {
+ if((fd==bufs[b].handle) && (bufs[b].type==SERVER))
+ {
+ w_buf_print(b, c_err, strerror(errno), "irc_rx: recv:");
+ bufs[b].live=false;
+ }
+ }
+ }
}
*data=low_dequote(buf);
if(!*data)
View
@@ -18,6 +18,7 @@
#include <netdb.h>
#include <arpa/inet.h>
#include <netinet/in.h>
+#include <errno.h>
#include "bits.h"
#include "buffer.h"
@@ -27,7 +28,8 @@
#define MQUOTE '\020'
-int irc_connect(char *server, char *portno, char *nick, char *username, char *fullname, fd_set *master, int *fdmax);
+int irc_connect(char *server, char *portno, fd_set *master, int *fdmax); // non-blocking
+int irc_conn_rest(int b, char *nick, char *username, char *fullname); // call this when the non-blocking connect() has finished
int autoconnect(fd_set *master, int *fdmax);
int irc_tx(int fd, char * packet);
int irc_rx(int fd, char ** data);
View
@@ -116,85 +116,92 @@ int main(int argc, char *argv[])
{
if((fd==bufs[b].handle) && (bufs[b].type==SERVER))
{
- char *packet;
- int e;
- if((e=irc_rx(fd, &packet))!=0)
+ if(bufs[b].live)
{
- char emsg[64];
- sprintf(emsg, "error: irc_rx(%d, &%p): %d", fd, packet, e);
- cbuf=0;
- redraw_buffer();
- w_buf_print(0, c_err, emsg, "");
- state=5;
- qmsg="client crashed";
- }
- else if(packet)
- {
- char *pdata=strdup(packet);
- if(packet[0])
+ char *packet;
+ int e;
+ if((e=irc_rx(fd, &packet))!=0)
{
- char *p=packet;
- if(*p==':')
- {
- p=strchr(p, ' ');
- }
- char *cmd=strtok(p, " ");
- if(*packet==':') *p=0;
- if(isdigit(*cmd))
- {
- irc_numeric(cmd, b);
- }
- else if(strcmp(cmd, "PING")==0)
- {
- rx_ping(fd);
- }
- else if(strcmp(cmd, "MODE")==0)
- {
- rx_mode(&join, b);
- }
- else if(strcmp(cmd, "KILL")==0)
- {
- rx_kill(b, &master);
- }
- else if(strcmp(cmd, "ERROR")==0)
- {
- rx_error(b, &master);
- }
- else if(strcmp(cmd, "PRIVMSG")==0)
- {
- rx_privmsg(b, packet, pdata);
- }
- else if(strcmp(cmd, "NOTICE")==0)
- {
- rx_notice(b, packet);
- }
- else if(strcmp(cmd, "TOPIC")==0)
- {
- rx_topic(b, packet);
- }
- else if(strcmp(cmd, "JOIN")==0)
- {
- rx_join(b, packet, pdata, &join);
- }
- else if(strcmp(cmd, "PART")==0)
- {
- rx_part(b, packet, pdata);
- }
- else if(strcmp(cmd, "QUIT")==0)
- {
- rx_quit(b, packet, pdata);
- }
- else if(strcmp(cmd, "NICK")==0)
- {
- rx_nick(b, packet, pdata);
- }
- else
+ char emsg[64];
+ sprintf(emsg, "error: irc_rx(%d, &%p): %d", fd, packet, e);
+ cbuf=0;
+ redraw_buffer();
+ w_buf_print(0, c_err, emsg, "");
+ state=5;
+ qmsg="client crashed";
+ }
+ else if(packet)
+ {
+ char *pdata=strdup(packet);
+ if(packet[0])
{
- w_buf_print(b, c_unk, pdata, "<? ");
+ char *p=packet;
+ if(*p==':')
+ {
+ p=strchr(p, ' ');
+ }
+ char *cmd=strtok(p, " ");
+ if(*packet==':') *p=0;
+ if(isdigit(*cmd))
+ {
+ irc_numeric(cmd, b);
+ }
+ else if(strcmp(cmd, "PING")==0)
+ {
+ rx_ping(fd);
+ }
+ else if(strcmp(cmd, "MODE")==0)
+ {
+ rx_mode(&join, b);
+ }
+ else if(strcmp(cmd, "KILL")==0)
+ {
+ rx_kill(b, &master);
+ }
+ else if(strcmp(cmd, "ERROR")==0)
+ {
+ rx_error(b, &master);
+ }
+ else if(strcmp(cmd, "PRIVMSG")==0)
+ {
+ rx_privmsg(b, packet, pdata);
+ }
+ else if(strcmp(cmd, "NOTICE")==0)
+ {
+ rx_notice(b, packet);
+ }
+ else if(strcmp(cmd, "TOPIC")==0)
+ {
+ rx_topic(b, packet);
+ }
+ else if(strcmp(cmd, "JOIN")==0)
+ {
+ rx_join(b, packet, pdata, &join);
+ }
+ else if(strcmp(cmd, "PART")==0)
+ {
+ rx_part(b, packet, pdata);
+ }
+ else if(strcmp(cmd, "QUIT")==0)
+ {
+ rx_quit(b, packet, pdata);
+ }
+ else if(strcmp(cmd, "NICK")==0)
+ {
+ rx_nick(b, packet, pdata);
+ }
+ else
+ {
+ w_buf_print(b, c_unk, pdata, "<? ");
+ }
}
+ free(pdata);
+ free(packet);
}
- free(pdata);
- free(packet);
+ }
+ else
+ {
+ irc_conn_rest(b, nick, username, fullname);
}
in_update(inp);
b=nbufs+1;

0 comments on commit 5bd9397

Please sign in to comment.