//读取事件触发调用函数 int ZCE_Event_INotify::handle_input () { #if defined (ZCE_OS_LINUX) ZCE_LOG(RS_DEBUG, "ZCE_Event_INotify::handle_input"); int detect_ret = 0; size_t watch_event_num = 0; //读取 ssize_t read_ret = ZCE_LIB::read(inotify_handle_, read_buffer_, READ_BUFFER_LEN); if (read_ret <= 0) { return -1; } uint32_t read_len = static_cast<uint32_t>(read_ret); uint32_t next_entry_offset = 0; //可能一次读取出来多个inotify_event数据,所以要循环处理 do { detect_ret = 0; ::inotify_event *ne_ptr = (::inotify_event *) (read_buffer_ + next_entry_offset); //检查读取的数据是否还有一个, read_len -= (sizeof(::inotify_event) + ne_ptr->len); next_entry_offset += sizeof(::inotify_event) + ne_ptr->len; HDL_TO_EIN_MAP::iterator active_iter = watch_event_map_.find(ne_ptr->wd); if (active_iter == watch_event_map_.end()) { //某个FD在MAP中间无法找到,最大的可能是 ZCE_LOG(RS_DEBUG, "You code error or a handle not in map (delete in this do while), please check you code. handle[%u]", ne_ptr->wd); continue; } EVENT_INOTIFY_NODE *node_ptr = &(active_iter->second); const char *active_path = ne_ptr->name; //根据返回的mask决定如何处理 //注意下面的代码分支用的if else if ,而不是if if,我的初步看法是这些事件不会一起触发,但也许不对。 //下面5个是和Windows 共有的, uint32_t event_mask = ne_ptr->mask; if (event_mask & IN_CREATE ) { detect_ret = inotify_create(node_ptr->watch_handle_, event_mask, node_ptr->watch_path_, active_path); } else if (event_mask & IN_DELETE ) { detect_ret = inotify_delete(node_ptr->watch_handle_, event_mask, node_ptr->watch_path_, active_path); } else if ( event_mask & IN_MODIFY ) { detect_ret = inotify_modify(node_ptr->watch_handle_, event_mask, node_ptr->watch_path_, active_path); } else if ( event_mask & IN_MOVED_FROM) { detect_ret = inotify_moved_from(node_ptr->watch_handle_, event_mask, node_ptr->watch_path_, active_path); } else if ( event_mask & IN_MOVED_TO) { detect_ret = inotify_moved_to(node_ptr->watch_handle_, event_mask, node_ptr->watch_path_, active_path); } //下面这些是LINUX自己特有的 else if ( event_mask & IN_ACCESS) { detect_ret = inotify_access(node_ptr->watch_handle_, event_mask, node_ptr->watch_path_, active_path); } else if (event_mask & IN_OPEN) { detect_ret = inotify_open(node_ptr->watch_handle_, event_mask, node_ptr->watch_path_, active_path); } else if (event_mask & IN_CLOSE_WRITE || event_mask | IN_CLOSE_NOWRITE) { detect_ret = inotify_close(node_ptr->watch_handle_, event_mask, node_ptr->watch_path_, active_path); } else if (event_mask & IN_ATTRIB) { detect_ret = inotify_attrib(node_ptr->watch_handle_, event_mask, node_ptr->watch_path_, active_path); } else if (event_mask & IN_MOVE_SELF) { detect_ret = inotify_move_slef(node_ptr->watch_handle_, event_mask, node_ptr->watch_path_, active_path); } else if (event_mask & IN_DELETE_SELF) { detect_ret = inotify_delete_slef(node_ptr->watch_handle_, event_mask, node_ptr->watch_path_, active_path); } //返回-1,关闭之, if (detect_ret == -1) { rm_watch(node_ptr->watch_handle_); } //累计发现事件计数 ++(watch_event_num); } while (read_len > 0); return 0; #elif defined (ZCE_OS_WINDOWS) int detect_ret = 0; DWORD num_read = 0; BOOL bret = ::GetOverlappedResult(watch_handle_, &over_lapped_, &num_read, FALSE); //读取结果失败 if (FALSE == bret) { ZCE_LOG(RS_ERROR, "[%s] ::GetOverlappedResult fail,error [%u].", __ZCE_FUNC__, ZCE_LIB::last_error()); return -1; } //记录当前处理的句柄, FILE_NOTIFY_INFORMATION *read_ptr = NULL; DWORD next_entry_offset = 0; do { detect_ret = 0; read_ptr = (FILE_NOTIFY_INFORMATION *)(read_buffer_ + next_entry_offset); //文件名称进行转换,从宽字节转换为多字节, //天杀的Windows在这些地方又埋了陷阱FILE_NOTIFY_INFORMATION里面的长度FileNameLength是字节长度 //而WideCharToMultiByte函数需要的长度是字长度,你能TMD统一一点吗? int length_of_ws = ::WideCharToMultiByte(CP_ACP, 0, read_ptr->FileName, read_ptr->FileNameLength / sizeof(wchar_t), NULL, 0, NULL, NULL); //Windows 的目录名称最大长度可以到3K,我没有兴趣去搞一套这个玩 if (length_of_ws >= MAX_PATH) { ZCE_LOG(RS_ALERT, "My God ,your path length [%u] more than MAX_PATH [%u],I don't process this.", length_of_ws, MAX_PATH); continue; } char active_path[MAX_PATH + 1]; ::WideCharToMultiByte(CP_ACP, 0, read_ptr->FileName, read_ptr->FileNameLength / sizeof(wchar_t), active_path, length_of_ws, NULL, NULL); active_path[length_of_ws] = '\0'; //根据Action和mask确定调用函数 switch (read_ptr->Action) { case FILE_ACTION_ADDED: if (watch_mask_ | IN_CREATE) { detect_ret = inotify_create(watch_handle_, watch_mask_, watch_path_, active_path); } break; case FILE_ACTION_REMOVED: if (watch_mask_ | IN_DELETE) { detect_ret = inotify_delete(watch_handle_, watch_mask_, watch_path_, active_path); } break; //注意Windows 下的这个类型,包括了属性更改 case FILE_ACTION_MODIFIED: if (watch_mask_ | IN_MODIFY) { detect_ret = inotify_modify(watch_handle_, watch_mask_, watch_path_, active_path); } break; case FILE_ACTION_RENAMED_OLD_NAME: if (watch_mask_ | IN_MOVED_FROM) { detect_ret = inotify_moved_from(watch_handle_, watch_mask_, watch_path_, active_path); } break; case FILE_ACTION_RENAMED_NEW_NAME: if (watch_mask_ | IN_MOVED_TO) { detect_ret = inotify_moved_to(watch_handle_, watch_mask_, watch_path_, active_path); } break; } //累计偏移长度 next_entry_offset += read_ptr->NextEntryOffset; //返回-1,关闭之 if (detect_ret == -1) { handle_close(); } //为什么要这样做,因为上面的处理过程,可能有人已经调用了rm_watch,或者handle_close, if (watch_handle_ == ZCE_INVALID_HANDLE) { return 0; } } while (read_ptr->NextEntryOffset != 0); DWORD bytes_returned = 0; //继续进行监控处理 bret = ::ReadDirectoryChangesW( watch_handle_, // handle to directory read_buffer_, // read results buffer READ_BUFFER_LEN, // length of buffer watch_sub_dir_, // monitoring option FILE_NOTIFY_CHANGE_SECURITY | FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_LAST_ACCESS | FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_FILE_NAME, // filter conditions &bytes_returned, // bytes returned & (over_lapped_), // overlapped buffer NULL // completion routine ); if (FALSE == bret) { ZCE_LOG(RS_ERROR, "[zcelib][%s] ::ReadDirectoryChangesW fail,error [%u].", __ZCE_FUNC__, ZCE_LIB::last_error()); } return 0; #endif }
int ENTRY_NAME(int argc, const char* argv[]) { const char **p = alloca(argc * sizeof(char*)); struct master_config config; char* keybuf; memcpy(p, argv + 1, (argc - 1) * sizeof(char*)); p[argc - 1] = 0; if (--argc == 0) { fprintf(stderr, "Usage:\n"); fprintf(stderr, "\tmultex --dev <name> --interface <name> \n"); return 2; } config.interfaces.next = &config.interfaces; config.sessions.next = &config.sessions; config.endpoints.next = &config.endpoints; config.rendpoints.next = &config.rendpoints; config.port = 1389; config.event_base = event_base_new(); config.tracker = tracker_create(config.event_base, &config, (tracker_callback_t)tracker_callback); if (config.tracker == 0) { return 1; } config.cipher = cipher_bf(); config.cipher_keysize = cipher_keysize(config.cipher); config.cipher_size = cipher_blocksize(config.cipher); keybuf = alloca(config.cipher_keysize); config.trackerhost = "tracker.publicbt.com:80"; memset(keybuf, 0, config.cipher_keysize); config.key0 = cipher_context_create(config.cipher, keybuf); random_bytes(keybuf, config.cipher_keysize); config.keyX = cipher_context_create(config.cipher, keybuf); config.digest = digest_context_create(digest_sha()); config.digest_size = digest_size(digest_sha()); while (*p != 0) { const char* cmd = *p++; if (strcmp(cmd, "--tracker") == 0) { if (*p == 0) { fprintf(stderr, "tracker address expected\n"); return 2; } tracker_add(config.tracker, *p++); continue; } if (strcmp(cmd, "--remote") == 0) { struct udpaddress address; if (*p == 0) { fprintf(stderr, "remote address expected\n"); return 2; } udpaddress_resolve(&address, *p++); tracker_callback(&config, &address, 0); continue; } if (strcmp(cmd, "--dev") == 0) { if (*p == 0) { fprintf(stderr, "Device name expected\n"); return 2; } fprintf(stderr, "Creating device %s...\n", *p); config.master_fd = tun_create(*p++); if (config.master_fd < 0) { return 1; } config.master_event = event_new(config.event_base, config.master_fd, EV_READ | EV_PERSIST, (event_callback_fn)master_callback, &config); event_add(config.master_event, 0); continue; } if (strcmp(cmd, "--interface") == 0 || strcmp(cmd, "-i") == 0) { const char *name = *p++; struct interface *interface = malloc(sizeof(struct interface)); if (name == 0) { fprintf(stderr, "interface name expected\n"); return 2; } interface->priority = 1; interface->weight = 1; interface->name = strdup(name); interface->next = config.interfaces.next; interface->active = 0; config.interfaces.next = interface; continue; } fprintf(stderr, "Unknown option: %s\n", cmd); return 2; } /*open interfaces*/ config.inotify = inotify_create(config.event_base, &config, (inotification_callback_t)inotify_callback); if (config.inotify == 0) { return 1; } { struct if_nameindex *ifp = if_nameindex(); struct if_nameindex *p = ifp; struct ifaddrs *ifaddr; struct ifaddrs *ifa; if (getifaddrs(&ifaddr) == -1) { perror("getifaddrs"); return 1; } while (p->if_index > 0 && p->if_name != 0) { struct inotification notification; notification.device = p->if_name; notification.type = INOTIFY_INT_ADDED; inotify_callback(&config, ¬ification); for (ifa = ifaddr; ifa != 0; ifa = ifa->ifa_next) { notification.address.family = ifa->ifa_addr->sa_family; if (strcmp(ifa->ifa_name, p->if_name) != 0) { continue; } notification.type = INOTIFY_ADDR_ADDED; /* For an AF_INET* interface address, display the address */ if (notification.address.family == AF_INET) { notification.address.addr4 = ((struct sockaddr_in*)ifa->ifa_addr)->sin_addr; } else if (notification.address.family == AF_INET6) { notification.address.addr6 = ((struct sockaddr_in6*)ifa->ifa_addr)->sin6_addr; } else { continue; } inotify_callback(&config, ¬ification); } p++; } if_freenameindex(ifp); freeifaddrs(ifaddr); } fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK); config.stdin_event = event_new(config.event_base, STDIN_FILENO, EV_READ | EV_PERSIST, (event_callback_fn)stdin_callback, &config); event_add(config.stdin_event, 0); { struct timeval timeval; timeval.tv_sec = 10; timeval.tv_usec = 0; config.reconnect_event = event_new(config.event_base, -1, EV_PERSIST, (event_callback_fn)reconnect_callback, &config); evtimer_add(config.reconnect_event, &timeval); } reconnect_callback(-1, EV_TIMEOUT, &config); event_base_dispatch(config.event_base); return 0; }