📄 httplib.c
字号:
//---------------------------------------------------------------------//// httplib - HTTP data exchanges mini library////---------------------------------------------------------------------//// Code derived from: HTTP put/get mini lib written by L. Demailly// (c) 1998 Laurent Demailly - http://www.demailly.com/~dl/// (c) 1996 Observatoire de Paris - Meudon - France//// Released under the "artistic" license terms// See LICENSE (at http://www.demailly.com/~dl/)// for terms, conditions and DISCLAIMER OF ALL WARRANTIES////---------------------------------------------------------------------//// Converted to "pure" Palm APIs and integrated into a// Palm System Library by Patrice BERNARD - metro@nanika.net////---------------------------------------------------------------------// History//---------------------------------------------------------------------//// 2002-05-14// - Initial release with MetrUp//// 2002-05-19// - Bug correction: read all data from socket before closing it//// 2003-12-25// - Support for HTTP 1.1//// 2004-06-21// - Bug in netlib open IF error handling////---------------------------------------------------------------------#include <PalmOS.h>#include "httplib.h"//---------------------------------------------------------------------// Max buffer size//---------------------------------------------------------------------#define MAXBUF 512//---------------------------------------------------------------------// User agent id//---------------------------------------------------------------------#define HTTP_USER_AGENT "palmlib/1 ($Date: 2001/10/15 01:00:00 $)"//---------------------------------------------------------------------// Socket management mode//---------------------------------------------------------------------typedef enum {CLOSE, KEEP_OPEN} SOCKMODE;//---------------------------------------------------------------------// The global structure for this library//---------------------------------------------------------------------typedef struct { UInt16 HttpLibRefCnt; // Usage counter UInt16 NetLibRefNum; // Net Library reference Int32 NetLibTimeout; // Net calls timeout} HTTPLib_globals;//---------------------------------------------------------------------// Static functions prototypes//---------------------------------------------------------------------static HTTPLib_globals * HttpGetGlobals(UInt16 refnum);static void HttpParseURL(char *url, UInt16 *port, char **hostname, char **pfilepath);static int HttpReadLine(HTTPLib_globals *global, NetSocketRef sr, char *buffer, int max);static Int32 HttpReadData(HTTPLib_globals *global, NetSocketRef sr, char *buffer, Int32 *length);static void HttpDumpData(HTTPLib_globals *global, NetSocketRef sr);static int HttpQuery(HTTPLib_globals *global, char *host, UInt16 port, char *cmd, char *url, char *hdr, SOCKMODE mode, char *data, int length, NetSocketRef *psr);//---------------------------------------------------------------------// Dispatch table declarations//---------------------------------------------------------------------UInt32 install_dispatcher(UInt16, SysLibTblEntryPtr);MemPtr * gettable(void);//---------------------------------------------------------------------//// Create and initialize the dispatch table (for the standard functions// as well as for our own). Must be the first function in the library.// The jmptable contains:// 1 word = 6 * n + 2 where n is the total number of functions// n words = 2 * n + 4 * i + 2, one for each function (i=0 to n-1)////---------------------------------------------------------------------UInt32 start (UInt16 refnum, SysLibTblEntryPtr entryP){ UInt32 ret; asm (" movel %%fp@(10),%%sp@- movew %%fp@(8),%%sp@- jsr install_dispatcher(%%pc) movel %%d0,%0 jmp out(%%pc)gettable: lea jmptable(%%pc),%%a0 rtsjmptable: dc.w 62 dc.w 22 dc.w 26 dc.w 30 dc.w 34 dc.w 38 dc.w 42 dc.w 46 dc.w 50 dc.w 54 dc.w 58 jmp HTTPLib_open(%%pc) jmp HTTPLib_close(%%pc) jmp HTTPLib_sleep(%%pc) jmp HTTPLib_wake(%%pc) jmp HTTPLib_httpopn(%%pc) jmp HTTPLib_httpcls(%%pc) jmp HTTPLib_httpget(%%pc) jmp HTTPLib_httpreqopen(%%pc) jmp HTTPLib_httpreqread(%%pc) jmp HTTPLib_httpreqclose(%%pc) .asciz \"Pat HTTP Library\".evenout: " : "=r" (ret) :); return ret;}//---------------------------------------------------------------------//// Install the library dispatcher////---------------------------------------------------------------------UInt32 install_dispatcher(UInt16 refnum, SysLibTblEntryPtr entryP){ MemPtr * table = gettable(); entryP -> dispatchTblP = table; entryP -> globalsP = NULL; return 0;}//---------------------------------------------------------------------//// Get pointer to library global variables////---------------------------------------------------------------------HTTPLib_globals * HttpGetGlobals(UInt16 refnum){ SysLibTblEntryPtr entryP = SysLibTblEntry(refnum); return (HTTPLib_globals *) entryP -> globalsP;}//---------------------------------------------------------------------//// PalmOS Call when the library is opened: allocate global structure////---------------------------------------------------------------------Err HTTPLib_open(UInt16 refnum){ // Get current global pointer SysLibTblEntryPtr entryP = SysLibTblEntry(refnum); HTTPLib_globals * global = (HTTPLib_globals *) entryP -> globalsP; // It's open somewhere: increment usage counter if (global) { global -> HttpLibRefCnt++; return 0; } // Have to open it: create global structure entryP -> globalsP = MemPtrNew(sizeof(HTTPLib_globals)); MemPtrSetOwner(entryP->globalsP, 0); global = (HTTPLib_globals *) entryP -> globalsP; // Initialize the usage counter global -> HttpLibRefCnt = 1; return 0;}//---------------------------------------------------------------------//// PalmOS Call when the library is closed: process clean-up////---------------------------------------------------------------------Err HTTPLib_close(UInt16 refnum, UInt16 * numappsP){ // Get current global pointer SysLibTblEntryPtr entryP = SysLibTblEntry(refnum); HTTPLib_globals * global = (HTTPLib_globals *) entryP -> globalsP; if (!global) { // Looks like an error return 1; } // Decrement usage counter global -> HttpLibRefCnt--; *numappsP = global -> HttpLibRefCnt; // Free globals if no more user if (global -> HttpLibRefCnt == 0) { MemChunkFree(entryP -> globalsP); entryP -> globalsP = NULL; } return 0;}//---------------------------------------------------------------------//// PalmOS Call when the processor goes to sleep////---------------------------------------------------------------------Err HTTPLib_sleep(UInt16 refnum){ return 0;}//---------------------------------------------------------------------//// PalmOS Call when the processor wakes up from sleep////---------------------------------------------------------------------Err HTTPLib_wake(UInt16 refnum){ return 0;}//---------------------------------------------------------------------//// Read one line from input socket// Returns : < 0 if error, number of bytes read otherwise////---------------------------------------------------------------------static int HttpReadLine(HTTPLib_globals *global, NetSocketRef sr, char *buffer, int max){ int n = 0; Int16 nbr; Err err; while (n < max) { nbr = NetLibReceive(global -> NetLibRefNum, sr, buffer, 1, 0, 0, 0, global -> NetLibTimeout, &err); // Error : 0 socket has been closed, -1 severe error // Ok : number of bytes read if (nbr != 1) { n = -n; break; } n++; if (*buffer == '\r') continue; /* ignore CR */ if (*buffer == '\n') break; /* LF is the separator */ buffer++; } *buffer = 0; return n;}//---------------------------------------------------------------------//// Read the specified number of bytes from input// Returns : < 0 if error, number of bytes read otherwise////---------------------------------------------------------------------static Int32 HttpReadData(HTTPLib_globals *global, NetSocketRef sr, char *buffer, Int32 *length){ Int32 n, nbr; Err err; for (n=0; n<*length; n+=nbr, buffer+=nbr) { nbr = NetLibReceive(global -> NetLibRefNum, sr, buffer, *length-n, 0, 0, 0, global -> NetLibTimeout, &err); // Error : 0 socket has been closed, -1 severe error // Ok : number of bytes read if (nbr <= 0) { break; } } *length = n; return err;}//---------------------------------------------------------------------//// Read all pending data on socket and dump it////---------------------------------------------------------------------static void HttpDumpData(HTTPLib_globals *global, NetSocketRef sr){ Char data[256]; Err err; while (NetLibReceive(global -> NetLibRefNum, sr, data, 256, 0, 0, 0, global -> NetLibTimeout, &err) > 0);}//---------------------------------------------------------------------//// Send an HTTP query and get HTTP result code////---------------------------------------------------------------------static int HttpQuery(HTTPLib_globals *global, char *host, UInt16 port, char *cmd, char *url, char *hdr, SOCKMODE mode, char *data, int length, NetSocketRef *psr){ NetHostInfoBufType AppHostInfo; NetSocketAddrINType server; Err err; NetSocketRef sr; char header[MAXBUF]; int hdrlen; Int16 nbr; int ret; char * result; NetSocketLingerType linger = {0, 1}; if (psr) *psr = -1; // Get address if (NetLibGetHostByName(global -> NetLibRefNum, host, &AppHostInfo, global -> NetLibTimeout, &err)) { server.addr = AppHostInfo.address[0]; server.family = AppHostInfo.hostInfo.addrType; server.port = NetHToNS(port); } else { return NET_HOST_NOT_FOUND; } // Create the socket sr = NetLibSocketOpen(global -> NetLibRefNum, netSocketAddrINET, netSocketTypeStream, 0, global -> NetLibTimeout, &err); // Creation error if (sr < 0) { return NET_SOCKET_CREATE; } // Connect socket to server if (NetLibSocketConnect(global -> NetLibRefNum, sr, (NetSocketAddrType *)&server, sizeof(server), global -> NetLibTimeout, &err) >= 0) { if (psr) *psr = sr; // Create standard HTTP request header// hdrlen = StrPrintF(header, "%s http://%s/%s HTTP/1.0\r\nUser-Agent: %s\r\n%s\r\n", cmd, host, url, HTTP_USER_AGENT, hdr);// HTTP 1.1 version hdrlen = StrPrintF(header, "%s /%s HTTP/1.1\r\nhost: %s\r\nConnection: close\r\nUser-Agent: %s\r\n%s\r\n", cmd, url, host, HTTP_USER_AGENT, hdr); // Send header to target host nbr = NetLibSend(global -> NetLibRefNum, sr, (void *)header, hdrlen, 0, 0, 0, global -> NetLibTimeout, &err); if (nbr == hdrlen) { // Send data if any nbr = 0; if (length && data) { nbr = NetLibSend(global -> NetLibRefNum, sr, (void *)data, length, 0, 0, 0, global -> NetLibTimeout, &err); } // Data has been written correctly if (nbr == length) { // Read & parse result code ret = HttpReadLine(global, sr, header, MAXBUF-1); if (ret > 0) { ret = 0; result = StrChr(header, ' '); if (result) { ret = StrAToI(result+1); } // Could not find the ret code if (ret == 0) { ret = NET_INVALID_ANSWER; } } // Could not read response else { ret = NET_READ_HEADER; } } // Could not write data else { ret = NET_WRITE_DATA; } } // Could not write header else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -