tHTTP authentication tidied up; better error reporting for socket() and bind() failures - vaccinewars - be a doctor and try to vaccinate the world
 (HTM) git clone git://src.adamsgaard.dk/vaccinewars
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 62523aa3d60bd5a9ea19f35c4af2f8ce36b03f9d
 (DIR) parent d575d43a2095a190ad01076332009a6b08071aa7
 (HTM) Author: Ben Webb <ben@salilab.org>
       Date:   Fri, 12 Oct 2001 16:40:35 +0000
       
       HTTP authentication tidied up; better error reporting for socket() and bind() failures
       
       
       Diffstat:
         M src/gtk_client.c                    |      41 ++++++++++++-------------------
         M src/network.c                       |      94 +++++++++++++++++++++++++------
         M src/network.h                       |       2 ++
       
       3 files changed, 95 insertions(+), 42 deletions(-)
       ---
 (DIR) diff --git a/src/gtk_client.c b/src/gtk_client.c
       t@@ -2057,6 +2057,9 @@ static void HandleMetaSock(gpointer data,gint socket,
           NBStatus oldstatus,newstatus;
           gchar *text;
        
       +g_print("HandleMetaSock: read %d, write %d\n",
       +        condition&GDK_INPUT_READ,
       +        condition&GDK_INPUT_WRITE);
           widgets=(struct StartGameStruct *)data;
           if (!widgets->MetaConn) return;
        
       t@@ -3127,11 +3130,17 @@ void DisplaySpyReports(Player *Play) {
        }
        
        static void OKAuthDialog(GtkWidget *widget,GtkWidget *window) {
       +   gtk_object_set_data(GTK_OBJECT(window),"authok",GINT_TO_POINTER(TRUE));
       +   gtk_widget_destroy(window);
       +}
       +
       +static void DestroyAuthDialog(GtkWidget *window,gpointer data) {
           GtkWidget *userentry,*passwdentry;
       -   gchar *username,*password;
       -   gpointer proxy;
       +   gchar *username=NULL,*password=NULL;
       +   gpointer proxy,authok;
           HttpConnection *conn;
        
       +   authok = gtk_object_get_data(GTK_OBJECT(window),"authok");
           proxy = gtk_object_get_data(GTK_OBJECT(window),"proxy");
           userentry = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(window),"username");
           passwdentry = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(window),
       t@@ -3139,34 +3148,16 @@ static void OKAuthDialog(GtkWidget *widget,GtkWidget *window) {
           conn = (HttpConnection *)gtk_object_get_data(GTK_OBJECT(window),"httpconn");
           g_assert(userentry && passwdentry && conn);
        
       -   username = gtk_editable_get_chars(GTK_EDITABLE(userentry),0,-1);
       -   password = gtk_editable_get_chars(GTK_EDITABLE(passwdentry),0,-1);
       -
       -   gtk_object_set_data(GTK_OBJECT(window),"authdone",GINT_TO_POINTER(TRUE));
       +   if (authok) {
       +     username = gtk_editable_get_chars(GTK_EDITABLE(userentry),0,-1);
       +     password = gtk_editable_get_chars(GTK_EDITABLE(passwdentry),0,-1);
       +   }
        
           if (!SetHttpAuthentication(conn,GPOINTER_TO_INT(proxy),username,password)) {
              g_print("FIXME: Connect error on setauth\n");
           }
       -   g_free(username); g_free(password);
       -
       -   gtk_widget_destroy(window);
       -}
       -
       -void DestroyAuthDialog(GtkWidget *widget,gpointer data) {
       -   HttpConnection *conn;
       -   gpointer authdone,proxy;
       -
       -   authdone = gtk_object_get_data(GTK_OBJECT(widget),"authdone");
       -   conn = (HttpConnection *)gtk_object_get_data(GTK_OBJECT(widget),"httpconn");
       -   proxy = gtk_object_get_data(GTK_OBJECT(widget),"proxy");
        
       -   if (authdone) {
       -      g_print("Auth already done, thanks\n");
       -   } else {
       -      if (!SetHttpAuthentication(conn,GPOINTER_TO_INT(proxy),NULL,NULL)) {
       -         g_print("FIXME: Connect error on unsetauth\n");
       -      }
       -   }
       +   g_free(username); g_free(password);
        }
        
        void AuthDialog(HttpConnection *conn,gboolean proxy,gchar *realm) {
 (DIR) diff --git a/src/network.c b/src/network.c
       t@@ -119,6 +119,14 @@ static gboolean FinishConnect(int fd,LastError *error);
        
        static void NetBufCallBack(NetworkBuffer *NetBuf) {
           if (NetBuf && NetBuf->CallBack) {
       +g_print("status = %d, read = %d, write = %d\n",
       +NetBuf->status,
       +NetBuf->status!=NBS_PRECONNECT,
       +                          (NetBuf->status==NBS_CONNECTED &&
       +                           NetBuf->WriteBuf.DataPresent) ||
       +                          (NetBuf->status==NBS_SOCKSCONNECT &&
       +                           NetBuf->negbuf.DataPresent) ||
       +                          NetBuf->WaitConnect);
              (*NetBuf->CallBack)(NetBuf,NetBuf->status!=NBS_PRECONNECT,
                                  (NetBuf->status==NBS_CONNECTED &&
                                   NetBuf->WriteBuf.DataPresent) ||
       t@@ -710,6 +718,7 @@ gboolean ReadDataFromWire(NetworkBuffer *NetBuf) {
                 return FALSE;
              } else {
                 CurrentPosition+=BytesRead;
       +g_print("%d bytes read from wire\n",BytesRead);
                 conn->DataPresent=CurrentPosition;
              }
           }
       t@@ -897,6 +906,7 @@ static gboolean WriteBufToWire(NetworkBuffer *NetBuf,ConnBuf *conn) {
                 }
        #endif
              } else {
       +g_print("%d bytes written to wire\n",BytesSent);
                 CurrentPosition+=BytesSent;
              }
           }
       t@@ -913,8 +923,10 @@ gboolean WriteDataToWire(NetworkBuffer *NetBuf) {
        /* TRUE on success, or FALSE if the buffer's maximum length is        */
        /* reached, or the remote end has closed the connection.              */
           if (NetBuf->status==NBS_SOCKSCONNECT) {
       +g_print("Writing negbuf\n");
              return WriteBufToWire(NetBuf,&NetBuf->negbuf);
           } else {
       +g_print("Writing WriteBuf\n");
              return WriteBufToWire(NetBuf,&NetBuf->WriteBuf);
           }
        }
       t@@ -1090,6 +1102,25 @@ static gboolean ParseHtmlLocation(gchar *uri,gchar **host,unsigned *port,
          return TRUE;
        }
        
       +static void StartHttpAuth(HttpConnection *conn,gboolean proxy,gchar *header) {
       +   gchar *realm,**split;
       +
       +   if (!conn->authfunc) return;
       +
       +   split=g_strsplit(header," ",1);
       +
       +   if (split[0] && split[1] && g_strcasecmp(split[0],"Basic")==0 &&
       +       g_strncasecmp(split[1],"realm=",6)==0 && strlen(split[1])>6) {
       +     realm = &split[1][6];
       +     conn->waitinput=TRUE;
       +     (*conn->authfunc)(conn,proxy,realm);
       +   } else {
       +     g_print("FIXME: Bad HTTP auth header\n");
       +   }
       +
       +   g_strfreev(split);
       +}
       +
        static void ParseHtmlHeader(gchar *line,HttpConnection *conn) {
          gchar **split,*host,*query;
          unsigned port;
       t@@ -1109,19 +1140,13 @@ static void ParseHtmlHeader(gchar *line,HttpConnection *conn) {
            } else if (g_strcasecmp(split[0],"WWW-Authenticate:")==0 &&
                       conn->StatusCode==401) {
              g_print("FIXME: Authentication %s required\n",split[1]);
       -      if (conn->authfunc) {
       -         conn->waitinput=TRUE;
       -         (*conn->authfunc)(conn,FALSE,split[1]);
       -      }
       +      StartHttpAuth(conn,FALSE,split[1]);
        /* Proxy-Authenticate is, strictly speaking, an HTTP/1.1 thing, but some
           HTTP/1.0 proxies seem to support it anyway */
            } else if (g_strcasecmp(split[0],"Proxy-Authenticate:")==0 &&
                       conn->StatusCode==407) {
              g_print("FIXME: Proxy authentication %s required\n",split[1]);
       -      if (conn->authfunc) {
       -         conn->waitinput=TRUE;
       -         (*conn->authfunc)(conn,TRUE,split[1]);
       -      }
       +      StartHttpAuth(conn,TRUE,split[1]);
            }
          }
          g_strfreev(split);
       t@@ -1204,10 +1229,52 @@ gboolean HandleHttpCompletion(HttpConnection *conn) {
                 SetNetworkBufferUserPasswdFunc(&conn->NetBuf,userpasswd);
                 return FALSE;
              }
       +   } else {
       +      if (conn->StatusCode>=300) {
       +        g_print("FIXME: Connection failed, code %d\n",conn->StatusCode);
       +      }
           }
           return TRUE;
        }
        
       +int CreateTCPSocket(LastError *error) {
       +  int fd;
       +
       +  fd=socket(AF_INET,SOCK_STREAM,0);
       +
       +  if (fd==SOCKET_ERROR && error) {
       +#ifdef CYGWIN
       +    SetError(error,ET_WINSOCK,WSAGetLastError());
       +#else
       +    SetError(error,ET_ERRNO,errno);
       +#endif
       +  }
       +
       +  return fd;
       +}
       +  
       +gboolean BindTCPSocket(int sock,unsigned port,LastError *error) {
       +  struct sockaddr_in bindaddr;
       +  int retval;
       +
       +  bindaddr.sin_family=AF_INET;
       +  bindaddr.sin_port=htons(port);
       +  bindaddr.sin_addr.s_addr=INADDR_ANY;
       +  memset(bindaddr.sin_zero,0,sizeof(bindaddr.sin_zero));
       +
       +  retval = bind(sock,(struct sockaddr *)&bindaddr,sizeof(struct sockaddr));
       +
       +  if (retval==SOCKET_ERROR && error) {
       +#ifdef CYGWIN
       +    SetError(error,ET_WINSOCK,WSAGetLastError());
       +#else
       +    SetError(error,ET_ERRNO,errno);
       +#endif
       +  }
       +
       +  return (retval!=SOCKET_ERROR);
       +}
       +
        gboolean StartConnect(int *fd,gchar *RemoteHost,unsigned RemotePort,
                              gboolean NonBlocking,LastError *error) {
           struct sockaddr_in ClientAddr;
       t@@ -1216,15 +1283,8 @@ gboolean StartConnect(int *fd,gchar *RemoteHost,unsigned RemotePort,
           he = LookupHostname(RemoteHost,error);
           if (!he) return FALSE;
        
       -   *fd=socket(AF_INET,SOCK_STREAM,0);
       -   if (*fd==SOCKET_ERROR) {
       -#ifdef CYGWIN
       -      if (error) SetError(error,ET_WINSOCK,WSAGetLastError());
       -#else
       -      if (error) SetError(error,ET_ERRNO,errno);
       -#endif
       -      return FALSE;
       -   }
       +   *fd=CreateTCPSocket(error);
       +   if (*fd==SOCKET_ERROR) return FALSE;
        
           ClientAddr.sin_family=AF_INET;
           ClientAddr.sin_port=htons(RemotePort);
 (DIR) diff --git a/src/network.h b/src/network.h
       t@@ -191,6 +191,8 @@ gboolean SetHttpAuthentication(HttpConnection *conn,gboolean proxy,
        void SetHttpAuthFunc(HttpConnection *conn,HCAuthFunc authfunc);
        gboolean HandleHttpCompletion(HttpConnection *conn);
        
       +int CreateTCPSocket(LastError *error);
       +gboolean BindTCPSocket(int sock,unsigned port,LastError *error);
        gboolean StartConnect(int *fd,gchar *RemoteHost,unsigned RemotePort,
                              gboolean NonBlocking,LastError *error);
        void StartNetworking(void);