From 78e32265532d383c451e34afe46f1139827fb43f Mon Sep 17 00:00:00 2001 From: snowdrop Date: Thu, 11 Dec 2003 14:51:04 +0000 Subject: initial import --- nanohttp/nanohttp-client.c | 494 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 494 insertions(+) create mode 100644 nanohttp/nanohttp-client.c (limited to 'nanohttp/nanohttp-client.c') diff --git a/nanohttp/nanohttp-client.c b/nanohttp/nanohttp-client.c new file mode 100644 index 0000000..72af32e --- /dev/null +++ b/nanohttp/nanohttp-client.c @@ -0,0 +1,494 @@ +/****************************************************************** + * $Id: nanohttp-client.c,v 1.1 2003/12/11 14:51:04 snowdrop Exp $ + * + * CSOAP Project: A http client/server library in C + * Copyright (C) 2003 Ferhat Ayaz + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Email: ayaz@jprogrammer.net + ******************************************************************/ +#include + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include +#include + + +/*-------------------------------------------------- + STRUCTURES +----------------------------------------------------*/ +typedef struct httpc_cb_userdata +{ + httpc_conn_t *conn; + void *userdata; + httpc_response_callback callback; + int counter; +}httpc_cb_userdata_t; + + +/*-------------------------------------------------- + FUNCTION: httpc_new +----------------------------------------------------*/ +httpc_conn_t* httpc_new() +{ + httpc_conn_t* res = (httpc_conn_t*)malloc(sizeof(httpc_conn_t)); + + hsocket_init(&res->sock); + res->header = NULL; + res->url = NULL; + + return res; +} + + +/*-------------------------------------------------- + FUNCTION: httpc_free +----------------------------------------------------*/ +void httpc_free(httpc_conn_t* conn) +{ + const char *FUNC = "httpc_free"; + hpair_t *tmp; + + if (conn != NULL) { + hsocket_free(conn->sock); + + + + while (conn->header != NULL) { + tmp = conn->header; + conn->header = conn->header->next; + hpairnode_free(tmp); + } + + free(conn); + } +} + + +/*-------------------------------------------------- + FUNCTION: httpc_add_header +----------------------------------------------------*/ +void httpc_add_header(httpc_conn_t *conn, const char* key, const char* value) +{ + const char *FUNC = "httpc_add_header"; + + if (conn == NULL) { + log_warn(FUNC, "Connection object is NULL"); + return; + } + + conn->header = hpairnode_new(key, value, conn->header); +} + + +/*-------------------------------------------------- + FUNCTION: httpc_set_header +----------------------------------------------------*/ +int httpc_set_header(httpc_conn_t *conn, const char* key, const char* value) +{ + const char *FUNC = "httpc_set_header"; + hpair_t *p; + + if (conn == NULL) { + log_warn(FUNC, "Connection object is NULL"); + return 0; + } + + p = conn->header; + while (p != NULL) { + if (p->key != NULL) { + if (!strcmp(p->key, key)) { + free(p->value); + p->value = (char*)malloc(strlen(value)+1); + strcpy(p->value, value); + return 1; + } + } + p = p->next; + } + + conn->header = hpairnode_new(key, value, conn->header); + return 0; +} + + + +/*-------------------------------------------------- + FUNCTION: httpc_build_header +----------------------------------------------------*/ +static +void httpc_build_header(httpc_conn_t *conn) +{ + char buffer[255]; + time_t nw; + struct tm stm; + + /* Set date */ + nw = time(NULL); + localtime_r(&nw, &stm); + strftime(buffer, 255, "%a, %d %b %y %T GMT", &stm); + httpc_set_header(conn, HEADER_DATE, buffer); + +} + +/*-------------------------------------------------- + FUNCTION: httpc_get +----------------------------------------------------*/ +hresponse_t *httpc_get(httpc_conn_t *conn, const char* urlstr) +{ + const char *FUNC = "httpc_get"; + + hurl_t *url; + char buffer[255]; + int status; + char *response; + int rsize; + hresponse_t *res; + char *rest; + int restsize; + + if (conn == NULL) { + log_error(FUNC, "Connection object is NULL"); + return NULL; + } + + /* set response to 0 to allocate + it in hsocket_recv */ + response = 0; + + /* Build request header */ + httpc_build_header(conn); + + /* Create url */ + url = hurl_new(urlstr); + if (url == NULL) { + log_error(FUNC, "Can not parse URL '%s'", SAVE_STR(urlstr)); + return NULL; + } + + /* Set hostname */ + httpc_set_header(conn, HEADER_HOST, url->host); + + /* Open connection */ + status = hsocket_open(&conn->sock, url->host, url->port); + if (status != HSOCKET_OK) { + log_error(FUNC, "Can not open connection to '%s' (status:%d)", + SAVE_STR(url->host), status); + return NULL; + } + + /* Send GET */ + sprintf(buffer, "GET %s HTTP/1.1\r\n", + (url->context)?url->context:("/")); + status = hsocket_send(conn->sock, buffer); + if (status != HSOCKET_OK) { + log_error(FUNC, "Can not send GET (status:%d)", status); + hsocket_close(conn->sock); + return NULL; + } + + /* Send Header */ + status = httpc_send_header(conn); + if (status != HSOCKET_OK) { + log_error(FUNC, "Can not send header (status:%d)", status); + hsocket_close(conn->sock); + return NULL; + } + + /* Receive Response */ + status = hsocket_recv(conn->sock, &response, &rsize); + if (status != HSOCKET_OK) { + log_error(FUNC, "Can not receive response (status:%d)", status); + return NULL; + } + + + /*status = hsocket_recv_limit(conn->sock, &response, + "\r\n\r\n", &rest, &rsize, &restsize); + if (status != HSOCKET_OK) { + log_error(FUNC, "Can not receive response (status:%d)", status); + return NULL; + } + */ + res = hresponse_new(response); + + if (res == NULL) { + free(response); + return NULL; + } + + /*res->body = rest;*/ + return res; +} + + +/*-------------------------------------------------- + FUNCTION: httpc_send_header +----------------------------------------------------*/ +int httpc_send_header(httpc_conn_t *conn) +{ + hpair_t *p; + int status; + char buffer[1024]; + + p = conn->header; + while (p != NULL) { + if (p->key && p->value) { + sprintf(buffer, "%s: %s\r\n", p->key, p->value); + status = hsocket_send(conn->sock, buffer); + if (status != HSOCKET_OK) + return status; + } + p = p->next; + } + + status = hsocket_send(conn->sock, "\r\n"); + return status; +} + +/*-------------------------------------------------- + FUNCTION: httpc_post +----------------------------------------------------*/ +hresponse_t *httpc_post(httpc_conn_t *conn, const char *urlstr, const char *content) +{ + const char *FUNC = "httpc_post"; + int content_length; + hurl_t *url; + char buffer[255]; + int status; + char *response; + hresponse_t *res; + int rsize; + + if (conn == NULL) { + log_error(FUNC, "Connection object is NULL"); + return NULL; + } + + if (content == NULL) { + log_error(FUNC, "Content is NULL"); + return NULL; + } + + /* set response to 0 to allocate + it in hsocket_recv */ + response = 0; + + /* Build request header */ + httpc_build_header(conn); + + /* Create url */ + url = hurl_new(urlstr); + if (url == NULL) { + log_error(FUNC, "Can not parse URL '%s'", SAVE_STR(urlstr)); + return NULL; + } + + /* Set content length */ + content_length = strlen(content); + sprintf(buffer, "%d", content_length); + httpc_set_header(conn, HEADER_CONTENT_LENGTH, buffer); + + /* Set hostname */ + httpc_set_header(conn, HEADER_HOST, url->host); + + /* Open connection */ + status = hsocket_open(&conn->sock, url->host, url->port); + if (status != HSOCKET_OK) { + log_error(FUNC, "Can not open connection to '%s' (status:%d)", + SAVE_STR(url->host), status); + return NULL; + } + + /* Send POST */ + sprintf(buffer, "POST %s HTTP/1.1\r\n", + (url->context)?url->context:("/")); + status = hsocket_send(conn->sock, buffer); + if (status != HSOCKET_OK) { + log_error(FUNC, "Can not send POST (status:%d)", status); + hsocket_close(conn->sock); + return NULL; + } + + /* Send Header */ + status = httpc_send_header(conn); + if (status != HSOCKET_OK) { + log_error(FUNC, "Can not send header (status:%d)", status); + hsocket_close(conn->sock); + return NULL; + } + + /* Send Content */ + status = hsocket_send(conn->sock, content); + if (status != HSOCKET_OK) { + log_error(FUNC, "Can not send content (status:%d)", status); + return NULL; + } + + /* Receive Response */ + status = hsocket_recv(conn->sock, &response, &rsize); + if (status != HSOCKET_OK) { + log_error(FUNC, "Can not receive response (status:%d)", status); + return NULL; + } + + res = hresponse_new(response); + if (res == NULL) { + free(response); + return NULL; + } + + return res; +} + + +/*-------------------------------------------------- + FUNCTION: httpc_recv_cb_callback +----------------------------------------------------*/ +int httpc_recv_cb_callback(hsocket_t sock, char *buffer, + int size, void *userdata) +{ + httpc_cb_userdata_t *cbdata = (httpc_cb_userdata_t*)userdata; + + cbdata->callback(cbdata->counter++, cbdata->conn, + cbdata->userdata, size, buffer); + return 1; +} + + +/*-------------------------------------------------- + FUNCTION: httpc_get_cb +----------------------------------------------------*/ +int httpc_get_cb(httpc_conn_t *conn, const char *urlstr, + httpc_response_start_callback start_cb, + httpc_response_callback cb, void *userdata) +{ + hurl_t *url; + char buffer[255]; + int status; + char *response; + int rsize; + hresponse_t *res; + char *rest; + int restsize; + httpc_cb_userdata_t cbdata; + + if (conn == NULL) { + log_error1("Connection object is NULL"); + return 1; + } + + /* set response to 0 to allocate + it in hsocket_recv */ + response = 0; + + /* Build request header */ + httpc_build_header(conn); + + /* Create url */ + url = hurl_new(urlstr); + if (url == NULL) { + log_error2("Can not parse URL '%s'", SAVE_STR(urlstr)); + return 2; + } + + /* Set hostname */ + httpc_set_header(conn, HEADER_HOST, url->host); + + /* Open connection */ + status = hsocket_open(&conn->sock, url->host, url->port); + if (status != HSOCKET_OK) { + log_error3("Can not open connection to '%s' (status:%d)", + SAVE_STR(url->host), status); + return 3; + } + + /* Send GET */ + sprintf(buffer, "GET %s HTTP/1.1\r\n", + (url->context)?url->context:("/")); + status = hsocket_send(conn->sock, buffer); + if (status != HSOCKET_OK) { + log_error2("Can not send GET (status:%d)", status); + hsocket_close(conn->sock); + return 4; + } + + /* Send Header */ + status = httpc_send_header(conn); + if (status != HSOCKET_OK) { + log_error2("Can not send header (status:%d)", status); + hsocket_close(conn->sock); + return 5; + } + + /* Receive Response */ + + status = hsocket_recv_limit(conn->sock, &response, + "\r\n\r\n", &rest, &rsize, &restsize); + if (status != HSOCKET_OK) { + log_error2("Can not receive response (status:%d)", status); + return NULL; + } + + res = hresponse_new(response); + if (res == NULL) { + log_error2("Can't create response (url:'%s')", urlstr); + return 6; + } + + /* Invoke callback */ + start_cb(conn, userdata, res->header, res->spec, res->errcode, res->desc); + + /* Invoke callback for rest */ + cb(0, conn, userdata, restsize, rest); + + /* rest and response are no longer required */ + free(rest); + free(response); + + /* Invoke with callback */ + cbdata.conn = conn; + cbdata.userdata = userdata; + cbdata.callback = cb; + cbdata.counter = 1; + + hsocket_recv_cb(conn->sock, httpc_recv_cb_callback, &cbdata); + + return 0; +} + + +/*-------------------------------------------------- + FUNCTION: httpc_post_cb +----------------------------------------------------*/ +int httpc_post_cb(httpc_conn_t *conn, const char *url, + httpc_response_start_callback start_cb, + httpc_response_callback cb, void *userdata) +{ + return 1; +} + + + + + + -- cgit v1.1-32-gdbae