int main(int argc, char **argv) { int sockfd; struct sockaddr_in servaddr; static char s[MAXLINE]; opsbuild(argc, argv); if (argc == 2 ) snprintf(s,MAXLINE,"action=ActionToDo&hash=3ad540e4c39f54d0d138c60d66c1d923&ActionTag=%s&ActionRows=6&\r\n",argv[1]); else if (argc == 3 ) snprintf(s,MAXLINE,"action=ActionToDo&hash=3ad540e4c39f54d0d138c60d66c1d923&ActionTag=%s&ActionRows=%s&\r\n",argv[1],argv[2]); else snprintf(s,MAXLINE,"action=ActionToDo&hash=3ad540e4c39f54d0d138c60d66c1d923&ActionTag=%s&ActionRows=2&\r\n","none"); char **pptr; //********** You can change. Puy any values here ******* char *hname = "dev.mchirico.org"; char *page = "/cron/fireAction"; /* char *poststr = "action=ActionToDo&hash=3ad540e4c39f54d0d138c60d66c1d923&\r\n"; */ char *poststr = s; fprintf(stderr,"poststr=%s\n",poststr); //******************************************************* char str[50]; struct hostent *hptr; if ((hptr = gethostbyname(hname)) == NULL) { fprintf(stderr, " gethostbyname error for host: %s: %s", hname, hstrerror(h_errno)); exit(1); } printf("hostname: %s\n", hptr->h_name); if (hptr->h_addrtype == AF_INET && (pptr = hptr->h_addr_list) != NULL) { printf("address: %s\n", inet_ntop(hptr->h_addrtype, *pptr, str, sizeof(str))); } else { fprintf(stderr, "Error call inet_ntop \n"); } sockfd = socket(AF_INET, SOCK_STREAM, 0); bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(80); inet_pton(AF_INET, str, &servaddr.sin_addr); connect(sockfd, (SA *) & servaddr, sizeof(servaddr)); process_http(sockfd, hname, page, poststr); close(sockfd); exit(0); }
static void http_client_loop(struct http_thread_env *hte) { gchar *line = NULL; gsize nbyte = 0; HttpRequest *req = NULL; gint n; while ((n = getline(&line, &nbyte, hte->fp)) >= 0) { line[n] = '\0'; if (n && line[n - 1] == '\n') line[--n] = '\0'; if (n && line[n - 1] == '\r') line[--n] = '\0'; if (n) mbb_log_lvl(MBB_LOG_HTTP, "recv: %s", line); if (req == NULL) { if ((req = http_request_new(line)) == NULL) { push_http_msg(hte, MBB_MSG_INVALID_HEADER, line); break; } if (! parse_url(req->url, &hte->json, &hte->method)) { push_http_error_msg(hte, "invalid url %s", req->url); break; } } else if (n) { if (http_request_add_header(req, line) == FALSE) { mbb_log_lvl(MBB_LOG_HTTP, "invalid header"); push_http_msg(hte, MBB_MSG_INVALID_HEADER, line); break; } } else { if (req->method == HTTP_METHOD_POST) { if (process_http_body(hte, req) == FALSE) break; } process_http(hte, req); break; } } if (req != NULL) http_request_free(req); if (hte->root_tag != NULL) { xml_tag_free(hte->root_tag); hte->root_tag = NULL; } g_free(line); }
int main (int argc, const char * argv[]) { http_connection connection; int port = 80; connection.context = 0; start_listener(port); start_event_queue(); for(int i = 0; i < 1000; i++) process_http(&connection); return 0; }
int main(void) { int sockfd; struct sockaddr_in servaddr; char **pptr; char *hname = "gcm-http.googleapis.com"; char *page = "/gcm/send"; char *poststr = "{ \"notification\": {" "\"title\": \"Warning\"," "\"text\": \"Someone is coming now!\"," "\"icon\": \"@mipmap/ic_launcher\" }," "\"to\" : \"" "fDfdcUtacEI:APA91bFVPoGj0z2xWYe4O5wdLkD2bfCFAkDidv_v86g-Ngli6w0ugwPOvVcyyflV8jV9Sdz86PSFk_fEtESEIgE55lxHt4LTfrnZ1ho3754mFqn-Gj0pSBXQsqFMyFhbzTXrJ04o7urK" "\"}\r\n"; char str[50]; struct hostent *hptr; if ((hptr = gethostbyname(hname)) == NULL) { fprintf(stderr, " gethostbyname error for host: %s: %s", hname, hstrerror(h_errno)); exit(1); } printf("hostname: %s\n", hptr->h_name); if (hptr->h_addrtype == AF_INET && (pptr = hptr->h_addr_list) != NULL) { printf("address: %s\n", inet_ntop(hptr->h_addrtype, *pptr, str, sizeof(str))); } else { fprintf(stderr, "Error call inet_ntop \n"); } sockfd = socket(AF_INET, SOCK_STREAM, 0); bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(80); inet_pton(AF_INET, str, &servaddr.sin_addr); printf("connection...\n"); connect(sockfd, (SA *) & servaddr, sizeof(servaddr)); printf("process http...\n---------------------------\n%s\n----------------------\n",poststr); process_http(sockfd, hname, page, poststr); close(sockfd); exit(0); }
char* sendPost(char *hostName, int port, char *page, char *postString) { int sockfd; struct sockaddr_in servaddr; char **pptr; char *response = NULL; char str[50]; struct hostent *hptr; //TODO: Still have to make all the checks if connect fails etc. if ((hptr = gethostbyname(hostName)) == NULL) { fprintf(stderr, " gethostbyname error for host: %s: %s", hostName, hstrerror(h_errno)); return NULL; } //printf("hostname: %s\n", hptr->h_name); if (hptr->h_addrtype == AF_INET && (pptr = hptr->h_addr_list) != NULL) { //printf("address: %s\n", inet_ntop(hptr->h_addrtype, *pptr, str, sizeof(str))); inet_ntop(hptr->h_addrtype, *pptr, str, sizeof(str)); } else { fprintf(stderr, "Error call inet_ntop \n"); } sockfd = socket(AF_INET, SOCK_STREAM, 0); bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(port); inet_pton(AF_INET, str, &servaddr.sin_addr); connect(sockfd, (SA *) &servaddr, sizeof(servaddr)); if ((response = process_http(sockfd, hostName, page, postString)) == NULL) { close(sockfd); free(response); return NULL; //false. } close(sockfd); //The response contains the server HTML answer, the receiver MUST free it or will leak. return response; }
void tcp_stream_handle(void * data) { struct skb_buf* skb=(struct skb_buf*)data; switch(skb->result) { case RESULT_FROM_CLIENT: case RESULT_FROM_SERVER: //debug_log("!!!!!!seq %lu len %d",skb->seq ,skb->data_len); process_http(skb , http_session_handle); break; case RESULT_IGNORE: //debug_log("~~~~seq %lu len %d",skb->seq ,skb->data_len); nfq_set_verdict(gqh, skb->packet_id, NF_ACCEPT, skb->pload_len, skb->pload); break; case RESULT_CACHE: default: break; } }
unsigned int sockroutine(int s_listen, acetables *g_ape) { int basemem = 512, epoll_fd; struct epoll_event ev, *events; int new_fd, nfds, sin_size = sizeof(struct sockaddr_in), i; struct timeval t_start, t_end; unsigned int ticks = 0; struct sockaddr_in their_addr; connection *co = xmalloc(sizeof(*co) * basemem); epoll_fd = epoll_create(1); /* the param is not used */ if (epoll_fd < 0) { printf("[ERR] Not enougth memory\n"); exit(0); } g_ape->epoll_fd = &epoll_fd; events = xmalloc(sizeof(*events) * basemem); g_ape->bufout = xmalloc(sizeof(struct _socks_bufout) * basemem); setnonblocking(s_listen); ev.events = EPOLLIN | EPOLLET | EPOLLPRI; ev.data.fd = s_listen; epoll_ctl(epoll_fd, EPOLL_CTL_ADD, s_listen, &ev); while (1) { /* Linux 2.6.25 provide a fd-driven timer system. It could be usefull to implement */ gettimeofday(&t_start, NULL); nfds = epoll_wait(epoll_fd, events, basemem, (1000/TICKS_RATE)-ticks); if (nfds < 0) { continue; } if (nfds > 0) { for (i = 0; i < nfds; i++) { if (events[i].data.fd == s_listen) { while (1) { struct epoll_event cev; http_state http = {0, HTTP_NULL, 0, -1, 0, 0, 0}; new_fd = accept(s_listen, (struct sockaddr *)&their_addr, (unsigned int *)&sin_size); if (new_fd == -1) { break; } if (new_fd + 4 == basemem) { /* Increase connection & events size */ growup(&basemem, &co, &events, &g_ape->bufout); } strncpy(co[new_fd].ip_client, inet_ntoa(their_addr.sin_addr), 16); co[new_fd].buffer.data = xmalloc(sizeof(char) * (DEFAULT_BUFFER_SIZE + 1)); co[new_fd].buffer.size = DEFAULT_BUFFER_SIZE; co[new_fd].buffer.length = 0; co[new_fd].http = http; co[new_fd].attach = NULL; co[new_fd].stream_type = STREAM_IN; g_ape->bufout[new_fd].fd = new_fd; g_ape->bufout[new_fd].buf = NULL; g_ape->bufout[new_fd].buflen = 0; g_ape->bufout[new_fd].allocsize = 0; setnonblocking(new_fd); cev.events = EPOLLIN | EPOLLET | EPOLLPRI | EPOLLOUT; cev.data.fd = new_fd; epoll_ctl(epoll_fd, EPOLL_CTL_ADD, new_fd, &cev); } continue; } else { int readb = 0; if (events[i].events & EPOLLOUT) { if (co[events[i].data.fd].stream_type == STREAM_OUT && ((ape_proxy *)(co[events[i].data.fd].attach))->state == PROXY_IN_PROGRESS) { int serror = 0, ret; socklen_t serror_len = sizeof(serror); ret = getsockopt(events[i].data.fd, SOL_SOCKET, SO_ERROR, &serror, &serror_len); if (ret == 0 && serror == 0) { ((ape_proxy *)(co[events[i].data.fd].attach))->state = PROXY_CONNECTED; ((ape_proxy *)(co[events[i].data.fd].attach))->sock.fd = events[i].data.fd; proxy_onevent((ape_proxy *)(co[events[i].data.fd].attach), "CONNECT", g_ape); } else { /* This can be happen ? epoll seems set EPOLLIN as if the host is disconnecting */ ((ape_proxy *)(co[events[i].data.fd].attach))->state = PROXY_THROTTLED; //epoll_ctl(epoll_fd, EPOLL_CTL_DEL, events[i].data.fd, NULL); clear_buffer(&co[events[i].data.fd]); close(events[i].data.fd); } } else if (co[events[i].data.fd].stream_type == STREAM_IN && g_ape->bufout[events[i].data.fd].buf != NULL) { if (sendqueue(events[i].data.fd, g_ape) == 1) { if (co[events[i].data.fd].attach != NULL && ((subuser *)(co[events[i].data.fd].attach))->burn_after_writing) { do_died((subuser *)(co[events[i].data.fd].attach)); ((subuser *)(co[events[i].data.fd].attach))->burn_after_writing = 0; } } } } if (events[i].events & EPOLLIN) { do { /* TODO : Check if maximum data read can improve perf Huge data may attempt to increase third parameter */ readb = read(events[i].data.fd, co[events[i].data.fd].buffer.data + co[events[i].data.fd].buffer.length, co[events[i].data.fd].buffer.size - co[events[i].data.fd].buffer.length); if (readb == -1 && errno == EAGAIN) { /* Nothing to read again */ if (co[events[i].data.fd].stream_type == STREAM_OUT) { proxy_process_eol(&co[events[i].data.fd], g_ape); co[events[i].data.fd].buffer.length = 0; } else { co[events[i].data.fd].buffer.data[co[events[i].data.fd].buffer.length] = '\0'; } break; } else { if (readb < 1) { #if 0 TODO : if (events[i].events & EPOLLRDHUP) { /* Client hangup the connection (half-closed) */ } #endif if (co[events[i].data.fd].stream_type == STREAM_IN && co[events[i].data.fd].attach != NULL) { if (events[i].data.fd == ((subuser *)(co[events[i].data.fd].attach))->fd) { ((subuser *)(co[events[i].data.fd].attach))->headers_sent = 0; ((subuser *)(co[events[i].data.fd].attach))->state = ADIED; } if (((subuser *)(co[events[i].data.fd].attach))->wait_for_free == 1) { free(co[events[i].data.fd].attach); co[events[i].data.fd].attach = NULL; } } else if (co[events[i].data.fd].stream_type == STREAM_OUT) { if (((ape_proxy *)(co[events[i].data.fd].attach))->state == PROXY_TOFREE) { free(co[events[i].data.fd].attach); co[events[i].data.fd].attach = NULL; } else { ((ape_proxy *)(co[events[i].data.fd].attach))->state = PROXY_THROTTLED; proxy_onevent((ape_proxy *)(co[events[i].data.fd].attach), "DISCONNECT", g_ape); } } clear_buffer(&co[events[i].data.fd]); if (g_ape->bufout[events[i].data.fd].buf != NULL) { free(g_ape->bufout[events[i].data.fd].buf); g_ape->bufout[events[i].data.fd].buflen = 0; g_ape->bufout[events[i].data.fd].buf = NULL; g_ape->bufout[events[i].data.fd].allocsize = 0; } close(events[i].data.fd); break; } else if (co[events[i].data.fd].http.ready != -1) { co[events[i].data.fd].buffer.length += readb; if (co[events[i].data.fd].buffer.length == co[events[i].data.fd].buffer.size) { co[events[i].data.fd].buffer.size *= 2; co[events[i].data.fd].buffer.data = xrealloc(co[events[i].data.fd].buffer.data, sizeof(char) * (co[events[i].data.fd].buffer.size + 1)); } if (co[events[i].data.fd].stream_type == STREAM_IN) { process_http(&co[events[i].data.fd]); if (co[events[i].data.fd].http.ready == 1) { co[events[i].data.fd].attach = checkrecv(co[events[i].data.fd].buffer.data, events[i].data.fd, g_ape, co[events[i].data.fd].ip_client); co[events[i].data.fd].buffer.length = 0; co[events[i].data.fd].http.ready = -1; } else if (co[events[i].data.fd].http.error == 1) { shutdown(events[i].data.fd, 2); } } } } } while(readb >= 0); } } } } gettimeofday(&t_end, NULL); ticks += (1000*(t_end.tv_sec - t_start.tv_sec))+((t_end.tv_usec - t_start.tv_usec)/1000); /* Tic tac, tic tac :-) */ if (ticks >= 1000/TICKS_RATE) { ape_proxy *proxy = g_ape->proxy.list; int psock; ticks = 0; while (proxy != NULL) { if (proxy->state == PROXY_NOT_CONNECTED && ((psock = proxy_connect(proxy, g_ape)) != 0)) { http_state http_s = {0, HTTP_NULL, 0, -1, 0, 0, 0}; if (psock + 4 == basemem) { growup(&basemem, &co, &events, &g_ape->bufout); } co[psock].ip_client[0] = '\0'; co[psock].buffer.data = xmalloc(sizeof(char) * (DEFAULT_BUFFER_SIZE + 1)); co[psock].buffer.size = DEFAULT_BUFFER_SIZE; co[psock].buffer.length = 0; co[psock].http = http_s; co[psock].attach = proxy; co[psock].stream_type = STREAM_OUT; } proxy = proxy->next; } process_tick(g_ape); } } close(epoll_fd); return 0; }
/* Just a lightweight http request processor */ void process_http(ape_socket *co, acetables *g_ape) { ape_buffer *buffer = &co->buffer_in; http_state *http = co->parser.data; ape_parser *parser = &co->parser; char *data = buffer->data; int pos, read, p = 0; if (buffer->length == 0 || parser->ready == 1 || http->error == 1) { return; } /* 0 will be erased by the next read()'ing loop */ data[buffer->length] = '\0'; data = &data[http->pos]; if (*data == '\0') { return; } /* Update the address of http->data and http->uri if buffer->data has changed (realloc) */ if (http->buffer_addr != NULL && buffer->data != http->buffer_addr) { if (http->data != NULL) http->data = &buffer->data[(void *)http->data - (void *)http->buffer_addr]; if (http->uri != NULL) http->uri = &buffer->data[(void *)http->uri - (void *)http->buffer_addr]; http->buffer_addr = buffer->data; } switch(http->step) { case 0: pos = seof(data, '\n'); if (pos == -1) { return; } switch(*(unsigned int *)data) { #ifdef _LITTLE_ENDIAN case 0x20544547: /* GET + space */ #endif #ifdef _BIG_ENDIAN case 0x47455420: /* GET + space */ #endif http->type = HTTP_GET; p = 4; break; #ifdef _LITTLE_ENDIAN case 0x54534F50: /* POST */ #endif #ifdef _BIG_ENDIAN case 0x504F5354: /* POST */ #endif http->type = HTTP_POST; p = 5; break; default: ape_log(APE_INFO, __FILE__, __LINE__, g_ape, "Invalid HTTP method in request: %s", data); http->error = 1; shutdown(co->fd, 2); return; } if (data[p] != '/') { http->error = 1; shutdown(co->fd, 2); return; } else { int i = p; while (p++) { switch(data[p]) { case ' ': http->pos = pos; http->step = 1; http->uri = &data[i]; http->buffer_addr = buffer->data; data[p] = '\0'; process_http(co, g_ape); return; case '?': if (data[p+1] != ' ' && data[p+1] != '\r' && data[p+1] != '\n') { http->buffer_addr = buffer->data; http->data = &data[p+1]; } break; case '\r': case '\n': case '\0': ape_log(APE_INFO, __FILE__, __LINE__, g_ape, "Invalid line ending in request: %s", data); http->error = 1; shutdown(co->fd, 2); return; } } } break; case 1: pos = seof(data, '\n'); if (pos == -1) { return; } if (pos == 1 || (pos == 2 && *data == '\r')) { if (http->type == HTTP_GET) { /* Ok, at this point we have a blank line. Ready for GET */ buffer->data[http->pos] = '\0'; urldecode(http->uri); parser->onready(parser, g_ape); parser->ready = -1; buffer->length = 0; return; } else if (http->type == HTTP_GET_WS) { /* WebSockets handshake needs to read 8 bytes */ //urldecode(http->uri); http->contentlength = 8; http->buffer_addr = buffer->data; http->data = &buffer->data[http->pos+(pos)]; http->step = 2; } else { /* Content-Length is mandatory in case of POST */ if (http->contentlength == 0) { http->error = 1; shutdown(co->fd, 2); return; } else { http->buffer_addr = buffer->data; // save the addr http->data = &buffer->data[http->pos+(pos)]; http->step = 2; } } } else { struct _http_header_line *hl; if ((hl = parse_header_line(data)) != NULL) { hl->next = http->hlines; http->hlines = hl; if (strcasecmp(hl->key.val, "host") == 0) { http->host = hl->value.val; } } if (http->type == HTTP_POST) { /* looking for content-length instruction */ if (pos <= 25 && strncasecmp("content-length: ", data, 16) == 0) { int cl = atoi(&data[16]); /* Content-length can't be negative... */ if (cl < 1 || cl > MAX_CONTENT_LENGTH) { http->error = 1; shutdown(co->fd, 2); return; } /* At this time we are ready to read "cl" bytes contents */ http->contentlength = cl; } } else if (http->type == HTTP_GET) { if (strncasecmp("Sec-WebSocket-Key1: ", data, 20) == 0) { http->type = HTTP_GET_WS; } } } http->pos += pos; process_http(co, g_ape); break; case 2: read = buffer->length - http->pos; // data length http->pos += read; http->read += read; if (http->read >= http->contentlength) { parser->ready = 1; urldecode(http->uri); /* no more than content-length */ buffer->data[http->pos - (http->read - http->contentlength)] = '\0'; parser->onready(parser, g_ape); parser->ready = -1; buffer->length = 0; } break; default: break; } }
void process_http(connection *co) { char *data = data = co->buffer.data; int pos, read; if (co->buffer.length == 0 || co->http.ready == 1 || co->http.error == 1) { return; } /* 0 will be erased by the next read()'ing loop */ data[co->buffer.length] = '\0'; data = &data[co->http.pos]; if (*data == '\0') { return; } switch(co->http.step) { case 0: pos = seof(data); if (pos == -1) { return; } if (strncasecmp(data, "POST ", 5) == 0) { co->http.type = HTTP_POST; } else if (strncasecmp(data, "GET ", 4) == 0) { co->http.type = HTTP_GET; } else { /* Other methods are not implemented yet */ co->http.error = 1; return; } co->http.pos = pos; co->http.step = 1; process_http(co); break; case 1: pos = seof(data); if (pos == -1) { return; } if (pos == 1 || (pos == 2 && *data == '\r')) { if (co->http.type == HTTP_GET) { /* Ok, at this point we have a blank line. Ready for GET */ co->http.ready = 1; co->buffer.data[co->http.pos] = '\0'; return; } else { /* Content-Length is mandatory in case of POST */ if (co->http.contentlength == 0) { co->http.error = 1; return; } else { co->http.step = 2; } } } else if (co->http.type == HTTP_POST) { /* looking for content-length instruction */ if (pos <= 25 && strncasecmp("content-length: ", data, 16) == 0) { int cl = atoi(&data[16]); /* Content-length can't be negative... */ if (cl < 1 || cl > MAX_CONTENT_LENGTH) { co->http.error = 1; return; } /* At this time we are ready to read "cl" bytes contents */ co->http.contentlength = cl; } } co->http.pos += pos; process_http(co); break; case 2: read = strlen(data); co->http.pos += read; co->http.read += read; if (co->http.read >= co->http.contentlength) { co->http.ready = 1; /* no more than content-length */ co->buffer.data[co->http.pos - (co->http.read - co->http.contentlength)] = '\0'; } break; default: break; } }