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; }
uint16_t ofp_header_get_xid(void* ofp_msg) { return NTOH(((struct ofp_header*) ofp_msg)->xid, 32); }
/** * Read and validate a Pico header from a file. * * @param pico The Pico data structure. This must have the file. * @return True iff there was an error. */ static bool read_header(PICO * pico) { pico->valid = false; // Not yet valid. if (fseek(pico->file, 0, SEEK_SET)) { pico->errno = CANNOT_SEEK; sprintf(pico->error_text, "Unable to seek to start of file."); return true; } // Read and check the header. magic_t file_magic = 0; if (fread(&file_magic, 1, sizeof(magic_t), pico->file) < sizeof(magic_t)) { pico->errno = CANNOT_READ; sprintf(pico->error_text, "Cannot read magic number."); return true; } file_magic = NTOH(magic_t, file_magic); if (file_magic != magic) { pico->errno = NOT_PICO; sprintf(pico->error_text, "Incorrect magic number in file."); return true; } if (fread(&pico->major, 1, sizeof(major_t), pico->file) < sizeof(major_t)) { pico->errno = CANNOT_READ; sprintf(pico->error_text, "Cannot read major version number."); return true; } pico->major = NTOH(major_t, pico->major); if (pico->major != VERSION_MAJOR) { pico->errno = BAD_VERSION; sprintf(pico->error_text, "File has incompatible version %d.x.", pico->major); return true; } if (fread(&pico->minor, 1, sizeof(minor_t), pico->file) < sizeof(minor_t)) { pico->errno = CANNOT_READ; sprintf(pico->error_text, "Cannot read minor version number."); return true; } pico->minor = NTOH(minor_t, pico->minor); if (fread(&pico->offset, 1, sizeof(offset_t), pico->file) < sizeof(offset_t)) { pico->errno = CANNOT_READ; sprintf(pico->error_text, "Cannot read data offset."); return true; } pico->offset = NTOH(offset_t, pico->offset); if (fread(pico->hash, 1, HASH_LEN, pico->file) < HASH_LEN) { pico->errno = CANNOT_READ; sprintf(pico->error_text, "Cannot read hash."); return true; } pico->hash_valid = true; if (fread(&pico->key_length, 1, sizeof(keylen_t), pico->file) < sizeof(keylen_t)) { pico->errno = CANNOT_READ; sprintf(pico->error_text, "Cannot read key length."); return true; } pico->key_length = NTOH(keylen_t, pico->key_length); if (pico->key_length < 1) { pico->errno = KEY_ERROR; sprintf(pico->error_text, "Key has illegal length (0)."); return true; } pico->key = MALLOC(uint8_t, pico->key_length); if (pico->key == NULL) { pico->errno = NO_MEMORY; sprintf(pico->error_text, "Cannot get memory to store key."); return true; } if (fread(pico->key, 1, pico->key_length, pico->file) < pico->key_length) { pico->errno = CANNOT_READ; sprintf(pico->error_text, "Cannot read key."); return true; } if (pico->offset < KEY_POS + pico->key_length) { pico->errno = BAD_OFFSET; sprintf(pico->error_text, "Offset is too small."); return true; } // Header has been read successfully. Compute and save the // metadata length. pico->md_length = pico->offset - KEY_POS - pico->key_length; pico->errno = OK; pico->valid = true; // Header is now valid. return false; }
uint16_t ofp_header_get_length(void* ofp_msg) { return NTOH(((struct ofp_header*) ofp_msg)->length, 16); }
static void *handle_clientconn(void *arg) { 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) { fprintf(stderr, "[%d] failed to handshake from client #%d: %s\n", my_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]; fprintf(stdout, "[%d] 来自 rpc 客户端 #%d 的握手已经成功建立\n", my_index, client_index); // 如果 client_index 等于自己的 my_index,则这个有问题 if (client_index == my_index) { fprintf(stderr, "[%d] rpc client promet the same index with mine.\n", my_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) { fprintf(stderr, "[%d] This client #%d has connected before, replace it.\n", my_index, client_index); st_netfd_close(fd_list[client_index]); } fd_list[client_index] = client;*/ // 初始化用于读取流的包结构 struct rpc_package package; memset((void*)&package, 0, sizeof(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) { fprintf(stderr, "[%d] failed when read from client #%d.\n", my_index, client_index); goto close_fd_and_quit; } else if (len == 0) { goto close_fd_and_quit; } else { if (len > sizeof(buf)) fprintf(stdout, "[%d] read %d bytes into buffer with size: %d bytes.\n", my_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) { fprintf(stdout, "[%d] receive an rpc request with content: %s\n", my_index, package.data); // TODO: 添加收到 rpc 包的业务处理 } } } } close_fd_and_quit: st_netfd_close(client); return 0; }