Author: matt
Date: 2012-06-14 16:47:42 -0700 (Thu, 14 Jun 2012)
New Revision: 9608
Log:
Very rough kayout of FTPClient

Modified:
   branches/branch-3.0/include/fltk3connect/HTTPClient.h
   branches/branch-3.0/include/fltk3connect/Socket.h
   branches/branch-3.0/include/fltk3connect/TCPSocket.h
   branches/branch-3.0/src/fltk3connect/HTTPClient.cxx
   branches/branch-3.0/src/fltk3connect/Socket.cxx
   branches/branch-3.0/src/fltk3connect/TCPSocket.cxx
   branches/branch-3.0/test/connect.cxx

Modified: branches/branch-3.0/include/fltk3connect/HTTPClient.h
===================================================================
--- branches/branch-3.0/include/fltk3connect/HTTPClient.h       2012-06-14 
18:40:11 UTC (rev 9607)
+++ branches/branch-3.0/include/fltk3connect/HTTPClient.h       2012-06-14 
23:47:42 UTC (rev 9608)
@@ -25,25 +25,55 @@
 //     http://www.fltk.org/str.php
 //
 
-#ifndef Fltk3_HTTP_Connection_H
-#define Fltk3_HTTP_Connection_H
+#ifndef FLTK3_HTTP_CLIENT_H
+#define FLTK3_HTTP_CLIENT_H
 
 /* \file
  fltk3::fltk3::HTTPClient widget . */
 
-#if 0 // TODO: FLTK3 Connect is not yet implemented 
+#include <fltk3connect/TCPSocket.h>
 
-/*
+#include <string.h>
+
+namespace fltk3 {
+
+/**
+ This class implements an HTTP client widget.
+ It can be used to manage network connections to HTTP servers. This is great 
+ for fetching web pages and other resources from the world wide web.
  
- This file will eventually contain an HTTP client widget which can be used
- to manage network connections to HTTP server. This is great for fetching
- web pages and other resources from the world wide web.
+ port 80 (or 8080, etc)
  
- To implement this class, fltk3::FTPClient may serve as a good start. 
+ request (header, body)
+    "GET /index.html HTTP/1.1\r\nHost: www.example.net\r\n\r\n"
  
+ response (header, body)
+    "HTTP/1.1 200 OK\r\n"
+    "Server: Apache/1.3.29 (Unix) PHP/4.3.4\r\n"
+    "Content-Length: 1024\r\n"
+    "Content-Language: en\r\n"
+    "Connection: close\r\n"
+    "Content-Type: text/html\r\n"
+    "\r\n" - binary data follows
  */
+  class HTTPClient : public TCPSocket
+  {
+    
+  protected:
+    
+    char *pHost;
+    
+  public:
+    
+    HTTPClient(int x, int y, int w, int h, const char *label=0L);
+    ~HTTPClient();
+    int connect(const char *host);
+    int GET(const char *filename);
+    
+  };
+  
+}
 
-#endif
 
 #endif
 

Modified: branches/branch-3.0/include/fltk3connect/Socket.h
===================================================================
--- branches/branch-3.0/include/fltk3connect/Socket.h   2012-06-14 18:40:11 UTC 
(rev 9607)
+++ branches/branch-3.0/include/fltk3connect/Socket.h   2012-06-14 23:47:42 UTC 
(rev 9608)
@@ -65,15 +65,13 @@
   class Socket : public Group
   {
     
-  private:
+  protected:
     
     int pStatus;
     int pActive;
     double pFirstByteTimeout;
     double pNextByteTimeout;
     
-  protected:
-    
     void draw();
     
   public:
@@ -137,7 +135,7 @@
      \param text the text we want to send
      \return the number of bytes sent, or -1 for error
      */
-    virtual char send(const char *text);
+    virtual int send(const char *text);
     
     /**
      Receive data until the buffer is filled or a timout occurs.

Modified: branches/branch-3.0/include/fltk3connect/TCPSocket.h
===================================================================
--- branches/branch-3.0/include/fltk3connect/TCPSocket.h        2012-06-14 
18:40:11 UTC (rev 9607)
+++ branches/branch-3.0/include/fltk3connect/TCPSocket.h        2012-06-14 
23:47:42 UTC (rev 9608)
@@ -31,7 +31,7 @@
 /* \file
  fltk3::TCPSocket widget . */
 
-#include <fltk3/Widget.h>
+#include <fltk3connect/Socket.h>
 #include <fltk3/Group.h>
 
 #ifdef WIN32
@@ -45,24 +45,23 @@
    \brief A simple TCP connection.
    
    This class wraps fltk3::add_fd, fltk3::remove_fd, and friends in a simple
-   package. 
+   package. It implements TCP/IP sockets as listeners (for servers) and as
+   initiators of a connection (for clients).
    
    Connections can be managed via callbacks or by overriding the on_...
    methods in this class.
    
    \todo There are still a lot of useful features missing in this class.
    */
-  class TCPSocket : public Widget
+  class TCPSocket : public Socket
   {
     
   private:
     
-    int pStatus;
-    int pActive;
 #ifdef WIN32
     SOCKET sListen;
     SOCKET sData;
-    static char wsaStartup;
+    static char pWSAStartup;
 #else
     int fdListen;
     int fdData;
@@ -76,16 +75,10 @@
     
     void draw();
     
+    static void wsaStartup();
+    
   public:
     
-    enum Status {
-      CLOSED, LISTENING, VERIFYING, CONNECTED
-    };
-    
-    enum Event {
-      CONNECT=128, RECEIVE, CLOSE
-    };
-    
     /**
      Create a widget that manages a TCP/IP network connection.
      This widget manages a network connection, displaying a graphic 
@@ -98,7 +91,7 @@
     /**
      Disconnect and return resources
      */
-    virtual ~TCPSocket();
+    ~TCPSocket();
     
     // server methods
     
@@ -122,23 +115,48 @@
     // client methods
     
     /**
-     Attempt a connection to another TCP/IP socket in liestening mode.
+     Attempt a connection to another TCP/IP socket which is in listening mode.
      */
     int connect(unsigned char ip0, unsigned char ip1, unsigned char ip2, 
unsigned char ip3, unsigned short port);
+
+    /**
+     Attempt a connection to another TCP/IP socket which is in listening mode.
+     
+     Supported formats:
+      - <i>name:port</i>, for example <i>ftp.fltk.org:21</i>
+     
+     /param server name and port number in a string
+     */
+    int connect(const char *server);
+
+    /**
+     Attempt a connection to another TCP/IP socket which is in listening mode.
+     
+     \param name server name
+     \param port TCP/IP port number (21 for FTP, etc.)
+     */
+    int connect(const char *server, unsigned short port);
     
+    /**
+     Find the IP address of a host using its host name.
+     
+     This method may block for a while.
+     
+     \param name the name of the host
+     \param[out] ip0, ip1, ip2, ip3 the individual bytes of the IP address.
+     \return -1 for error
+     */
+    int find_host(const char* name, unsigned char &ip0, unsigned char &ip1, 
unsigned char &ip2, unsigned char &ip3);
+    
     // shared methods
     
     /**
      Send a datablock over the network connection.
      */
-    char send(const void *data, int size);
+    int send(const void *data, int size);
+    int send(const char *text) { return Socket::send(text); }
     
     /**
-     Send some text, terminated by NUL.
-     */
-    char send(const char *text);
-    
-    /**
      Receive data until the buffer is filled.
      \todo Code on Unix is missing the loop.
      */

Modified: branches/branch-3.0/src/fltk3connect/HTTPClient.cxx
===================================================================
--- branches/branch-3.0/src/fltk3connect/HTTPClient.cxx 2012-06-14 18:40:11 UTC 
(rev 9607)
+++ branches/branch-3.0/src/fltk3connect/HTTPClient.cxx 2012-06-14 23:47:42 UTC 
(rev 9608)
@@ -27,20 +27,81 @@
 
 #include <fltk3connect/HTTPClient.h>
 
-#if 0 // TODO: FLTK3 Connect is not yet implemented 
 
-/*
- 
- This file will eventually contain an HTTP client widget which can be used
- to manage network connections to HTTP server. This is great for fetching
- web pages and other resources from the world wide web.
- 
- To implement this class, fltk3::FTPClient may serve as a good start. 
- 
- */
+fltk3::HTTPClient::HTTPClient(int x, int y, int w, int h, const char *l)
+: fltk3::TCPSocket(x, y, w, h, l),
+  pHost(0)
+{
+}
 
-#endif
 
+fltk3::HTTPClient::~HTTPClient()
+{
+  if (pHost)
+    free(pHost);
+}
+
+
+int fltk3::HTTPClient::connect(const char *host)
+{
+  int ret = -1;
+  if (pHost) {
+    free(pHost);
+    pHost = 0;
+  }
+  if (host) {
+    const char *cln = strchr(host, ':');
+    if (cln) {
+      ret = TCPSocket::connect(host);
+    } else {
+      ret = TCPSocket::connect(host, 80);
+    }
+    pHost = strdup(host);
+  }
+  return ret;
+}
+
+
+int fltk3::HTTPClient::GET(const char *filename)
+{
+  int ret = -1;
+  if (!filename || !*filename) 
+    filename = "index.html";
+  
+  int size = 32+strlen(filename)+strlen(pHost);
+  char *msg = (char*)malloc(size);
+  snprintf(msg, size, "GET /%s HTTP/1.1\r\nHost: %s\r\n\r\n", filename, pHost);
+  send(msg);
+  
+  // sync mode for testing: simply wait indefinetly for a reply
+  char buf[2048]; buf[0] = 0;
+  
+  // grab the header
+  int n = recv(buf, 2048);
+  if (strncmp(buf, "HTTP", 4)!=0) {
+    return ret;
+  }
+  if (strncmp(buf+4, "/1.1 ", 5)!=0) {
+    return ret;
+  }
+  int err = atoi(buf+9);
+  printf("ERROR: %d\n", err);
+  
+  char *len_key = strstr(buf, "Content-Length:");
+  char *data_key = strstr(buf, "\r\n\r\n");
+  if (len_key && data_key) {
+    int len = atoi(len_key+15);
+    const char *data = (char*)malloc(len);
+    //int nd = n-data_key+4;
+    //memcpy(data, data_key+4, n);    
+    //free(data);//
+  }
+  
+  return ret;
+}
+
+
+
 //
 // End of "$Id$".
 //

Modified: branches/branch-3.0/src/fltk3connect/Socket.cxx
===================================================================
--- branches/branch-3.0/src/fltk3connect/Socket.cxx     2012-06-14 18:40:11 UTC 
(rev 9607)
+++ branches/branch-3.0/src/fltk3connect/Socket.cxx     2012-06-14 23:47:42 UTC 
(rev 9608)
@@ -41,6 +41,9 @@
   pFirstByteTimeout(0),
   pNextByteTimeout(0)
 {
+  box(fltk3::THIN_DOWN_BOX);
+  align(fltk3::ALIGN_LEFT);
+  end();
 }
 
 
@@ -61,7 +64,7 @@
 }
 
 
-char fltk3::Socket::send(const char *text)
+int fltk3::Socket::send(const char *text)
 {
   if (text) {
     return send(text, strlen(text));

Modified: branches/branch-3.0/src/fltk3connect/TCPSocket.cxx
===================================================================
--- branches/branch-3.0/src/fltk3connect/TCPSocket.cxx  2012-06-14 18:40:11 UTC 
(rev 9607)
+++ branches/branch-3.0/src/fltk3connect/TCPSocket.cxx  2012-06-14 23:47:42 UTC 
(rev 9608)
@@ -32,7 +32,7 @@
 #include <fltk3/draw.h>
 
 #ifdef WIN32
-char fltk3::TCPSocket::wsaStartup = 0;
+char fltk3::TCPSocket::pWSAStartup = 0;
 typedef int socklen_t;
 #else
 # include <unistd.h>
@@ -55,9 +55,7 @@
 
 
 fltk3::TCPSocket::TCPSocket(int x, int y, int w, int h, const char *l)
-: fltk3::Widget(x, y, w, h, l),
-  pStatus(CLOSED),
-  pActive(0),
+: fltk3::Socket(x, y, w, h, l),
 #ifdef WIN32
   sListen(INVALID_SOCKET),
   sData(INVALID_SOCKET),
@@ -67,8 +65,6 @@
 #endif
   pPort(-1)
 {
-  box(fltk3::THIN_DOWN_BOX);
-  align(fltk3::ALIGN_LEFT);
   LOG("fltk3::TCPSocket: constructor\n");
 }
 
@@ -80,6 +76,24 @@
 }
 
 
+void fltk3::TCPSocket::wsaStartup()
+{
+#ifdef WIN32
+  if (!pWSAStartup) {
+    WORD wVersionRequested;
+    WSADATA wsaData;
+    int err;
+    wVersionRequested = MAKEWORD( 2, 2 );
+    err = WSAStartup( wVersionRequested, &wsaData );
+    if (err) {
+      LOG("fltk3::TCPSocket: listen - WSAStartup failed!\n");
+    }
+    pWSAStartup = 1;
+  }
+#endif
+}
+
+
 void fltk3::TCPSocket::close()
 {
   LOG("fltk3::TCPSocket: close\n");
@@ -118,6 +132,7 @@
 
 int fltk3::TCPSocket::connect(unsigned char ip0, unsigned char ip1, unsigned 
char ip2, unsigned char ip3, unsigned short port)
 {
+  wsaStartup();
   redraw();
 #ifdef WIN32
   if (sData==INVALID_SOCKET)
@@ -126,17 +141,6 @@
 #endif
     {
 #ifdef WIN32
-      if (!wsaStartup) {
-        WORD wVersionRequested;
-        WSADATA wsaData;
-        int err;
-        wVersionRequested = MAKEWORD( 2, 2 );
-        err = WSAStartup( wVersionRequested, &wsaData );
-        if (err) {
-          LOG("fltk3::TCPSocket: listen - WSAStartup failed!\n");
-        }
-        wsaStartup = 1;
-      }
       pStatus = CLOSED;
       
       // create the socket
@@ -144,7 +148,7 @@
       sData = socket(AF_INET, SOCK_STREAM, 0);
       if (sData==INVALID_SOCKET) {
         LOG("fltk3::TCPSocket: connect - can't open socket\n");
-        return 0;
+        return -1;
       }
 #else
       // create the socket
@@ -152,7 +156,7 @@
       fdData = socket(AF_INET, SOCK_STREAM, 0);
       if (fdData==-1) {
         LOG("fltk3::TCPSocket: connect - can't open socket\n");
-        return 0;
+        return -1;
       }
 #endif
     }
@@ -178,7 +182,7 @@
       ::close(fdData);
       fdData = -1;
 #endif
-      return 0;
+      return -1;
     }
   // all went well, we listen for connections now
   pStatus = CONNECTED;
@@ -190,12 +194,57 @@
   fltk3::add_fd(fdData, fltk3::READ, pDataReadCB, this);
   fltk3::add_fd(fdData, fltk3::EXCEPT, pDataExceptCB, this);
 #endif
-  return 1;
+  return 0;
 }
 
 
+int fltk3::TCPSocket::connect(const char *name)
+{
+  if (!name) 
+    return -1;
+  int ret = -1;
+  char *host = strdup(name);
+  char *col = strchr(host, ':');
+  if (col) {
+    unsigned short port = atoi(col+1);
+    *col = 0;
+    ret = connect(host, port);
+  }
+  free(host);
+  return ret;
+}
+
+
+int fltk3::TCPSocket::connect(const char *name, unsigned short port)
+{
+  unsigned char ip0, ip1, ip2, ip3;
+  int ret = -1;
+  if (find_host(name, ip0, ip1, ip2, ip3)!=-1) {
+    ret = connect(ip0, ip1, ip2, ip3, port);
+  }
+  return ret;
+}
+
+
+int fltk3::TCPSocket::find_host(const char* name, unsigned char &ip0, unsigned 
char &ip1, unsigned char &ip2, unsigned char &ip3)
+{
+  int ret = -1;
+  wsaStartup();
+  struct hostent* host = gethostbyname(name);
+  if (host && (host->h_addrtype==2) && (host->h_length==4)) {
+    ip0 = host->h_addr_list[0][0];
+    ip1 = host->h_addr_list[0][1];
+    ip2 = host->h_addr_list[0][2];
+    ip3 = host->h_addr_list[0][3];
+    ret = 0;
+  }
+  return ret;
+}
+
+
 int fltk3::TCPSocket::available() const
 {
+  wsaStartup();
   unsigned long n;
 #ifdef WIN32
   DWORD rcvd;
@@ -277,6 +326,7 @@
 
 char fltk3::TCPSocket::listen(unsigned short port) 
 {
+  wsaStartup();
   redraw();
 #ifdef WIN32
   if (sListen==INVALID_SOCKET)
@@ -285,7 +335,7 @@
 #endif
     {
 #ifdef WIN32
-      if (!wsaStartup) {
+      if (!pWSAStartup) {
         WORD wVersionRequested;
         WSADATA wsaData;
         int err;
@@ -294,7 +344,7 @@
         if (err) {
           LOG("fltk3::TCPSocket: listen - WSAStartup failed!\n");
         }
-        wsaStartup = 1;
+        pWSAStartup = 1;
       }
 #endif
       pStatus = CLOSED;
@@ -305,13 +355,13 @@
       sListen = socket(AF_INET, SOCK_STREAM, 0);
       if (sListen==INVALID_SOCKET) {
         LOG("fltk3::TCPSocket: listen - can't open socket\n");
-        return 0;
+        return -1;
       }
 #else
       fdListen = socket(AF_INET, SOCK_STREAM, 0);
       if (fdListen==-1) {
         LOG("fltk3::TCPSocket: listen - can't open socket\n");
-        return 0;
+        return -1;
       }
 #endif
       
@@ -328,14 +378,14 @@
         LOG("fltk3::TCPSocket: listen - can't bind socket\n");
         closesocket(sListen);
         sListen = INVALID_SOCKET;
-        return 0;
+        return -1;
       }
 #else
       if (::bind(fdListen, (struct sockaddr*)&my_addr, addr_len) == -1) {
         LOG("fltk3::TCPSocket: listen - can't bind socket\n");
         ::close(fdListen);
         fdListen = -1;
-        return 0;
+        return -1;
       }
 #endif
     }
@@ -347,7 +397,7 @@
     pStatus = CLOSED;
     closesocket(sListen);
     sListen = INVALID_SOCKET;
-    return 0;
+    return -1;
   }
 #else
   if (::listen(fdListen, 0) == -1) {
@@ -355,7 +405,7 @@
     pStatus = CLOSED;
     ::close(fdListen);
     fdListen = -1;
-    return 0;
+    return -1;
   }
 #endif
   // all went well, we listen for connections now
@@ -366,12 +416,13 @@
 #else
   fltk3::add_fd(fdListen, pListenCB, this);
 #endif
-  return 1;
+  return 0;
 }
 
 
 char fltk3::TCPSocket::accept()
 {
+  wsaStartup();
   redraw();
   LOG("fltk3::TCPSocket: accept\n");
 #ifdef WIN32
@@ -391,14 +442,14 @@
   if (sData==INVALID_SOCKET) {
     LOG("fltk3::TCPSocket: accept - failed\n");
     close();
-    return 0;
+    return -1;
   }
 #else
   fdData = ::accept(fdListen, (struct sockaddr*)&their_addr, &addr_len);
   if (fdData==-1) {
     LOG("fltk3::TCPSocket: accept - failed\n");
     close();
-    return 0;
+    return -1;
   }
 #endif
   pStatus = CONNECTED;
@@ -409,36 +460,30 @@
   fltk3::add_fd(fdData, fltk3::READ, pDataReadCB, this);
   fltk3::add_fd(fdData, fltk3::EXCEPT, pDataExceptCB, this);
 #endif
-  return 1;
+  return 0;
 }
 
 
-char fltk3::TCPSocket::send(const char *text)
+int fltk3::TCPSocket::send(const void *d, int n)
 {
-  return send(text, strlen(text));
-}
-
-
-char fltk3::TCPSocket::send(const void *d, int n)
-{
   LOG("fltk3::TCPSocket: send\n");
   pActive++; redraw();
 #ifdef WIN32
   if (sData==INVALID_SOCKET) {
-    return 0;
+    return -1;
   }
   if (::send(sData, (const char*)d, n, 0)!=n) {
-    return 0;
+    return -1;
   }
 #else
   if (fdData==-1) {
-    return 0;
+    return -1;
   }
   if (::send(fdData, d, n, 0)!=n) {
-    return 0;
+    return -1;
   }
 #endif
-  return 1;
+  return n;
 }
 
 
@@ -446,7 +491,7 @@
 {
 #ifdef WIN32
   if (sData==-1) {
-    return 0;
+    return -1;
   }
   char *dst = (char*)d;
   int sum = 0;
@@ -461,7 +506,7 @@
   }
 #else
   if (fdData==-1) {
-    return 0;
+    return -1;
   }
   return ::recv(fdData, d, n, MSG_WAITALL);
 #endif
@@ -472,12 +517,12 @@
 {
 #ifdef WIN32
   if (sData==-1) {
-    return 0;
+    return -1;
   }
   return ::recv(sData, (char*)d, n, 0);
 #else
   if (fdData==-1) {
-    return 0;
+    return -1;
   }
   int ret = ::recv(fdData, d, n, 0);
 #if 0
@@ -500,12 +545,12 @@
 {
 #ifdef WIN32
   if (sData==-1) {
-    return 0;
+    return -1;
   }
   return ::recv(sData, (char*)d, n, MSG_PEEK);
 #else
   if (fdData==-1) {
-    return 0;
+    return -1;
   }
   return ::recv(fdData, d, n, MSG_PEEK);
 #endif

Modified: branches/branch-3.0/test/connect.cxx
===================================================================
--- branches/branch-3.0/test/connect.cxx        2012-06-14 18:40:11 UTC (rev 
9607)
+++ branches/branch-3.0/test/connect.cxx        2012-06-14 23:47:42 UTC (rev 
9608)
@@ -38,11 +38,21 @@
 
 void ftp_cb(fltk3::Widget*, void *d)
 {
+#if 0
   fltk3::FTPClient *ftp = (fltk3::FTPClient*)d;
-  
   ftp->sync_open("ftp.gnu.org", "anonymous", "[email protected]");
-  //ftp->dir()....
   ftp->close();
+#endif
+#if 0
+  unsigned char ip0, ip1, ip2, ip3;
+  fltk3::TCPSocket* s = new fltk3::TCPSocket(0, 0, 0, 0, 0);
+  s->find_host("fltk.org", ip0, ip1, ip2, ip3);
+#endif
+#if 1
+  fltk3::HTTPClient *http = (fltk3::HTTPClient*)d;
+  http->connect("www.fltk.org");
+  http->GET("index.php");  
+#endif
 }
 
 
@@ -52,9 +62,16 @@
   fltk3::Window* win = new fltk3::Window(300, 100, "FTP test");
   win->begin();
   fltk3::Button* btn = new fltk3::Button(10, 10, 150, 24, "ftp.gnu.org");
+#if 0
   fltk3::FTPClient* ftp = new fltk3::FTPClient(100, 44, 50, 24, "FTP:");
   ftp->align(fltk3::ALIGN_LEFT);
   btn->callback(ftp_cb, ftp);
+#endif
+#if 1
+  fltk3::HTTPClient* http = new fltk3::HTTPClient(100, 44, 50, 24, "HTTP:");
+  http->align(fltk3::ALIGN_LEFT);
+  btn->callback(ftp_cb, http);
+#endif
   win->end();
   win->show(argc, argv);
   fltk3::run();

_______________________________________________
fltk-commit mailing list
[email protected]
http://lists.easysw.com/mailman/listinfo/fltk-commit

Reply via email to