void Guest::Error(int ret, int code) { LOGD(DHTTP, "guest Error %s: ret:%d, code:%d, http_flag:%u\n", getsrc(nullptr), ret, code, http_flag); if((ret == READ_ERR || ret == SOCKET_ERR) && code == 0){ http_flag |= HTTP_CLIENT_CLOSE_F; deleteLater(NOERROR | DISCONNECT_FLAG); return; } if(Status_flags != GUEST_IDELE_F){ LOGE("Guest error %s: %d/%d/%u\n", getsrc(nullptr), ret, code, Status_flags); } deleteLater(ret); }
ssize_t Guest::DataProc(const void *buff, size_t size) { if (responser_ptr.expired() || (Status_flags & GUEST_ERROR_F)) { LOGE("(%s): connecting to host lost or error ocured\n", getsrc(nullptr)); deleteLater(PEER_LOST_ERR); return -1; } int len = responser_ptr.lock()->bufleft(responser_index); if (len <= 0) { LOGE("(%s): The host's buff is full\n", getsrc(nullptr)); rwer->delEvents(RW_EVENT::READ); return -1; } LOGD(DHTTP, "guest DataProc %s: send:%lu\n", getsrc(nullptr), Min(size, len)); responser_ptr.lock()->Send(buff, Min(size, len), responser_index); return Min(size, len); }
void shared_setsource(struct vir_region *vr, endpoint_t ep, struct vir_region *src_vr) { struct vmproc *vmp; struct vir_region *srcvr; int id = src_vr->id; vir_bytes vaddr = src_vr->vaddr; assert(vr->def_memtype == &mem_type_shared); if(!ep || !vaddr || !id) { printf("VM: shared_setsource: zero ep/vaddr/id - ignoring\n"); return; } vr->param.shared.ep = ep; vr->param.shared.vaddr = vaddr; vr->param.shared.id = id; if(getsrc(vr, &vmp, &srcvr) != OK) panic("initial getsrc failed"); assert(srcvr == src_vr); srcvr->remaps++; }
static int shared_pagefault(struct vmproc *vmp, struct vir_region *region, struct phys_region *ph, int write, vfs_callback_t cb, void *state, int statelen, int *io) { struct vir_region *src_region; struct vmproc *src_vmp; struct phys_region *pr; if(getsrc(region, &src_vmp, &src_region) != OK) { return EINVAL; } assert(ph->ph->phys == MAP_NONE); pb_free(ph->ph); if(!(pr = physblock_get(src_region, ph->offset))) { int r; if((r=map_pf(src_vmp, src_region, ph->offset, write, NULL, NULL, 0, io)) != OK) return r; if(!(pr = physblock_get(src_region, ph->offset))) { panic("missing region after pagefault handling"); } } pb_link(ph, pr->ph, ph->offset, region); return OK; }
void Guest::ReadHE(size_t len){ const char* data = rwer->rdata(); size_t consumed = 0; size_t ret = 0; while((ret = (this->*Http_Proc)(data+consumed, len-consumed))){ consumed += ret; } LOGD(DHTTP, "guest ReadHE %s: len:%zu, consumed:%zu\n", getsrc(nullptr), len, consumed); rwer->consume(data, consumed); }
static u32_t shared_regionid(struct vir_region *vr) { struct vir_region *src_region; struct vmproc *src_vmp; if(getsrc(vr, &src_vmp, &src_region) != OK) return 0; return src_region->id; }
static void shared_delete(struct vir_region *region) { struct vir_region *src_region; struct vmproc *src_vmp; if(getsrc(region, &src_vmp, &src_region) != OK) return; assert(src_region->remaps > 0); src_region->remaps--; }
static int shared_copy(struct vir_region *vr, struct vir_region *newvr) { struct vmproc *vmp; struct vir_region *srcvr; if(getsrc(vr, &vmp, &srcvr) != OK) panic("copy: original getsrc failed"); shared_setsource(newvr, vr->param.shared.ep, srcvr); return OK; }
Guest::Guest(int fd, const sockaddr_un *myaddr): Requester(myaddr) { rwer = new StreamRWer(fd, std::bind(&Guest::Error, this, _1, _2)); rwer->SetReadCB(std::bind(&Guest::ReadHE, this, _1)); rwer->SetWriteCB([this](size_t len){ LOGD(DHTTP, "guest writed %s: wlength:%zu, http_flag:%u\n", getsrc(nullptr), rwer->wlength(), http_flag); if(!responser_ptr.expired() && len){ responser_ptr.lock()->writedcb(responser_index); } if(rwer->wlength() == 0 && (http_flag & HTTP_SERVER_CLOSE_F)){ rwer->Shutdown(); } }); }
void Guest::EndProc() { LOGD(DHTTP, "guest EndProc %s: status:%u\n", getsrc(nullptr), Status_flags); rwer->addEvents(RW_EVENT::READ); if(!responser_ptr.expired()){ if(Status_flags == GUEST_IDELE_F){ }else if(Status_flags & GUEST_RES_COMPLETED){ Status_flags = GUEST_IDELE_F; }else{ Status_flags |= GUEST_REQ_COMPLETED; rwer->delEvents(RW_EVENT::READ); } responser_ptr.lock()->finish(NOERROR, responser_index); }else if((Status_flags & GUEST_ERROR_F) == 0){ Status_flags = GUEST_IDELE_F; } }
void Guest::ReqProc(HttpReqHeader* req) { LOGD(DHTTP, "guest ReqProc %s: Status:%u\n", getsrc(nullptr), Status_flags); assert((Status_flags & GUEST_CONNECT_F) == 0 && (Status_flags & GUEST_SEND_F) == 0); assert((Status_flags == GUEST_IDELE_F) || (Status_flags & GUEST_REQ_COMPLETED)); req->index = (void *)1; auto res_ptr = distribute(req, responser_ptr); if(!res_ptr.expired()){ if(req->ismethod("CONNECT")){ Status_flags |= GUEST_CONNECT_F; }else if(req->ismethod("SEND")){ Status_flags |= GUEST_SEND_F; } Status_flags |= GUEST_PROCESSING_F; Status_flags &= ~GUEST_RES_COMPLETED; void* res_index = res_ptr.lock()->request(req); if(!responser_ptr.expired() && (res_ptr.lock() != responser_ptr.lock() || res_index != responser_index)){ responser_ptr.lock()->finish(PEER_LOST_ERR, responser_index); } responser_ptr = res_ptr; responser_index = res_index; }else{ delete req; } }
Guest::Guest(int fd, const sockaddr_un *myaddr, SSL_CTX* ctx): Requester(myaddr) { rwer = new SslRWer(fd, ctx, std::bind(&Guest::Error, this, _1, _2), [this](const sockaddr_un&){ SslRWer* srwer = dynamic_cast<SslRWer*>(rwer); const unsigned char *data; unsigned int len; srwer->get_alpn(&data, &len); if ((data && strncasecmp((const char*)data, "h2", len) == 0)) { new Guest2(sourceip, sourceport, srwer); rwer = nullptr; Peer::deleteLater(PEER_LOST_ERR); } }); rwer->SetReadCB(std::bind(&Guest::ReadHE, this, _1)); rwer->SetWriteCB([this](size_t len){ LOGD(DHTTP, "guest WriteCB %s: wlength:%zu, http_flag:%u\n", getsrc(nullptr), rwer->wlength(), http_flag); if(!responser_ptr.expired() && len){ responser_ptr.lock()->writedcb(responser_index); } if(rwer->wlength() == 0 && (http_flag & HTTP_SERVER_CLOSE_F)){ rwer->Shutdown(); } }); }
void Guest::response(HttpResHeader* res) { assert((uint32_t)(long)res->index == 1); LOGD(DHTTP, "guest response %s: %s\n", getsrc(nullptr), res->status); if(Status_flags & GUEST_CONNECT_F){ if(memcmp(res->status, "200", 3) == 0){ strcpy(res->status, "200 Connection established"); res->del("Transfer-Encoding"); } }else if(Status_flags & GUEST_SEND_F){ //ignore response delete res; return; }else if(res->no_body()){ Status_flags |= GUEST_RES_COMPLETED; }else if(res->get("Transfer-Encoding")){ Status_flags |= GUEST_CHUNK_F; }else if(res->get("Content-Length") == nullptr) { Status_flags |= GUEST_NOLENGTH_F; } size_t len; char *buff=res->getstring(len); rwer->buffer_insert(rwer->buffer_end(), write_block{buff, len, 0}); delete res; }
}else if(res->get("Content-Length") == nullptr) { Status_flags |= GUEST_NOLENGTH_F; } size_t len; char *buff=res->getstring(len); rwer->buffer_insert(rwer->buffer_end(), write_block{buff, len, 0}); delete res; } int32_t Guest::bufleft(void*){ return 1024*1024 - rwer->wlength(); } void Guest::Send(void *buff, size_t size, __attribute__ ((unused)) void* index) { LOGD(DHTTP, "guest Send %s: size:%zu\n", getsrc(nullptr), size); assert((uint32_t)(long)index == 1); assert((http_flag & HTTP_SERVER_CLOSE_F) == 0); if(Status_flags & GUEST_CHUNK_F){ char chunkbuf[100]; int chunklen = snprintf(chunkbuf, sizeof(chunkbuf), "%x" CRLF, (uint32_t)size); buff = p_move(buff, -chunklen); memcpy(buff, chunkbuf, chunklen); rwer->buffer_insert(rwer->buffer_end(), write_block{buff, (size_t)chunklen+size, 0}); rwer->buffer_insert(rwer->buffer_end(), write_block{p_strdup(CRLF), strlen(CRLF), 0}); }else{ rwer->buffer_insert(rwer->buffer_end(), write_block{buff, size, 0}); } } void Guest::transfer(__attribute__ ((unused)) void* index, std::weak_ptr<Responser> res_ptr, void* res_index) {