void *_handle_peer_interconnect(void *arg) { assert(arg != NULL); LOG("[%d] 收到 rpc 客户端连接\n", self_index); st_netfd_t client = (st_netfd_t)arg; arg = NULL; // 握手 // rpc客户端连入后,会主动发来客户端自己的 index // 长度为 1 字节 char buf[4096]; ssize_t len; // 先只读取 1 字节的客户端握手头,表示客户端自己的 index if ((len = st_read(client, buf, 1, ST_UTIME_NO_TIMEOUT)) < 0) { ERR("[%d] failed to handshake from client #%d: %s\n", self_index, *buf, strerror(errno)); goto close_fd_and_quit; } else if (len == 0) { goto close_fd_and_quit; } uint8_t client_index = (uint8_t)buf[0]; LOG("[%d] 来自 rpc 客户端 #%d 的握手已经成功建立\n", self_index, client_index); // 如果 client_index 等于自己的 self_index,则这个有问题 if (client_index == self_index) { ERR("[%d] rpc client promet the same index with mine.\n", self_index); goto close_fd_and_quit; } // 将客户端 fd 放入属于它 index 的 fd_list 内 // 在前面的 make link to peers 当中,已经把写去远程结点的 st_netfd_t 保存于 fd_list 之内了 // 所以不需要需要将远程连入的 st_netfd_t 保存在自己的 fd_list /*if (fd_list[client_index] != NULL) { ERR("[%d] This client #%d has connected before, replace it.\n", self_index, client_index); st_netfd_close(fd_list[client_index]); } fd_list[client_index] = client;*/ // 初始化用于读取流的包结构 struct rpc_package *package; package = (struct rpc_package*)calloc(1, sizeof(struct rpc_package)); // const size_t pkghead_len = sizeof(rpcpkg_len); size_t receive; size_t cursor; // 记录数据偏移到了 buf 的什么位置 // 循环服务处理 for (;;) { if ((len = st_read(client, buf, sizeof(buf), ST_UTIME_NO_TIMEOUT)) < 0) { ERR("[%d] failed when read from client #%d.\n", self_index, client_index); goto free_package_close_fd_and_quit; } else if (len == 0) { goto free_package_close_fd_and_quit; } else { if (len > sizeof(buf)) LOG("[%d] read %ld bytes into buffer with size: %lu bytes.\n", self_index, len, sizeof(buf)); // 流进来数据了 cursor = 0; while (cursor < len) { // 如果缓冲区内数据没有处理完 // 如果之前没切过包,或者前一包已经完成 if (package->total == package->received) { package->total = NTOH(*(rpcpkg_len *)(buf + cursor)); if (len - cursor - pkghead_len >= package->total) { package->received = package->total; } else { package->received = len - cursor - pkghead_len; } memcpy(&package->data, buf + cursor + pkghead_len, package->received); cursor += package->received + pkghead_len; } else { // 现在处理的是断开包 assert(package->received < package->total); receive = (len >= package->total - package->received) ? package->total - package->received : len; memcpy(&package->data + package->received, buf + cursor, receive); package->received += receive; cursor += receive; } // 如果刚刚处理过的包已经是完整包,则处决它 if (package->received == package->total) { struct rpc_package_head *head = protocol_decode(package); switch (head->type) { case UNKNOW: break; case REQUEST: LOG("[%d] receive an rpc request with method: %s and parameter: %s\n", self_index, head->body->request.method, head->body->request.parameter); queue_put(queue, head); break; case RESPONSE: LOG("[%d] response an rpc request with result: %s\n", self_index, head->body->response.result); // TODO: 对 response 对象的后续处理 protocol_package_free(head); head = NULL; break; } } } } } free_package_close_fd_and_quit: free(package); close_fd_and_quit: st_netfd_close(client); return 0; }
int receiver_recv(struct receiver *recvr, const struct sa *src, struct mbuf *mb) { struct hdr hdr; uint64_t now = tmr_jiffies(); size_t start, sz; int err; if (!recvr || !mb) return EINVAL; if (!recvr->ts_start) recvr->ts_start = now; recvr->ts_last = now; start = mb->pos; sz = mbuf_get_left(mb); /* decode packet */ err = protocol_decode(&hdr, mb); if (err) { if (err == EBADMSG) { re_fprintf(stderr, "[%u] ignore a non-Turnperf packet" " from %J (%zu bytes)\n", recvr->allocid, src, sz); hexdump(stderr, mb->buf + start, sz); return 0; } re_fprintf(stderr, "receiver: protocol decode" " error [%zu bytes from %J] (%m)\n", sz, src, err); re_fprintf(stderr, " %w\n", mb->buf + start, sz); return err; } /* verify packet */ if (hdr.session_cookie != recvr->cookie) { re_fprintf(stderr, "invalid cookie received" " from %J [exp=%x, actual=%x] (%zu bytes)\n", src, recvr->cookie, hdr.session_cookie, sz); protocol_packet_dump(&hdr); return EPROTO; } if (hdr.alloc_id != recvr->allocid) { re_fprintf(stderr, "invalid allocation-ID received" " from %J [exp=%u, actual=%u] (%zu bytes)\n", src, hdr.alloc_id, recvr->allocid, sz); protocol_packet_dump(&hdr); return EPROTO; } if (recvr->last_seq) { if (hdr.seq <= recvr->last_seq) { re_fprintf(stderr, "receiver[%u]: late or " " out-of-order packet from %J" " (last_seq=%u, seq=%u)\n", recvr->allocid, src, recvr->last_seq, hdr.seq); } } #if 0 protocol_packet_dump(&hdr); #endif recvr->total_bytes += sz; recvr->total_packets += 1; recvr->last_seq = hdr.seq; return 0; }