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
