void stream_writer_send_8(struct stream_writer * writer, int8_t value) { int remain = writer->max_size - writer->written; if (remain < 1) { stream_writer_send_remain(writer); } writer->buffer[writer->written++] = (char)value; }
void _http_client_request(struct http_client_module *const module) { struct stream_writer writer; int size; int result; char length[11]; char *ptr; const char CH_LUT[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; struct http_entity * entity; union http_client_data data; #define HTTP_CHUNKED_MAX_LENGTH 3 /*TCP MTU is 1400(0x578) */ char buffer[module->config.send_buffer_size]; if (module == NULL) { return; } if (module->sending != 0) { /* Device is busy. */ return; } entity = &module->req.entity; switch (module->req.state) { case STATE_REQ_SEND_HEADER: /* Initializing variables. */ module->req.content_length = 0; module->req.sent_length = 0; stream_writer_init(&writer, buffer, module->config.send_buffer_size, _http_client_send_wait, (void *)module); /* Write Method. */ if (module->req.method == HTTP_METHOD_GET) { stream_writer_send_buffer(&writer, "GET ", 4); } else if (module->req.method == HTTP_METHOD_POST) { stream_writer_send_buffer(&writer, "POST ", 5); } else if (module->req.method == HTTP_METHOD_DELETE) { stream_writer_send_buffer(&writer, "DELETE ", 7); } else if (module->req.method == HTTP_METHOD_PUT) { stream_writer_send_buffer(&writer, "PUT ", 4); } else if (module->req.method == HTTP_METHOD_OPTIONS) { stream_writer_send_buffer(&writer, "OPTIONS ", 8); } else if (module->req.method == HTTP_METHOD_HEAD) { stream_writer_send_buffer(&writer, "HEAD ", 5); } /* Write URI. */ stream_writer_send_buffer(&writer, module->req.uri, strlen(module->req.uri)); stream_writer_send_buffer(&writer, " "HTTP_PROTO_NAME"\r\n", strlen(" "HTTP_PROTO_NAME"\r\n")); /* Write HTTP headers. */ /* Default value. */ //stream_writer_send_buffer(&writer, "User-Agent: ", strlen("User-agent: ")); //stream_writer_send_buffer(&writer, (char *)module->config.user_agent, strlen(module->config.user_agent)); //stream_writer_send_buffer(&writer, "\r\n", strlen("\r\n")); stream_writer_send_buffer(&writer, "Host: ", strlen("Host: ")); stream_writer_send_buffer(&writer, module->host, strlen(module->host)); stream_writer_send_buffer(&writer, "\r\n", strlen("\r\n")); /* It supported persistent connection. */ stream_writer_send_buffer(&writer, "Connection: Keep-Alive\r\n", strlen("Connection: Keep-Alive\r\n")); /* Notify supported encoding type and character set. */ /* should write accept json, but for now i will just take it out */ //stream_writer_send_buffer(&writer, "Accept: application/x-www-form-urlencoded; charset=utf-8\r\n", strlen("Accept: application/x-www-form-urlencoded; charset=utf-8\r\n")); //stream_writer_send_buffer(&writer, "Accept-Charset: utf-8\r\n", strlen("Accept-Charset: utf-8\r\n")); if (entity->read != NULL) { /* HTTP Entity is exist. */ if (entity->is_chunked) { /* Chunked mode. */ module->req.content_length = -1; stream_writer_send_buffer(&writer, "Transfer-Encoding: chunked\r\n", strlen("Transfer-Encoding: chunked\r\n")); } else if(entity->get_contents_length) { module->req.content_length = entity->get_contents_length(entity->priv_data); if (module->req.content_length < 0) { /* Error was occurred. */ /* Does not send any entity. */ module->req.content_length = 0; } else { sprintf(length, "%u", (unsigned int)module->req.content_length); stream_writer_send_buffer(&writer, "Content-Length: ", strlen("Content-Length: ")); stream_writer_send_buffer(&writer, length, strlen(length)); stream_writer_send_buffer(&writer, "\r\n", strlen("\r\n")); if( entity->get_contents_type ) { stream_writer_send_buffer(&writer, "Content-Type: ", strlen("Content-Type: ")); stream_writer_send_buffer(&writer, entity->get_contents_type(entity->priv_data), strlen(entity->get_contents_type(entity->priv_data))); stream_writer_send_buffer(&writer, "\r\n", strlen("\r\n")); } } } } if (module->req.ext_header != NULL ) { stream_writer_send_buffer(&writer, module->req.ext_header, strlen(module->req.ext_header)); } //See the module->header stream_writer_send_buffer(&writer, "\r\n", strlen("\r\n")); stream_writer_send_remain(&writer); module->req.state = STATE_REQ_SEND_ENTITY; /* Send first part of entity. */ case STATE_REQ_SEND_ENTITY: if (module->req.content_length < 0 && entity->read) { /* Send chunked packet. */ /* Chunked header (size + \r\n) tail (\r\n) */ size = entity->read(entity->priv_data, buffer + HTTP_CHUNKED_MAX_LENGTH + 2, module->config.send_buffer_size - HTTP_CHUNKED_MAX_LENGTH - 4, module->req.sent_length); if (size < 0) { /* If occurs problem during the operation, Close this socket. */ size = 0; } buffer[HTTP_CHUNKED_MAX_LENGTH + 1] = '\n'; buffer[HTTP_CHUNKED_MAX_LENGTH] = '\r'; buffer[size + HTTP_CHUNKED_MAX_LENGTH + 2] = '\r'; buffer[size + HTTP_CHUNKED_MAX_LENGTH + 3] = '\n'; if (size >= 0) { ptr = buffer + 2; *ptr = CH_LUT[size % 16]; } if (size >= 0x10) { ptr = buffer + 1; *ptr = CH_LUT[(size / 0x10) % 16]; } if (size >= 0x100) { ptr = buffer; *ptr = CH_LUT[(size / 0x100) % 16]; } //module->sending = 1; printf("send data \r\n%s\r\n", ptr); if ((result = send(module->sock, (void*)ptr, ptr + HTTP_CHUNKED_MAX_LENGTH - buffer + size + 4, 0)) < 0) { _http_client_clear_conn(module, -EIO); return; } module->req.sent_length += size; if(size == 0) { if (module->req.entity.close) { module->req.entity.close(module->req.entity.priv_data); } module->req.state = STATE_SOCK_CONNECTED; if (module->cb) { module->cb(module, HTTP_CLIENT_CALLBACK_REQUESTED, &data); } break; } } else if (module->req.content_length > 0 && entity->read) { /* Send entity. */ if (module->req.sent_length >= module->req.content_length) { /* Complete to send the buffer. */ if (module->req.entity.close) { module->req.entity.close(module->req.entity.priv_data); } module->req.state = STATE_SOCK_CONNECTED; if (module->cb) { module->cb(module, HTTP_CLIENT_CALLBACK_REQUESTED, &data); } break; } size = entity->read(entity->priv_data, buffer, module->config.send_buffer_size, module->req.sent_length); if (size < 0) { /* Entity occurs errors or EOS. */ /* Disconnect it. */ _http_client_clear_conn(module, (size == 0)?-EBADMSG:-EIO); } else { if (size > module->req.content_length - module->req.sent_length) { size = module->req.content_length - module->req.sent_length; } //module->sending = 1; if( size > 0 ) { for( int i=0 ; i<size ; i++) printf("%c", buffer[i]); printf("\r\n"); } if ((result = send(module->sock, (void*)buffer, size, 0)) < 0) { _http_client_clear_conn(module, -EIO); return; } module->req.sent_length += size; } } else { /* Has not any entity. */ module->req.state = STATE_SOCK_CONNECTED; if (module->cb) { module->cb(module, HTTP_CLIENT_CALLBACK_REQUESTED, &data); } break; } break; default: /* Invalid status. */ break; } }