211 sscanf_s 和 fgets (从buffer里读取file_stream)

1 从buffer里读取file_stream中带标签的数据

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
int main(void) {
	FILE* file_stream = NULL;
	errno_t err = fopen_s(&file_stream, "E:\\桌面\\cs.txt", "r");
	if (err != 0 || file_stream == NULL) {
		perror("file opening failed");
		return EXIT_FAILURE;
	}
	char line[200];
	char name[100] = "";
	int age = 0;
	char gender = 'N';
	float num = 0.00f;
	 while(fgets(line, sizeof(line), file_stream) != NULL)
	{
		if (strstr(line, "name:") != NULL) {
		
			sscanf_s(line, "name:%s", name, (unsigned)_countof(name));
		
		}
		if (strstr(line, "age:") != NULL) {
		
			sscanf_s(line, "age:%d", &age);
		}
		if (strstr(line, "gender:") != NULL) {
		
			sscanf_s(line, "gender:%c", &gender, 1);
		}
		if (strstr(line, "num") != NULL) {
		
			sscanf_s(line, "num:%f", &num);
		}
	}
	printf("name:%s\n", name);
	printf("age:%d\n", age);
	printf("gender:%c\n", gender);
	printf("num:%.4f\n", num);
	fclose(file_stream);
	return 0;
}

2 output:

name:Lily
age:23
gender:G
num:3.1456

3file

4 注意点:

1.sscanf_s中参数的顺序,第二个参数是格式化字符串(char* format)
2.sscanf_s 不支持指定浮点数的小数位数,只需要用 %f 即可

#include <dirent.h> #include <sys/statfs.h> #include "common.h" #include "storage.h" #include "iot_info.h" #include "device.h" #ifdef HEALTH_INFO_SUPPORT #include "health_info.h" #endif void storage_session_free(STORAGE_SESSION *storage_session); void storage_server_timeout_handle_immediately(STORAGE_SERVER *storage_server); /*---------------------------------------------------------*/ void storage_delete_posted_session(STORAGE_SERVER *storage_server, char *dev_id, int storage_type) { STORAGE_SESSION *session, *nsession; if (!storage_server || !dev_id) { DBG_ERR("arg NULL\n"); return; } if (STORAGE_STREAMING == storage_type) { list_for_each_entry_safe(session, nsession, &storage_server->stream_session, list) { if (!strncmp(session->dev_id, dev_id, LEN_MAX_ID) && !session->uploading_flag && (!session->stream_send_to_cloud_flag || session->delete_flag)) { storage_session_free(session); } } } else if (STORAGE_SNAPSHOT == storage_type) { list_for_each_entry_safe(session, nsession, &storage_server->snapshot_session, list) { DBG_DBG("%s %s %d %d %d\n", dev_id,session->dev_id, session->uploading_flag, session->snapshot_send_to_cloud_flag, session->delete_flag); if (!strncmp(session->dev_id, dev_id, LEN_MAX_ID) && !session->uploading_flag && (!session->snapshot_send_to_cloud_flag || session->delete_flag)) { storage_session_free(session); } } } } static void storage_session_telemetry_failure_count(STORAGE_SESSION *storage_session) { DEV_INFO *dev_info; MEDIACENTER_CTX *mediacenter_ctx; if (!storage_session) { DBG_ERR("arg NULL\n"); return; } mediacenter_ctx = storage_session->storage_server->worker_ctx->top_ctx; dev_info = get_dev_info(mediacenter_ctx, storage_session->dev_id, storage_session->dev_ip); if (dev_info && storage_session->post_success && (dev_info->telemetry.relay_clips_failure_count > 0)) { dev_info->telemetry.relay_clips_failure_count--; #ifdef HEALTH_INFO_SUPPORT dev_update_health_info(dev_info->dev_id); #endif } return; } void storage_delete_sessions_of_device(MEDIACENTER_CTX *mediacenter_ctx, char *dev_id) { WORKER_CTX *worker_ctx = NULL; STORAGE_SERVER *storage_server = NULL; STORAGE_SESSION *session = NULL, *nsession = NULL; if (!mediacenter_ctx || !dev_id) { DBG_ERR("arg NULL\n"); return; } if (list_empty(&mediacenter_ctx->worker_list)) { DBG_ERR("worker list empty\n"); return; } worker_ctx = (WORKER_CTX *)list_first_entry(&mediacenter_ctx->worker_list, STORAGE_SESSION, list); if (worker_ctx) { storage_server = worker_ctx->storage_server; if (storage_server) { list_for_each_entry_safe(session, nsession, &storage_server->stream_session, list) { if (!strncmp(session->dev_id, dev_id, LEN_MAX_ID)) { storage_session_free(session); } } list_for_each_entry_safe(session, nsession, &storage_server->snapshot_session, list) { if (!strncmp(session->dev_id, dev_id, LEN_MAX_ID)) { storage_session_free(session); } } } } } int storage_session_get_push_status(STORAGE_SESSION *session) { DEV_INFO *dev_info; MEDIACENTER_CTX *mediacenter_ctx; if (!session) { DBG_ERR("arg NULL\n"); return -1; } mediacenter_ctx = session->storage_server->worker_ctx->top_ctx; dev_info = get_dev_info(mediacenter_ctx, session->dev_id, session->dev_ip); if (dev_info) { if (STORAGE_STREAMING == session->storage_type) { return dev_info->alarm_stream_push_status; } else { return dev_info->alarm_snapshot_push_status; } } return -1; } void storage_session_set_push_status(STORAGE_SESSION *session, int status) { DEV_INFO *dev_info; MEDIACENTER_CTX *mediacenter_ctx; if (!session) { DBG_ERR("arg NULL\n"); return; } mediacenter_ctx = session->storage_server->worker_ctx->top_ctx; dev_info = get_dev_info(mediacenter_ctx, session->dev_id, session->dev_ip); if (dev_info) { DBG_INFO("It is alarm re-upload below\n"); if (STORAGE_STREAMING == session->storage_type) { dev_set_alarm_stream_status(dev_info, status); } else { dev_set_alarm_snapshot_status(dev_info, status); } } return; } void storage_session_reupload_timeout(struct uloop_timeout* tmo) { //MYDEBUG("STORAGE SESSION REUPLOAD CHECK TIMEOUT\n"); unsigned long long sent; STORAGE_SESSION *storage_session = container_of(tmo, STORAGE_SESSION, reupload_tmo); if (!storage_session) { DBG_ERR("arg NULL\n"); return; } uloop_timeout_set(&storage_session->reupload_tmo, storage_session->reupload_idle_time); if (storage_session->sock) { sent = storage_session->reupload_total_load - storage_session->sock->write_buf_length; if (sent <= storage_session->reupload_last_sent) { DBG_ERR("STORAGE SESSION REUPLOAD TIMEOUT\n"); tpsocket_free(storage_session->sock); } else { storage_session->reupload_last_sent = sent; storage_session->reupload_last_load = storage_session->reupload_total_load; } } } bool storage_session_write_list_force(STORAGE_SESSION *storage_session, struct list_head *head, bool force) { struct tpsocket_buf *buf; unsigned long long to_send = 0; if (!storage_session || !head) { DBG_ERR("arg NULL\n"); return false; } /* data length */ list_for_each_entry(buf, head, list) { to_send += tpbuf_data_len(buf); } /* move bufs to sock */ if (false == tpsocket_write_list_force(storage_session->sock, head, force)) { DBG_ERR("tpsocket_write_list error\n"); return false; } /* calculate total load */ storage_session->reupload_total_load += to_send; return true; } void storage_session_stream_add_tail(STORAGE_SESSION *storage_session) { struct list_head head; if (!storage_session) { DBG_ERR("arg NULL\n"); return; } if (storage_session->chunked) { INIT_LIST_HEAD(&head); tpsocket_chunk_encode(&head);//generate chunk end '0\r\n' tpsocket_write_list_force(storage_session->sock, &head, true); } tpsocket_write_list_force(storage_session->sock, &head, true); } void storage_session_snapshot_add_tail(STORAGE_SESSION *storage_session) { struct tpsocket_buf *mybuf = NULL; struct list_head head; if (!storage_session) { DBG_ERR("arg NULL\n"); return; } INIT_LIST_HEAD(&head); mybuf = tpbuf_snprintf(LEN_MAX_128, "\r\n"); if (mybuf) { list_add_tail(&mybuf->list, &head); } if (storage_session->region_buf_len) { mybuf = tpbuf_snprintf(LEN_MAX_128*4, "%s", storage_session->region_buf); if (mybuf) { list_add_tail(&mybuf->list, &head); } } mybuf = tpbuf_snprintf(LEN_MAX_128, "--%s--", SNAPSHOT_FILE_BOUNDARY);//generate snapshot multi-part end if (mybuf) { list_add_tail(&mybuf->list, &head); } if (storage_session->chunked) { tpsocket_chunk_encode(&head); } tpsocket_write_list_force(storage_session->sock, &head, true); } int storage_session_set_region(STORAGE_SESSION *storage_session, TRIGGER_REGION *region) { if (!storage_session || !region) { DBG_ERR("arg NULL\n"); return -1; } if (0 == region->x1 && 0 == region->y1 && 0 == region->x2 && 0 == region->y2) { } else { storage_session->region_buf_len = snprintf(storage_session->region_buf, LEN_MAX_128*4, "--%s\r\n" "Content-Disposition: form-data;name=\"region\"\r\n\r\n" "{\"top\": %d, \"bottom\": %d, \"left\": %d, \"right\": %d}\r\n", SNAPSHOT_FILE_BOUNDARY, region->y1, region->y2, region->x1, region->x2); MYDEBUG("%s", storage_session->region_buf); } return 0; } int storage_session_set_event_timestamp(STORAGE_SESSION *storage_session, time_t timestamp) { if (!storage_session) { DBG_ERR("arg NULL\n"); return -1; } //storage_session->event_timestamp = timestamp - common_get_time_diff(); storage_session->event_timestamp = timestamp; return 0; } int storage_session_set_event_type(STORAGE_SESSION *storage_session, enum EVENT_TYPE event_type) { if (!storage_session) { DBG_ERR("arg NULL\n"); return -1; } storage_session->event_type = event_type; return 0; } void storage_update_list(STORAGE_SERVER *storage_server, int flag) { STORAGE_SESSION *storage_session; char list_path[LEN_MAX_PATH] = {0}; FILE *fd; if (!storage_server) { DBG_ERR("arg NULL\n"); return; } if (STORAGE_STREAMING == flag) { memset(list_path, 0, LEN_MAX_PATH); snprintf(list_path, LEN_MAX_PATH, "%s/%s", STORAGE_ROOT_PATH, STORAGE_STREAMING_LIST); fd = fopen(list_path, "w"); if (fd) { list_for_each_entry(storage_session, &storage_server->stream_session, list) { fwrite(storage_session, sizeof(*storage_session), 1, fd); } fclose(fd); } } if (STORAGE_SNAPSHOT == flag) { memset(list_path, 0, LEN_MAX_PATH); snprintf(list_path, LEN_MAX_PATH, "%s/%s", STORAGE_ROOT_PATH, STORAGE_SNAPSHOT_LIST); fd = fopen(list_path, "w"); if (fd) { list_for_each_entry(storage_session, &storage_server->snapshot_session, list) { fwrite(storage_session, sizeof(*storage_session), 1, fd); } fclose(fd); } } } void storage_session_add_session(STORAGE_SESSION *storage_session) { STORAGE_SERVER *storage_server; STORAGE_SESSION *session, *nsession; if (!storage_session) { MYDEBUG("arg NULL\n"); return; } storage_server = storage_session->storage_server; if (STORAGE_STREAMING == storage_session->storage_type) { MYDEBUG("storage stream session = %p\n", storage_session); if (false == storage_session->storage_success) { storage_session_free(storage_session); return; } list_for_each_entry_safe(session, nsession, &storage_server->stream_session, list) { if (!strncmp(session->dev_id, storage_session->dev_id, LEN_MAX_ID) && !session->uploading_flag) { if (!strncmp(session->stream_path, storage_session->stream_path, LEN_MAX_PATH)) memset(session->stream_path, 0, LEN_MAX_PATH);//if old session's path is the same as new, do not delete file storage_session_free(session); } } if (get_dev_info(storage_server->worker_ctx->top_ctx, storage_session->dev_id, NULL)) { list_add_tail(&storage_session->list, &storage_server->stream_session); storage_update_list(storage_server, STORAGE_STREAMING); } else { //if device not exist, free session storage_session_free(storage_session); } } else { MYDEBUG("storage snapshot session = %p\n", storage_session); if (false == storage_session->storage_success) { storage_session_free(storage_session); return; } list_for_each_entry_safe(session, nsession, &storage_server->snapshot_session, list) { if (!strncmp(session->dev_id, storage_session->dev_id, LEN_MAX_ID) && !session->uploading_flag) { if (!strncmp(session->snapshot_path, storage_session->snapshot_path, LEN_MAX_PATH)) memset(session->snapshot_path, 0, LEN_MAX_PATH); storage_session_free(session); } } if (get_dev_info(storage_server->worker_ctx->top_ctx, storage_session->dev_id, NULL)) { list_add_tail(&storage_session->list, &storage_server->snapshot_session); storage_update_list(storage_server, STORAGE_SNAPSHOT); } else { //if device not exist, free session storage_session_free(storage_session); } } return; } bool storage_session_add_fixed_header(STORAGE_SESSION *storage_session) { struct tpsocket_buf *buf; if (!storage_session) { DBG_ERR("arg NULL\n"); return false; } /* add */ buf = tpbuf_snprintf(512, "%x\r\n" "--data-boundary--\r\n" "Content-Length: 218\r\n" "Content-Type: text/http-header\r\n" "\r\n" "HTTP/1.0 200 OK\r\n" "Content-Type: multipart/x-mixed-replace;boundary=data-boundary--\r\n" "X-Encrypt-Type: PLAIN\r\n" "Pragma: no-cache\r\n" "Cache-Control: no-cache\r\n" "Content-Length: -1\r\n" "Transfer-Encoding: chunked\r\n" "Connection: close\r\n\r\n" "\r\n", 292); if (buf) { list_add_tail(&buf->list, &storage_session->headers); } return true; } bool storage_stream_consumer_post(STORAGE_SESSION *storage_session) { struct list_head head; struct tpsocket_buf *buf; DEV_INFO *dev_info; char *request = NULL; if (!storage_session) { DBG_ERR("arg NULL\n"); return false; } dev_info = get_dev_info(storage_session->storage_server->worker_ctx->top_ctx, storage_session->dev_id, NULL); if (!dev_info) { DBG_ERR("get dev info failed\n"); return false; } INIT_LIST_HEAD(&head); char url[256] = {0}; request = strstr(dev_info->relay_storage_url, "/v1"); snprintf(url, 256, "%sactivity?deviceid=%s" "&eventid=%s" "&type=mixed" "&resolution=HD", request, storage_session->dev_id, storage_session->event_id); //MYDEBUG("storage token:%s\n", storage_session->xtoken); //MYDEBUG("storage cookie:%s\n", storage_session->cookie); buf = tpbuf_snprintf(1024, "POST %s HTTP/1.1\r\n" "User-Agent: %s/%s %s\r\n" // MODEL/FW_VERSION PROGRAM_NAME/PROGRAM_VERSION "Host: %s\r\n" "Transfer-Encoding: chunked\r\n" //http chunked transfer encoding "Content-Type: multipart/x-mixed-replace;boundary=%s\r\n" "X-token: %s\r\n" // X-token "X-Audio-Codec: %s\r\n" "Cookie: %s\r\n" "\r\n", url, dev_info->dev_model?dev_info->dev_model:"*", dev_info->sw_ver?dev_info->sw_ver:"*", THIS_PROCESS, storage_session->host, "data-boundary--", storage_session->xtoken, dev_info->audio_fmt, storage_session->cookie); list_add_tail(&buf->list, &head); /* header */ list_splice_tail_init(&storage_session->headers, &head); /* ready to write */ debug_show_tpbuf_list(&head, "STORAGE STREAM POST:", 3); if (false == storage_session_write_list_force(storage_session, &head, false)) { DBG_ERR("storage_session_write_list_force error\n"); tpsocket_free_buf(&head, NULL, 0); return false; } return true; } bool storage_snapshot_consumer_post(STORAGE_SESSION *storage_session) { struct list_head head; struct tpsocket_buf *buf; DEV_INFO *dev_info; char *request = NULL; if (!storage_session) { DBG_ERR("arg NULL\n"); return false; } INIT_LIST_HEAD(&head); dev_info = get_dev_info(storage_session->storage_server->worker_ctx->top_ctx, storage_session->dev_id, NULL); if (!dev_info) { DBG_ERR("get dev info failed\n"); return false; } /* add POST header */ char url[256] = {0}; int sub_header_len; char sub_header[512] = {0}; request = strstr(dev_info->storage_url, "/v1"); snprintf(url, 256, "%sdevice/%s/activity/%s/snapshot", request, storage_session->dev_id, storage_session->event_id); sub_header_len = snprintf(sub_header, 512, "--%s\r\n" "Content-Disposition: form-data;name=\"snapshot\";filename=\"example.jpg\"\r\n" "Content-Type: image/jpeg\r\n\r\n", SNAPSHOT_FILE_BOUNDARY); int content_len = sub_header_len+storage_session->content_len+strlen("\r\n")+storage_session->region_buf_len+ strlen("--")+strlen(SNAPSHOT_FILE_BOUNDARY)+strlen("--"); buf = tpbuf_snprintf(1024, "POST %s HTTP/1.1\r\n" "User-Agent: %s/%s %s\r\n" // MODEL/FW_VERSION PROGRAM_NAME/PROGRAM_VERSION "X-token: %s\r\n" // X-token "Host: %s\r\n" "Content-Length: %d\r\n" "Content-Type: multipart/form-data;boundary=%s\r\n" "\r\n" "%s",//sub_header url, dev_info->dev_model?dev_info->dev_model:"*", dev_info->sw_ver?dev_info->sw_ver:"*", THIS_PROCESS, storage_session->xtoken, storage_session->host, content_len, SNAPSHOT_FILE_BOUNDARY, sub_header); list_add_tail(&buf->list, &head); debug_show_tpbuf_list(&head, "STORAGE SNAPSHOT POST:", 3); if (false == storage_session_write_list_force(storage_session, &head, false)) { DBG_ERR("storage_session_write_list_force error\n"); tpsocket_free_buf(&head, NULL, 0); return false; } return true; } bool storage_file_produce(STORAGE_SESSION *storage_session, struct list_head *buf) { if (!storage_session) { DBG_ERR("arg NULL\n"); return false; } if (!storage_session->sock) { DBG_ERR("%p arg NULL, file = %p\n", storage_session, storage_session->file); return false; } if (tpsocket_writable(storage_session->sock)) { if (!list_empty(buf) && storage_session->chunked && !tpsocket_chunk_encode(buf)) { tpsocket_free_buf(buf, "PRODUCE", 0); return false; } storage_session_write_list_force(storage_session, buf, true); } return true; } bool storage_read_file(struct tpsocket_handler*handler, struct list_head*buf, int event) { STORAGE_SESSION *storage_session = handler->priv; //MYDEBUG("storage read file event = %s, sock = %p, consumer = %p\n", tpsocket_event_name(event), sock, storage_session); switch(event) { case TPSOCKET_EVENT_CONNECTED: break; case TPSOCKET_EVENT_REQ_HEAD: break; case TPSOCKET_EVENT_RSP_HEAD: break; case TPSOCKET_EVENT_UPGRADE: break; case TPSOCKET_EVENT_SUB_HEAD: case TPSOCKET_EVENT_STREAM: case TPSOCKET_EVENT_MESSAGE: if (false == storage_file_produce(storage_session, buf)) { return false; } goto out; //break; case TPSOCKET_EVENT_RESET: break; case TPSOCKET_EVENT_CLOSED: if (storage_session) { storage_session->file = NULL; if (storage_session->sock) { if (!list_empty(buf)) { if (storage_session->chunked) { tpsocket_chunk_encode(buf); tpsocket_write_list_force(storage_session->sock, buf, true); } } if (STORAGE_STREAMING == storage_session->storage_type) { storage_session_stream_add_tail(storage_session); } else { storage_session_snapshot_add_tail(storage_session); } } } break; case TPSOCKET_EVENT_ERROR: default: break; } tpsocket_free_buf(buf, tpsocket_event_name(event), 0); out: return true; } bool storage_start_read(STORAGE_SESSION *storage_session) { if (!storage_session) { DBG_ERR("arg NULL\n"); return false; } struct tpsocket_handler client = { .cb = storage_read_file, .flowcontrol = 10*1024, .priv = storage_session, .read_buf_max = STORAGE_MEMORY_CACHE_LIMIT, }; if (STORAGE_STREAMING == storage_session->storage_type) { storage_session->file = tpsocket_new(NULL, "stream", NULL, storage_session->stream_path, TPSOCKET_TYPE_FILE, &client); if (!storage_session->file) { DBG_ERR("open %s failed\n", storage_session->stream_path); return false; } } else { storage_session->file = tpsocket_new(NULL, "read", NULL, storage_session->snapshot_path, TPSOCKET_TYPE_FILE, &client); if (!storage_session->file) { DBG_ERR("open %s failed\n", storage_session->snapshot_path); return false; } } DBG_DBG("session = %p, sock = %p, open file = %p\n", storage_session, storage_session->sock, storage_session->file); return true; } bool tpsocket_event_storage_stream_to_cloud(struct tpsocket_handler *handler, struct list_head *buf, int event) { //debug_show_tpbuf_list(buf, "TEST", 3); struct tpsocket_fd *sock = container_of(handler, struct tpsocket_fd, handler); STORAGE_SESSION *storage_session = handler->priv; int err_code = 0; if (event != TPSOCKET_EVENT_WRITABLE) { MYDEBUG("storage stream to cloud event = %s, sock = %p, session = %p\n", tpsocket_event_name(event), sock, storage_session); if (storage_session) { DBG_DBG("Device Id = %s, session sock = %p\n", storage_session->dev_id, storage_session->sock); } } switch(event) { case TPSOCKET_EVENT_LISTEN: break; case TPSOCKET_EVENT_SHUTDOWN: break; case TPSOCKET_EVENT_ACCEPT: break; case TPSOCKET_EVENT_CONNECTED: MYDEBUG("STORAGESTREAM2CLOUD: %s:%s Connected\n", sock->addr, sock->port); if (false == storage_stream_consumer_post(storage_session)) return false; if (false == storage_start_read(storage_session)) { DBG_ERR("read stream file failed\n"); return false; } break; case TPSOCKET_EVENT_REQ_HEAD: break; case TPSOCKET_EVENT_RSP_HEAD: break; case TPSOCKET_EVENT_SUB_HEAD: break; case TPSOCKET_EVENT_UPGRADE: break; case TPSOCKET_EVENT_WRITABLE: if (storage_session->file && !list_empty(&(storage_session->file->parser.buf))) { if (storage_session->chunked && !tpsocket_chunk_encode(&(storage_session->file->parser.buf))) { tpsocket_free_buf(&(storage_session->file->parser.buf), tpsocket_event_name(event), 0); break; } storage_session_write_list_force(storage_session, &(storage_session->file->parser.buf), true); storage_session->file->read_buf_length = 0; } break; case TPSOCKET_EVENT_STREAM: return true; case TPSOCKET_EVENT_MESSAGE: err_code = common_check_error_code(buf); if (!err_code) { DBG_DBG("storage stream push success\n"); storage_session->post_success = 1; #ifndef TAPO_CAMERA } else if (err_code == -98400) { //If the recording/relay server finds out that the device is not eligible for cloud storage, // it returns an error code of -98400 upon which the firmware updates the cloud storage feature of that device. DEV_INFO *dev_info = get_dev_info(storage_session->storage_server->worker_ctx->top_ctx, storage_session->dev_id, NULL); if (dev_info) { dev_info->cloud_storage = false; } // mark as success here to avoid retrying. storage_session->post_success = 1; #endif } tpsocket_free_buf(buf, tpsocket_event_name(event), 0); common_tpsocket_close_immediately(sock); break; case TPSOCKET_EVENT_RESET: break; case TPSOCKET_EVENT_KEEPALIVE: common_tpsocket_close_immediately(sock); break; case TPSOCKET_EVENT_CLOSED: if (storage_session) { tpsocket_unbind(sock, &storage_session->sock); uloop_timeout_cancel(&storage_session->reupload_tmo); tpsocket_free2(&storage_session->file, storage_session); if (storage_session->post_success) { storage_session->stream_send_to_cloud_flag = 0; } storage_session->uploading_flag = 0; storage_session_set_push_status(storage_session, 0); /* handle timeout immediately */ storage_server_timeout_handle_immediately(storage_session->storage_server); } break; case TPSOCKET_EVENT_ERROR: default: break; } tpsocket_free_buf(buf, tpsocket_event_name(event), 0); return true; } bool tpsocket_event_storage_snapshot_to_cloud(struct tpsocket_handler *handler, struct list_head *buf, int event) { //debug_show_tpbuf_list(buf, "TEST", 3); struct tpsocket_fd *sock = container_of(handler, struct tpsocket_fd, handler); STORAGE_SESSION *storage_session = handler->priv; if (event != TPSOCKET_EVENT_WRITABLE) { MYDEBUG("storage snapshot to cloud event = %s, sock = %p, session = %p\n", tpsocket_event_name(event), sock, storage_session); if (storage_session) { DBG_DBG("Device Id = %s, session sock = %p\n", storage_session->dev_id, storage_session->sock); } } switch(event) { case TPSOCKET_EVENT_LISTEN: break; case TPSOCKET_EVENT_SHUTDOWN: break; case TPSOCKET_EVENT_ACCEPT: break; case TPSOCKET_EVENT_CONNECTED: MYDEBUG("STORAGESNAPSHOT2CLOUD: %s:%s Connected\n", sock->addr, sock->port); if (false == storage_snapshot_consumer_post(storage_session)) return false; if (false == storage_start_read(storage_session)) { DBG_ERR("read snapshot file failed\n"); return false; } break; case TPSOCKET_EVENT_REQ_HEAD: break; case TPSOCKET_EVENT_RSP_HEAD: break; case TPSOCKET_EVENT_SUB_HEAD: break; case TPSOCKET_EVENT_UPGRADE: break; case TPSOCKET_EVENT_WRITABLE: if (storage_session->file && !list_empty(&(storage_session->file->parser.buf))) { if (storage_session->chunked && !tpsocket_chunk_encode(&(storage_session->file->parser.buf))) { tpsocket_free_buf(&(storage_session->file->parser.buf), tpsocket_event_name(event), 0); break; } storage_session_write_list_force(storage_session, &(storage_session->file->parser.buf), true); storage_session->file->read_buf_length = 0; } break; case TPSOCKET_EVENT_STREAM: return true; case TPSOCKET_EVENT_MESSAGE: if (!common_check_error_code(buf)) { DBG_DBG("storage snapshot push success\n"); storage_session->post_success = 1; } tpsocket_free_buf(buf, tpsocket_event_name(event), 0); common_tpsocket_close_immediately(sock); break; case TPSOCKET_EVENT_RESET: break; case TPSOCKET_EVENT_KEEPALIVE: common_tpsocket_close_immediately(sock); break; case TPSOCKET_EVENT_CLOSED: if (storage_session) { tpsocket_unbind(sock, &storage_session->sock); uloop_timeout_cancel(&storage_session->reupload_tmo); tpsocket_free2(&storage_session->file, storage_session); if (storage_session->post_success) { storage_session->snapshot_send_to_cloud_flag = 0; //storage_session_free(storage_session); } else { storage_session->retry_count++; //list_add_tail(&storage_session->list, &storage_session->storage_server->snapshot_session); } storage_session->uploading_flag = 0; storage_session_set_push_status(storage_session, 0); /* handle timeout immediately */ storage_server_timeout_handle_immediately(storage_session->storage_server); } break; case TPSOCKET_EVENT_ERROR: default: break; } tpsocket_free_buf(buf, tpsocket_event_name(event), 0); return true; } bool storage_stream_upload(STORAGE_SESSION *storage_session) { DEV_INFO *dev_info = NULL; STORAGE_SERVER *storage_server; if (!storage_session) { DBG_ERR("arg NULL\n"); return false; } if (storage_session->sock) { DBG_DBG("sock exist\n"); return true; } storage_server = storage_session->storage_server; uloop_timeout_set(&storage_session->reupload_tmo, storage_session->reupload_idle_time); dev_info = get_dev_info(storage_server->worker_ctx->top_ctx, storage_session->dev_id, NULL); if (!dev_info) { DBG_ERR("Not find device\n"); return false; } /* create socket */ struct tpsocket_handler storage_stream_to_cloud = { .cb = tpsocket_event_storage_stream_to_cloud, .cer = MEDIACENTER_CERTFILE, .write_buf_max = STORAGE_MEMORY_CACHE_LIMIT, }; storage_session->retry_count++; if ((storage_session->sock = tpsocket_from_url(dev_info->relay_storage_url, &storage_stream_to_cloud))) { //if (storage_session->sock = tpsocket_from_url("http://192.168.137.103:8010", &storage_stream_to_cloud)) { DBG_DBG("Create session sock = %p, session = %p\n", storage_session->sock, storage_session); storage_session->sock->handler.priv = storage_session; storage_session->uploading_flag = 1; storage_session_set_push_status(storage_session, 1); } return true; } void storage_set_iot_info(void *arg, const char *host, const char *cookie, const char *token, const char *event_id) { STORAGE_SESSION *storage_session; #ifdef TAPO_CAMERA if (!arg || !host || !token || !event_id) { #else if (!arg || !host || !cookie || !token || !event_id) { #endif DBG_ERR("arg NULL\n"); return; } storage_session = (STORAGE_SESSION*)arg; snprintf(storage_session->host, LEN_MAX_HOST, "%s", host); snprintf(storage_session->cookie, LEN_MAX_COOKIE, "%s", cookie); snprintf(storage_session->xtoken, LEN_MAX_TOKEN, "%s", token); snprintf(storage_session->event_id, LEN_MAX_EVENT_ID, "%s", event_id); MYDEBUG("host: %s\n", storage_session->host); //MYDEBUG("cookie: %s\n", storage_session->cookie); //MYDEBUG("xtoken: %s\n", storage_session->xtoken); MYDEBUG("event_id: %s\n", storage_session->event_id); return; } void storage_get_iot_info_cb(void *priv, void *iot_info, char *host, char *cookie, char *token, char *event_id, int err_code) { STORAGE_SESSION *storage_session; if (!priv) { DBG_ERR("arg NULL\n"); return; } storage_session = (STORAGE_SESSION*)priv; if (err_code) { DBG_ERR("storage get iot info failed\n"); goto out; } if (!host || !cookie || !token || !event_id) { DBG_ERR("storage get iot info param error\n"); goto out; } storage_set_iot_info(storage_session, host, cookie, token, event_id); MYDEBUG("Have got iot info, reupload now\n"); if (STORAGE_STREAMING == storage_session->storage_type) { storage_stream_upload(storage_session); return; } out: storage_session->retry_count++; return; } int storage_stream_reupload(STORAGE_SESSION *storage_session) { IOT_INFO *iot_info; if (!storage_session) { DBG_ERR("arg NULL\n"); return -1; } if (storage_session->event_id[0]) { MYDEBUG("Have got iot info, reupload now\n"); if (false == storage_stream_upload(storage_session)) { storage_session->stream_send_to_cloud_flag = 0; } } else { //find event id iot_info = iot_info_find(storage_session->storage_server->worker_ctx->iot_info_server, storage_session->dev_id , storage_session->count_id); if (iot_info) { if (iot_info->ready) { #ifdef TAPO_CAMERA storage_get_iot_info_cb((void*)storage_session, NULL, iot_info->host, iot_info->cookie, iot_info->xtoken, iot_info->alarm_id, 0); #else storage_get_iot_info_cb((void*)storage_session, NULL, iot_info->host, iot_info->cookie, iot_info->token, iot_info->event_id, 0); #endif if (IOT_INFO_CONSUMER_NUM == iot_info->consumer_used_count) { iot_info_free(iot_info); } } else { storage_session->retry_count++; } } else { storage_session->stream_send_to_cloud_flag = 0; } } return 0; } void storage_force_delete_session(STORAGE_SERVER *storage_server) { struct statfs diskInfo; STORAGE_SESSION *stream_session, *nstream_session; int force = 0; if (!storage_server) { DBG_ERR("arg NULL\n"); return; } retry: if (force++ < 2 && !statfs(STORAGE_ROOT_PATH, &diskInfo)) { int free_size = (diskInfo.f_bsize * diskInfo.f_bfree) >> 20; if (free_size < 20) { MYDEBUG("FREE MEMORY %u MB!\n", free_size); if (free_size < 8) { list_for_each_entry_safe(stream_session, nstream_session, &storage_server->stream_session, list) { if (!stream_session->iot_consumer) { if ((force == 1 && stream_session->delete_flag) || (force == 2 && !stream_session->uploading_flag)) { storage_session_free(stream_session); } } } goto retry; } } } } void storage_check_list_to_upload(STORAGE_SERVER *storage_server) { STORAGE_SESSION *stream_session, *nstream_session; int ret = 0; if (!storage_server) { DBG_ERR("arg NULL\n"); return; } list_for_each_entry_safe(stream_session, nstream_session, &storage_server->stream_session, list) { if (!stream_session->iot_consumer) {//make sure alarm push finished //MYDEBUG("find storage stream session = %p\n", stream_session); if (stream_session->uploading_flag) { MYDEBUG("stream session %p uploading push busy ...\n", stream_session); break; } ret = storage_session_get_push_status(stream_session); if (1 == ret) { MYDEBUG("this stream session %p is ready, but other session of the same device push busy ...\n", stream_session); break; } else if (-1 == ret) { MYDEBUG("device not found\n"); break; } if (stream_session->stream_send_to_cloud_flag && (stream_session->retry_count < 3)) { MYDEBUG("stream session %p do upload!\n", stream_session); storage_stream_reupload(stream_session); } else { //DBG_DBG("stream session %p can be deleted\n", stream_session); stream_session->delete_flag = true; } } else { MYDEBUG("waitting iot session %p closed\n", stream_session->iot_consumer); } } } void storage_server_timeout_handle_immediately(STORAGE_SERVER *storage_server) { MYDEBUG("storage_server_timeout_handle_immediately ...\n"); if (!storage_server) { DBG_ERR("arg NULL\n"); return; } uloop_timeout_set(&storage_server->tmo, 100); } void storage_server_timeout_cb(struct uloop_timeout *tmo) { //MYDEBUG("storage server timeout cb ...\n"); STORAGE_SERVER *storage_server = container_of(tmo, STORAGE_SERVER, tmo); if (!storage_server) { DBG_ERR("storage_server NULL\n"); return; } storage_force_delete_session(storage_server); storage_check_list_to_upload(storage_server); uloop_timeout_set(tmo, 10*1000); } void storage_session_set_send_flag(void *arg, int flag) { STORAGE_SESSION *storage_session = NULL; if (!arg) { DBG_ERR("arg NULL\n"); return; } storage_session = (STORAGE_SESSION*)arg; if (STORAGE_STREAMING == storage_session->storage_type) { storage_session->stream_send_to_cloud_flag = flag; } else { storage_session->snapshot_send_to_cloud_flag = flag; } return; } void storage_session_set_iot_consumer_null(void *arg) { STORAGE_SESSION *storage_session; if (!arg) { DBG_ERR("arg NULL\n"); return; } storage_session = (STORAGE_SESSION*)arg; storage_session->iot_consumer = NULL; storage_update_list(storage_session->storage_server, storage_session->storage_type); return; } int storage_delete_empty_dir(char *filedir) { int count = 0; DIR *dir = NULL; struct dirent *Dirent = NULL; //char cmd[128] = {0}; if(!filedir){ DBG_ERR("arg NULL\n"); return -1; } dir = opendir(filedir); if(dir == NULL){ DBG_NOTICE("opendir:%s error:%s\n", filedir, strerror(errno)); return -1; } while((Dirent = readdir(dir)) != NULL){ if(0 != strncmp(Dirent->d_name, ".", sizeof(".")) && 0 != strncmp(Dirent->d_name, "..", sizeof(".."))) { count++; } } closedir(dir); if(!count){ //memset(cmd, '\0', 128); //snprintf(cmd, 128, "rm -rf %s", filedir); //if (system(cmd) < 0) { if (tpcom_system("rm", ("-rf"), ("%s", filedir)) < 0) { DBG_ERR("remove:%s error:%s\n", filedir, strerror(errno)); return -1; } DBG_DBG("remove dir:%s ok\n", filedir); } else { DBG_DBG("has %d file in %s\n", count, filedir); } return 0; } void storage_delete_file(char *file) { char *pos; char dev_id[LEN_MAX_ID] = {0}; char count_id[LEN_MAX_ID] = {0}; char dir[LEN_MAX_PATH] = {0}; if (!file) { DBG_ERR("arg NULL\n"); return; } if (!file[0]) { DBG_DBG("No file to delete\n"); return; } pos = file+strlen(STORAGE_ROOT_PATH); DBG_DBG("pos = %s\n", pos); sscanf(pos, "/%[^/]/%[^/]/%*s", dev_id, count_id); DBG_DBG("dev_id = %s, count_id = %s\n", dev_id, count_id); /* delete file */ remove(file); /* delete count id dir */ memset(dir, 0, LEN_MAX_PATH); snprintf(dir, LEN_MAX_PATH, "%s/%s/%s", STORAGE_ROOT_PATH, dev_id, count_id); storage_delete_empty_dir(dir); /* delete device dir */ memset(dir, 0, LEN_MAX_PATH); snprintf(dir, LEN_MAX_PATH, "%s/%s", STORAGE_ROOT_PATH, dev_id); storage_delete_empty_dir(dir); } void storage_move_file(char *file) { char *pos; char cmd[512] = {0}; char dev_id[LEN_MAX_ID] = {0}; char count_id[LEN_MAX_ID] = {0}; char dir[LEN_MAX_PATH] = {0}; char count_path[LEN_MAX_PATH] = {0}; if (!file || !file[0]) { DBG_ERR("arg NULL\n"); return; } pos = file+strlen(STORAGE_ROOT_PATH); MYDEBUG("pos = %s\n", pos); sscanf(pos, "/%[^/]/%[^/]/%*s", dev_id, count_id); MYDEBUG("dev_id = %s, count_id = %s\n", dev_id, count_id); /* remove file */ snprintf(count_path, LEN_MAX_PATH, "%s/%s/%s/", NFS_ROOT, dev_id, count_id); if (access(count_path, F_OK)) { //snprintf(cmd, 512, "mkdir -p %s", count_path); //system(cmd); tpcom_system("mkdir", ("-p"), ("%s", count_path)); } memset(cmd, 0, 512); snprintf(cmd, 512, "mv %s %s", file, count_path); DEBUG("cmd: %s\n", cmd); //system(cmd); tpcom_system("mv", (file), ("%s", count_path)); if (!access(file, F_OK)) { DBG_ERR("%s failed\n", cmd); remove(file); } /* delete count id dir */ memset(dir, 0, LEN_MAX_PATH); snprintf(dir, LEN_MAX_PATH, "%s/%s/%s", STORAGE_ROOT_PATH, dev_id, count_id); storage_delete_empty_dir(dir); /* delete device dir */ memset(dir, 0, LEN_MAX_PATH); snprintf(dir, LEN_MAX_PATH, "%s/%s", STORAGE_ROOT_PATH, dev_id); storage_delete_empty_dir(dir); } void storage_session_free(STORAGE_SESSION *storage_session) { MYDEBUG("STORAGE SESSION FREE %p\n", storage_session); if (!storage_session) { return; } list_del(&storage_session->list); uloop_timeout_cancel(&storage_session->reupload_tmo); tpsocket_free_buf(&storage_session->headers, NULL, 0); if (storage_session->sock) { storage_session_set_push_status(storage_session, 0); } tpsocket_free2(&storage_session->sock, storage_session); tpsocket_free2(&storage_session->file, storage_session); if (storage_session->iot_consumer) { alarm_consumer_set_storage_session_null(storage_session->iot_consumer); } /* telemetry */ storage_session_telemetry_failure_count(storage_session); /* delete file */ if (STORAGE_STREAMING == storage_session->storage_type) { if (STORAGE_DEBUG && !access("/nfsroot", F_OK)) { storage_move_file(storage_session->stream_path); } else { storage_delete_file(storage_session->stream_path); } } else { if (STORAGE_DEBUG && !access("/nfsroot", F_OK)) { storage_move_file(storage_session->snapshot_path); } else { storage_delete_file(storage_session->snapshot_path); } } free(storage_session); } bool tpsocket_event_consumer_to_storage(struct tpsocket_handler *handler, struct list_head *buf, int event) { struct tpsocket_fd *sock = container_of(handler, struct tpsocket_fd, handler); STORAGE_SESSION *storage_session = (STORAGE_SESSION*)handler->priv; if (STORAGE_SNAPSHOT == storage_session->storage_type) { MYDEBUG("storage snpashot cb: sock=%p, event=%d\n", sock, event); } switch(event) { case TPSOCKET_EVENT_CONNECTED: break; case TPSOCKET_EVENT_REQ_HEAD: break; case TPSOCKET_EVENT_RSP_HEAD: break; case TPSOCKET_EVENT_SUB_HEAD: break; case TPSOCKET_EVENT_UPGRADE: break; case TPSOCKET_EVENT_MESSAGE: break; case TPSOCKET_EVENT_STREAM: break; case TPSOCKET_EVENT_RESET: break; case TPSOCKET_EVENT_CLOSED: if (storage_session) { storage_session->file = NULL; list_del_init(&storage_session->list); storage_session_add_session(storage_session); } break; case TPSOCKET_EVENT_ERROR: MYDEBUG("tpsocket_event_consumer_to_storage ERROR %p\n", storage_session); storage_session->storage_success = false; default: break; } tpsocket_free_buf(buf, tpsocket_event_name(event), 0); return true; } STORAGE_SESSION *storage_session_new(char *path, STORAGE_SERVER *storage_server) { STORAGE_SESSION *storage_session; if (!path || ! storage_server) { DBG_ERR("arg NULL\n"); return NULL; } storage_session = (STORAGE_SESSION*)malloc(sizeof(*storage_session)); if (!storage_session) { DBG_ERR("malloc failed\n"); return NULL; } memset(storage_session, 0, sizeof(*storage_session)); INIT_LIST_HEAD(&storage_session->list); INIT_LIST_HEAD(&storage_session->headers); storage_session->storage_server = storage_server; storage_session->reupload_idle_time = 10000; storage_session->reupload_tmo.cb = storage_session_reupload_timeout; storage_session->storage_success = true; storage_session->delete_flag = false; /* create socket */ struct tpsocket_handler client = { .cb = tpsocket_event_consumer_to_storage, .flowcontrol = 500000, .priv = storage_session }; storage_session->file = tpsocket_new(NULL, "write", NULL, path, TPSOCKET_TYPE_FILE, &client); if (!(storage_session->file)) { DBG_ERR("tpsocket_new failed\n"); free(storage_session); return NULL; } //consumer->chunked = 0; //consumer->store = 1; return storage_session; } int storage_find_file_in_list(char *dev_id, char *timestamp_str, struct list_head *head) { STORAGE_SESSION *session; int timestamp; if (!dev_id || !timestamp_str || !head) { DBG_ERR("arg NULL\n"); return -1; } timestamp = atoi(timestamp_str); list_for_each_entry(session, head, list) { if (!strncmp(session->dev_id, dev_id, LEN_MAX_ID) && (session->event_timestamp == timestamp)) { return 0; } } return -1; } void storage_check_file(STORAGE_SERVER *storage_server) { if (!storage_server) { DBG_ERR("arg NULL\n"); return; } DIR *dir = NULL, *dev_dir = NULL; struct dirent *root_dirent = NULL, *dev_dirent = NULL; char dev_id[LEN_MAX_ID] = {0}, timestamp[LEN_MAX_ID] = {0}; char dev_path[LEN_MAX_PATH] = {0}, event_path[LEN_MAX_PATH] = {0}, file_path[LEN_MAX_PATH] = {0}; dir = opendir(STORAGE_ROOT_PATH); if(dir == NULL){ DBG_NOTICE("opendir:%s error:%s\n", STORAGE_ROOT_PATH, strerror(errno)); return; } while((root_dirent = readdir(dir)) != NULL){ /* dev */ if(0 == strncmp(root_dirent->d_name, ".", sizeof(".")) || 0 == strncmp(root_dirent->d_name, "..", sizeof(".."))) { continue; } memset(dev_path, 0, LEN_MAX_PATH); snprintf(dev_path, LEN_MAX_PATH, "%s/%s", STORAGE_ROOT_PATH, root_dirent->d_name); dev_dir = opendir(dev_path); if(dev_dir == NULL){ DBG_NOTICE("opendir:%s error:%s\n", dev_path, strerror(errno)); continue; } memset(dev_id, 0, LEN_MAX_ID); snprintf(dev_id, LEN_MAX_ID, "%s", root_dirent->d_name); while ((dev_dirent = readdir(dev_dir)) != NULL) { /* event */ if(0 == strncmp(dev_dirent->d_name, ".", sizeof(".")) || 0 == strncmp(dev_dirent->d_name, "..", sizeof(".."))) { continue; } memset(timestamp, 0, LEN_MAX_ID); snprintf(timestamp, LEN_MAX_ID, "%s", dev_dirent->d_name); memset(event_path, 0, LEN_MAX_PATH); snprintf(event_path, LEN_MAX_PATH, "%s/%s/%s", STORAGE_ROOT_PATH, dev_id, timestamp); memset(file_path, 0, LEN_MAX_PATH); snprintf(file_path, LEN_MAX_PATH, "%s/%s/%s/%s", STORAGE_ROOT_PATH, dev_id, timestamp, STORAGE_STREAMING_FILE); if (!access(file_path, F_OK)) { DBG_NOTICE("streaming file: %s\n", file_path); if (storage_find_file_in_list(dev_id, timestamp, &storage_server->stream_session)) { storage_delete_file(file_path); } } memset(file_path, 0, LEN_MAX_PATH); snprintf(file_path, LEN_MAX_PATH, "%s/%s/%s/%s", STORAGE_ROOT_PATH, dev_id, timestamp, STORAGE_SNAPSHOT_FILE); if (!access(file_path, F_OK)) { DBG_NOTICE("snapshot file: %s\n", file_path); if (storage_find_file_in_list(dev_id, timestamp, &storage_server->snapshot_session)) { storage_delete_file(file_path); } } storage_delete_empty_dir(event_path); } closedir(dev_dir); } closedir(dir); return; } void storage_get_iot_info(STORAGE_SESSION *session, struct list_head *iot_info_head) { IOT_INFO *iot_info; if (!session || !iot_info_head) { DBG_ERR("arg NULL\n"); return; } list_for_each_entry(iot_info, iot_info_head, list) { if (!strncmp(session->dev_id, iot_info->dev_id, LEN_MAX_ID) && (session->count_id == iot_info->count_id)) { #ifdef TAPO_CAMERA storage_set_iot_info(session, iot_info->host, iot_info->cookie, iot_info->xtoken, iot_info->alarm_id); #else storage_set_iot_info(session, iot_info->host, iot_info->cookie, iot_info->token, iot_info->event_id); #endif break; } } } bool storage_check_version() { FILE *version_fd; char version_path[LEN_MAX_PATH] = {0}, version[4] = {0}; //char cmd[128] = {0}; snprintf(version_path, LEN_MAX_PATH, "%s/%s", STORAGE_ROOT_PATH, STORAGE_VERSION_FILE); if (access(version_path, F_OK)) { DBG_NOTICE("storage version file not exist\n"); goto failed; } if (!(version_fd = fopen(version_path, "r"))) { DBG_NOTICE("open storage version file failed\n"); goto failed; } if (1 != fread(version, 4, 1, version_fd)) { DBG_NOTICE("read storage version file error\n"); fclose(version_fd); goto failed; } fclose(version_fd); if (strncmp(version, STORAGE_VERSION, 4)) { DBG_NOTICE("old version\n"); goto failed; } return true; failed: /* delete storage */ //snprintf(cmd, 128, "rm -rf %s/*", STORAGE_ROOT_PATH); //system(cmd); tpcom_system("rm", ("-rf"), ("%s", STORAGE_ROOT_PATH)); tpcom_system("mkdir", ("-p"), ("%s", STORAGE_ROOT_PATH)); /* create version */ snprintf(version, 4, "%s", STORAGE_VERSION); version_fd = fopen(version_path, "w"); if (version_fd) { fwrite(version, 4, 1, version_fd); fclose(version_fd); } return false; } void storage_file_list_init(STORAGE_SERVER *storage_server) { FILE *iot_info_fd, *stream_fd, *snapshot_fd; char iot_info_path[LEN_MAX_PATH] = {0}, stream_path[LEN_MAX_PATH] = {0}, snapshot_path[LEN_MAX_PATH] = {0}; struct list_head list; IOT_INFO *iot_info, *niot_info; if (!storage_server) { DBG_ERR("arg NULL\n"); return; } /* check version */ if (false == storage_check_version()) { return; } /* iot info */ INIT_LIST_HEAD(&list); snprintf(iot_info_path, LEN_MAX_PATH, "%s/%s", STORAGE_ROOT_PATH, STORAGE_IOT_INFO_LIST); iot_info_fd = fopen(iot_info_path, "r"); if (iot_info_fd) { while (1) { iot_info = malloc(sizeof(IOT_INFO)); if (fread(iot_info, sizeof(IOT_INFO), 1, iot_info_fd) <= 0) { free(iot_info); break; } list_add_tail(&iot_info->list, &list); } fclose(iot_info_fd); } /* stream session */ snprintf(stream_path, LEN_MAX_PATH, "%s/%s", STORAGE_ROOT_PATH, STORAGE_STREAMING_LIST); stream_fd = fopen(stream_path, "r"); if (stream_fd) { while (1) { STORAGE_SESSION *stream_session = malloc(sizeof(STORAGE_SESSION)); if (fread(stream_session, sizeof(STORAGE_SESSION), 1, stream_fd) <= 0) { free(stream_session); break; } DBG_NOTICE("dev_id: %s, count_id: %d\n", stream_session->dev_id, stream_session->count_id); INIT_LIST_HEAD(&stream_session->list); INIT_LIST_HEAD(&stream_session->headers); stream_session->sock = NULL; stream_session->file = NULL; stream_session->uploading_flag = 0; stream_session->producer = NULL; stream_session->iot_consumer = NULL; stream_session->storage_server = storage_server; storage_session_add_fixed_header(stream_session); memset(&stream_session->reupload_tmo, 0, sizeof(struct uloop_timeout)); list_add_tail(&stream_session->list, &storage_server->stream_session); storage_get_iot_info(stream_session, &list); } fclose(stream_fd); } /* snapshot session */ snprintf(snapshot_path, LEN_MAX_PATH, "%s/%s", STORAGE_ROOT_PATH, STORAGE_SNAPSHOT_LIST); snapshot_fd = fopen(snapshot_path, "r"); if (snapshot_fd) { while (1) { STORAGE_SESSION *snapshot_session = malloc(sizeof(STORAGE_SESSION)); if (fread(snapshot_session, sizeof(STORAGE_SESSION), 1, snapshot_fd) <= 0) { free(snapshot_session); break; } DBG_NOTICE("dev_id: %s, count_id: %d\n", snapshot_session->dev_id, snapshot_session->count_id); INIT_LIST_HEAD(&snapshot_session->list); INIT_LIST_HEAD(&snapshot_session->headers); snapshot_session->sock = NULL; snapshot_session->file = NULL; snapshot_session->uploading_flag = 0; snapshot_session->producer = NULL; snapshot_session->iot_consumer = NULL; snapshot_session->storage_server = storage_server; memset(&snapshot_session->reupload_tmo, 0, sizeof(struct uloop_timeout)); list_add_tail(&snapshot_session->list, &storage_server->snapshot_session); storage_get_iot_info(snapshot_session, &list); } fclose(snapshot_fd); } /* free & delete */ list_for_each_entry_safe(iot_info, niot_info, &list, list) { free(iot_info); } /* check file */ storage_check_file(storage_server); return; } void storage_server_free(STORAGE_SERVER *storage_server) { STORAGE_SESSION *storage_session, *nstorage_session; if (!storage_server) { return; } uloop_timeout_cancel(&storage_server->tmo); list_for_each_entry_safe(storage_session, nstorage_session, &storage_server->stream_session, list) { storage_session_free(storage_session); } list_for_each_entry_safe(storage_session, nstorage_session, &storage_server->snapshot_session, list) { storage_session_free(storage_session); } if (storage_server->worker_ctx) { storage_server->worker_ctx->storage_server = NULL; } list_del_init(&storage_server->list); free(storage_server); } int storage_server_init(WORKER_CTX *worker_ctx) { STORAGE_SERVER *storage_server; if (!worker_ctx) { DBG_ERR("worker ctx NULL\n"); return -1; } /* create */ storage_server = (STORAGE_SERVER*)malloc(sizeof(*storage_server)); if (!storage_server) { DBG_ERR("malloc failed\n"); return -1; } memset(storage_server, 0, sizeof(*storage_server)); storage_server->worker_ctx = worker_ctx; INIT_LIST_HEAD(&storage_server->list); INIT_LIST_HEAD(&storage_server->stream_session); INIT_LIST_HEAD(&storage_server->snapshot_session); //timer to re-upload storage_server->tmo.cb = storage_server_timeout_cb; uloop_timeout_set(&storage_server->tmo, 10*1000); /* set */ worker_ctx->storage_server = storage_server; /* file list init */ storage_file_list_init(storage_server); return 0; }
最新发布
09-23
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <sys/stat.h> #include <dirent.h> #include <errno.h> #define PORT 8080 // 使用8080端口避免权限问题 #define WEB_ROOT "./web" // 网页文件目录 #define BUFFER_SIZE 4096 // 缓冲区大小 #define MAX_CONNECTIONS 10 // 最大等待连接数 // 发送HTTP错误响应 void send_error(int client_sock, int status_code, const char* status_msg) { char response[1024]; int length = snprintf(response, sizeof(response), "HTTP/1.1 %d %s\r\n" "Content-Type: text/html\r\n" "Connection: close\r\n\r\n" "<html><body><h1>%d %s</h1><p>%s</p></body></html>", status_code, status_msg, status_code, status_msg, strerror(errno)); send(client_sock, response, length, 0); } // 获取文件内容类型 const char* get_content_type(const char* path) { // 获取文件扩展名 const char *ext = strrchr(path, '.'); if (!ext) return "text/plain"; // 常见文件类型映射 if (strcmp(ext, ".html") == 0) return "text/html"; if (strcmp(ext, ".htm") == 0) return "text/html"; if (strcmp(ext, ".css") == 0) return "text/css"; if (strcmp(ext, ".js") == 0) return "application/javascript"; if (strcmp(ext, ".json") == 0) return "application/json"; if (strcmp(ext, ".jpg") == 0) return "image/jpeg"; if (strcmp(ext, ".jpeg") == 0) return "image/jpeg"; if (strcmp(ext, ".png") == 0) return "image/png"; if (strcmp(ext, ".gif") == 0) return "image/gif"; if (strcmp(ext, ".ico") == 0) return "image/x-icon"; if (strcmp(ext, ".txt") == 0) return "text/plain"; return "application/octet-stream"; // 默认类型 } // 处理HTTP请求 void handle_request(int client_sock) { char buffer[BUFFER_SIZE]; // 读取客户端请求 ssize_t bytes_read = recv(client_sock, buffer, BUFFER_SIZE - 1, 0); if (bytes_read <= 0) { if (bytes_read == 0) { printf("客户端关闭了连接\n"); } else { perror("接收请求失败"); } return; } buffer[bytes_read] = '\0'; // 确保字符串结束 // 打印请求信息(用于调试) printf("------ 收到请求 ------\n%.*s\n----------------------\n", (int)bytes_read, buffer); // 解析请求行 (只处理GET请求) char method[16], path[256], protocol[16]; if (sscanf(buffer, "%15s %255s %15s", method, path, protocol) != 3) { send_error(client_sock, 400, "Bad Request"); return; } // 只支持GET方法 if (strcmp(method, "GET") != 0) { send_error(client_sock, 501, "Not Implemented"); return; } // 安全处理:防止路径遍历攻击 if (strstr(path, "..") != NULL) { send_error(client_sock, 403, "Forbidden"); return; } // 处理根路径请求 if (strcmp(path, "/") == 0) { strcpy(path, "/Index.html"); // 默认打开Index.html } // 构建实际文件路径 char file_path[512]; snprintf(file_path, sizeof(file_path), "%s%s", WEB_ROOT, path); printf("请求文件: %s\n", file_path); // 检查文件是否存在 struct stat file_stat; if (stat(file_path, &file_stat) < 0) { printf("文件不存在: %s (%s)\n", file_path, strerror(errno)); send_error(client_sock, 404, "Not Found"); return; } // 检查是否是普通文件 if (!S_ISREG(file_stat.st_mode)) { printf("不是普通文件: %s\n", file_path); send_error(client_sock, 403, "Forbidden"); return; } // 打开文件 FILE* file = fopen(file_path, "rb"); if (!file) { printf("无法打开文件: %s (%s)\n", file_path, strerror(errno)); send_error(client_sock, 500, "Internal Server Error"); return; } // 获取文件大小 long file_size = file_stat.st_size; // 获取内容类型 const char* content_type = get_content_type(file_path); printf("内容类型: %s, 文件大小: %ld 字节\n", content_type, file_size); // 发送HTTP响应头 char header[1024]; int header_length = snprintf(header, sizeof(header), "HTTP/1.1 200 OK\r\n" "Content-Type: %s\r\n" "Content-Length: %ld\r\n" "Connection: close\r\n\r\n", // 每次请求后关闭连接 content_type, file_size); if (send(client_sock, header, header_length, 0) != header_length) { perror("发送响应头失败"); fclose(file); return; } // 发送文件内容 char file_buffer[BUFFER_SIZE]; size_t bytes; long total_sent = 0; while ((bytes = fread(file_buffer, 1, sizeof(file_buffer), file)) > 0) { ssize_t sent = send(client_sock, file_buffer, bytes, 0); if (sent != bytes) { perror("发送文件内容失败"); break; } total_sent += sent; } fclose(file); printf("文件发送完成: %ld/%ld 字节\n", total_sent, file_size); } // 创建并配置服务器socket int create_server_socket() { // 创建socket int server_sock = socket(AF_INET, SOCK_STREAM, 0); if (server_sock < 0) { perror("创建socket失败"); exit(EXIT_FAILURE); } // 设置SO_REUSEADDR选项,避免"地址已在使用中"错误 int reuse = 1; if (setsockopt(server_sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0) { perror("设置SO_REUSEADDR失败"); close(server_sock); exit(EXIT_FAILURE); } // 配置服务器地址 struct sockaddr_in server_addr; memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(PORT); server_addr.sin_addr.s_addr = htonl(INADDR_ANY); // 绑定端口 if (bind(server_sock, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) { perror("绑定端口失败"); close(server_sock); exit(EXIT_FAILURE); } // 开始监听 if (listen(server_sock, MAX_CONNECTIONS) < 0) { perror("监听失败"); close(server_sock); exit(EXIT_FAILURE); } printf("服务器已启动,监听端口 %d\n", PORT); return server_sock; } // 打印目录结构 void print_directory_structure() { printf("网页目录结构 (%s):\n", WEB_ROOT); DIR *dir = opendir(WEB_ROOT); if (!dir) { perror("无法打开网页目录"); return; } struct dirent *entry; struct stat entry_stat; char full_path[512]; while ((entry = readdir(dir)) != NULL) { // 跳过 "." ".." if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) continue; // 构建完整路径 snprintf(full_path, sizeof(full_path), "%s/%s", WEB_ROOT, entry->d_name); // 获取文件信息 if (stat(full_path, &entry_stat) == 0) { if (S_ISREG(entry_stat.st_mode)) { printf(" - %s (文件, %ld 字节)\n", entry->d_name, entry_stat.st_size); } else if (S_ISDIR(entry_stat.st_mode)) { printf(" + %s/ (目录)\n", entry->d_name); } } } closedir(dir); printf("\n"); } int main() { // 创建服务器socket int server_sock = create_server_socket(); // 打印网页目录结构 print_directory_structure(); while (1) { printf("等待客户端连接...\n"); // 等待客户端连接 struct sockaddr_in client_addr; socklen_t client_len = sizeof(client_addr); int client_sock = accept(server_sock, (struct sockaddr*)&client_addr, &client_len); if (client_sock < 0) { perror("接受连接失败"); continue; } // 获取客户端IP char client_ip[INET_ADDRSTRLEN]; inet_ntop(AF_INET, &client_addr.sin_addr, client_ip, sizeof(client_ip)); printf("新客户端连接: %s\n", client_ip); // 处理请求 handle_request(client_sock); // 关闭客户端连接 close(client_sock); printf("客户端断开连接: %s\n\n", client_ip); } // 关闭服务器socket (实际上不会执行到这) close(server_sock); return 0; }帮我逐行解释这个代码
08-08
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/socket.h> #include <pthread.h> void error_handling(const char* msg) { perror(msg); exit(1); } void send_data(FILE* fp, const char* content_type, const char* file_name); void* request_handler(void* arg) { int clnt_sock = *(int*)arg; FILE* clnt_read = fdopen(clnt_sock, "r"); FILE* clnt_write = fdopen(dup(clnt_sock), "w"); char req_line[1024]; fgets(req_line, sizeof(req_line), clnt_read); char method[256], path[1024]; sscanf(req_line, "%s %s", method, path); if (strcasecmp(method, "GET") == 0) { char* file_path = path; if (strcmp(path, "/") == 0) { file_path = "/index.html"; } send_data(clnt_write, "text/html", file_path + 1); } fclose(clnt_read); fclose(clnt_write); free(arg); return NULL; } void send_data(FILE* fp, const char* content_type, const char* file_name) { FILE* file = fopen(file_name, "r"); if (file == NULL) { fprintf(fp, "HTTP/1.1 404 Not Found\r\n"); fprintf(fp, "Content-Type: text/plain\r\n\r\n"); fprintf(fp, "404 Not Found"); return; } fprintf(fp, "HTTP/1.1 200 OK\r\n"); fprintf(fp, "Content-Type: %s\r\n\r\n", content_type); char line[1024]; while (fgets(line, sizeof(line), file)) { fprintf(fp, "%s", line); } fclose(file); } int main(int argc, char* argv[]) { int serv_sock, clnt_sock; struct sockaddr_in serv_addr, clnt_addr; socklen_t clnt_addr_size; pthread_t thread_id; serv_sock = socket(PF_INET, SOCK_STREAM, 0); if (serv_sock == -1) error_handling("socket() error"); memset(&serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); serv_addr.sin_port = htons(8080); if (bind(serv_sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) == -1) error_handling("bind() error"); if (listen(serv_sock, 5) == -1) error_handling("listen() error"); while (1) { clnt_addr_size = sizeof(clnt_addr); clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_addr, &clnt_addr_size); int* sock_ptr = malloc(sizeof(int)); *sock_ptr = clnt_sock; pthread_create(&thread_id, NULL, request_handler, (void*)sock_ptr); pthread_detach(thread_id); } close(serv_sock); return 0; } 帮我逐行解释代码
08-08
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值