// Open Ethernet adapter (Pcap) ETH *OpenEthPcap(char *name, bool local, bool tapmode, char *tapaddr) { char errbuf[PCAP_ERRBUF_SIZE]; ETH *e; pcap_t *p; CANCEL *c; // Validate arguments if (name == NULL || tapmode != false) { return NULL; } // Initialize error message buffer errbuf[0] = 0; // Open capturing device p = pcap_open_live(name, 65535, (local == false), 1, errbuf); if(p==NULL) { return NULL; } // Set to non-block mode // (In old BSD OSs, 'select(2)' don't block normally for BPF device. To prevent busy loop) /* if(pcap_setnonblock(p, true, errbuf) == -1) { Debug("pcap_setnonblock:%s\n",errbuf); pcap_close(p); return NULL; } */ e = ZeroMalloc(sizeof(ETH)); e->Name = CopyStr(name); e->Title = CopyStr(name); e->Queue = NewQueue(); e->QueueSize = 0; e->Cancel = NewCancel(); e->IfIndex = -1; e->Socket = pcap_get_selectable_fd(p); e->Pcap = p; e->CaptureThread = NewThread(PcapThread, e); WaitThreadInit(e->CaptureThread); return e; }
extern SessionCtrl* NewSessionCtrl( SessionCtrlType type) { SessionCtrl *ctrl; ctrl = g_new0(SessionCtrl,1); ctrl->type = type; ctrl->waitq = NewQueue(); ctrl->sysdbval = RecParseValueMem(SYSDBVAL_DEF,NULL); InitializeValue(ctrl->sysdbval); ctrl->sysdbvals = RecParseValueMem(SYSDBVALS_DEF,NULL); InitializeValue(ctrl->sysdbvals); return ctrl; }
static bool _WorkerInit(ThreadData _worker) { Worker* worker = (Worker*)_worker; if ((worker->queue = NewQueue()) == NULL) { return false; } if ((worker->pool = NewBufferPool(worker->bufferSize)) == NULL) { return false; } if ((worker->writer = NewWriter(worker->pipe, worker->bufferSize)) == NULL) { return false; } Log(AIO4C_LOG_LEVEL_DEBUG, "initialized with tid 0x%08lx", ThreadGetId(worker->thread)); return true; }
static bool _ReaderInit(ThreadData _reader) { Reader* reader = (Reader*)_reader; if ((reader->selector = NewSelector()) == NULL) { return false; } if ((reader->queue = NewQueue()) == NULL) { return false; } if ((reader->worker = NewWorker(reader->pipe, reader->bufferSize)) == NULL) { return false; } Log(AIO4C_LOG_LEVEL_DEBUG, "initialized with tid 0x%08lx", ThreadGetId(reader->thread)); return true; }
Server* NewServer(AddressType type, char* host, aio4c_port_t port, int bufferSize, int nbPipes, void (*handler)(Event,Connection*,void*), void* handlerArg, void* (*dataFactory)(Connection*,void*)) { Server* server = NULL; ErrorCode code = AIO4C_ERROR_CODE_INITIALIZER; if ((server = aio4c_malloc(sizeof(Server))) == NULL) { #ifndef AIO4C_WIN32 code.error = errno; #else /* AIO4C_WIN32 */ code.source = AIO4C_ERRNO_SOURCE_SYS; #endif /* AIO4C_WIN32 */ code.size = sizeof(Server); code.type = "Server"; Raise(AIO4C_LOG_LEVEL_ERROR, AIO4C_ALLOC_ERROR_TYPE, AIO4C_ALLOC_ERROR, &code); return NULL; } server->address = NewAddress(type, host, port); server->pool = NewBufferPool(bufferSize); server->factory = NewConnectionFactory(server->pool, dataFactory, handlerArg); server->acceptor = NULL; server->thread = NULL; server->handler = handler; server->queue = NewQueue(); server->nbPipes = nbPipes; server->thread = NewThread( "server", _serverInit, _serverRun, _serverExit, (ThreadData)server); if (server->thread == NULL) { FreeAddress(&server->address); FreeBufferPool(&server->pool); FreeConnection(&server->factory); FreeQueue(&server->queue); aio4c_free(server); return NULL; } return server; }
int main(void) { puts("!!!Hello World!!!"); /* prints !!!Hello World!!! */ Queue* q = NewQueue(5); q->enqueue(q, 2); q->enqueue(q, 3); q->enqueue(q, 4); q->enqueue(q, 5); q->enqueue(q, 6); q->dequeue(q); q->dequeue(q); q->enqueue(q, 7); q->enqueue(q, 8); q->dequeue(q); q->enqueue(q, 9); for (int i = 0; i < q->size; i++){ printf("%d,", q->dequeue(q)); } printf("\nQueue Free: %d", q->free); return EXIT_SUCCESS; }
// Initialize the packet adapter bool LinkPaInit(SESSION *s) { LINK *k; THREAD *t; // Validate arguments if (s == NULL || (k = (LINK *)s->PacketAdapter->Param) == NULL) { return false; } // Create a transmission packet queue k->SendPacketQueue = NewQueue(); // Creat a link server thread t = NewThread(LinkServerSessionThread, (void *)k); WaitThreadInit(t); ReleaseThread(t); return true; }
// パケットアダプタ初期化 bool LinkPaInit(SESSION *s) { LINK *k; THREAD *t; // 引数チェック if (s == NULL || (k = (LINK *)s->PacketAdapter->Param) == NULL) { return false; } // 送信パケットキューの作成 k->SendPacketQueue = NewQueue(); // リンクサーバースレッドの作成 t = NewThread(LinkServerSessionThread, (void *)k); WaitThreadInit(t); ReleaseThread(t); return true; }
// Initialize the packet adapter bool NullPaInit(SESSION *s) { NULL_LAN *n; // Validate arguments if (s == NULL) { return false; } n = ZeroMalloc(sizeof(NULL_LAN)); s->PacketAdapter->Param = (void *)n; n->Cancel = NewCancel(); n->PacketQueue = NewQueue(); n->Event = NewEvent(); GenMacAddress(n->MacAddr); n->PacketGeneratorThread = NewThread(NullPacketGenerateThread, n); return true; }
extern int ConnectTerm( int _fhTerm) { int fhTerm; pthread_t thr; pthread_attr_t attr; TermNode *term; ENTER_FUNC; pthread_attr_init(&attr); pthread_attr_setstacksize(&attr,256*1024); if ((fhTerm = accept(_fhTerm,0,0)) < 0) { Error("accept(2) failure:%s",strerror(errno)); } term = New(TermNode); term->que = NewQueue(); term->fp = SocketToNet(fhTerm); pthread_create(&thr,&attr,(void *(*)(void *))TermThread,(void *)term); pthread_detach(thr); LEAVE_FUNC; return (fhTerm); }
// Start tracking of the routing table void RouteTrackingStart(SESSION *s) { VLAN *v; ROUTE_TRACKING *t; UINT if_id = 0; ROUTE_ENTRY *e; ROUTE_ENTRY *dns = NULL; ROUTE_ENTRY *route_to_real_server_global = NULL; char tmp[64]; UINT exclude_if_id = 0; bool already_exists = false; bool already_exists_by_other_account = false; IP eight; // Validate arguments if (s == NULL) { return; } v = (VLAN *)s->PacketAdapter->Param; if (v->RouteState != NULL) { return; } // Get the interface ID of the virtual LAN card if_id = GetInstanceId(v->InstanceName); Debug("[InstanceId of %s] = 0x%x\n", v->InstanceName, if_id); if (MsIsVista()) { // The routing table by the virtual LAN card body should be // excluded explicitly in Windows Vista exclude_if_id = if_id; } // Get the route to the server e = GetBestRouteEntryEx(&s->ServerIP, exclude_if_id); if (e == NULL) { // Acquisition failure Debug("Failed to get GetBestRouteEntry().\n"); return; } IPToStr(tmp, sizeof(tmp), &e->GatewayIP); Debug("GetBestRouteEntry() Succeed. [Gateway: %s]\n", tmp); // Add a route if (MsIsVista()) { e->Metric = e->OldIfMetric; } if (AddRouteEntryEx(e, &already_exists) == false) { FreeRouteEntry(e); e = NULL; } Debug("already_exists: %u\n", already_exists); if (already_exists) { if (s->Cedar->Client != NULL && s->Account != NULL) { UINT i; ACCOUNT *a; for (i = 0;i < LIST_NUM(s->Cedar->Client->AccountList);i++) { a = LIST_DATA(s->Cedar->Client->AccountList, i); Lock(a->lock); { SESSION *sess = a->ClientSession; if (sess != NULL && sess != s) { VLAN *v = sess->PacketAdapter->Param; if (v != NULL) { ROUTE_TRACKING *tr = v->RouteState; if (tr != NULL && e != NULL) { if (Cmp(tr->RouteToServer, e, sizeof(ROUTE_ENTRY)) == 0) { already_exists_by_other_account = true; } } } } } Unlock(a->lock); } } if (already_exists_by_other_account) { Debug("already_exists_by_other_account = %u\n", already_exists_by_other_account); already_exists = false; } } // Get the routing table to the DNS server // (If the DNS server is this PC itself, there's no need to get) if (IsZeroIP(&s->DefaultDns) == false) { if (IsMyIPAddress(&s->DefaultDns) == false) { dns = GetBestRouteEntryEx(&s->DefaultDns, exclude_if_id); if (dns == NULL) { // Getting failure Debug("Failed to get GetBestRouteEntry DNS.\n"); } else { // Add a route if (MsIsVista()) { dns->Metric = dns->OldIfMetric; if (AddRouteEntry(dns) == false) { FreeRouteEntry(dns); dns = NULL; } } } } } if (s->IsAzureSession && IsZeroIP(&s->AzureRealServerGlobalIp) == false) { // Add also a static route to the real server in the case of via VPN Azure if (IsMyIPAddress(&s->AzureRealServerGlobalIp) == false) { route_to_real_server_global = GetBestRouteEntryEx(&s->AzureRealServerGlobalIp, exclude_if_id); if (route_to_real_server_global != NULL) { if (MsIsVista()) { route_to_real_server_global->Metric = route_to_real_server_global->OldIfMetric; } if (AddRouteEntry(route_to_real_server_global) == false) { FreeRouteEntry(route_to_real_server_global); route_to_real_server_global = NULL; } } } } // Initialize if (s->Cedar->Client != NULL && s->Account != NULL) { Lock(s->Account->lock); } t = ZeroMalloc(sizeof(ROUTE_TRACKING)); v->RouteState = t; t->RouteToServerAlreadyExists = already_exists; t->RouteToServer = e; t->RouteToDefaultDns = dns; t->RouteToRealServerGlobal = route_to_real_server_global; t->VLanInterfaceId = if_id; t->NextTrackingTime = 0; t->DeletedDefaultGateway = NewQueue(); t->OldDefaultGatewayMetric = 0x7fffffff; if (s->Cedar->Client != NULL && s->Account != NULL) { Unlock(s->Account->lock); } // Get the route to 8.8.8.8 SetIP(&eight, 8, 8, 8, 8); t->RouteToEight = GetBestRouteEntryEx(&eight, exclude_if_id); // Get the current default DNS server to detect network changes GetDefaultDns(&t->OldDnsServer); // Get as soon as releasing the IP address in the case of using DHCP if (IsNt()) { char tmp[MAX_SIZE]; MS_ADAPTER *a; Format(tmp, sizeof(tmp), VLAN_ADAPTER_NAME_TAG, v->InstanceName); a = MsGetAdapter(tmp); if (a != NULL) { if (a->UseDhcp) { bool ret = Win32ReleaseAddressByGuidEx(a->Guid, 100); Debug("*** Win32ReleaseAddressByGuidEx = %u\n", ret); ret = Win32RenewAddressByGuidEx(a->Guid, 100); Debug("*** Win32RenewAddressByGuidEx = %u\n", ret); } MsFreeAdapter(a); } } else { // For Win9x Win32RenewDhcp9x(if_id); } // Clear the DNS cache Win32FlushDnsCache(); // Detect a change in the routing table (for only supported OS) t->RouteChange = NewRouteChange(); Debug("t->RouteChange = 0x%p\n", t->RouteChange); }
// Open Ethernet adapter (BPF) ETH *OpenEthBpf(char *name, bool local, bool tapmode, char *tapaddr) { ETH *e; CANCEL *c; char devname[MAX_SIZE]; int n = 0; int fd; int ret; UINT bufsize; struct ifreq ifr; struct timeval to; // Find unused bpf device and open it do{ Format(devname, sizeof(devname), "/dev/bpf%d", n++); fd = open (devname, O_RDWR); if(fd<0){ perror("open"); } }while(fd < 0 && errno == EBUSY); // No free bpf device was found if(fd < 0){ Debug("BPF: No minor number are free.\n"); return NULL; } // Enlarge buffer size n = 524288; // Somehow(In libpcap, this size is 32768) while(true){ // Specify buffer size ioctl(fd, BIOCSBLEN, &n); // Bind to the network device StrCpy(ifr.ifr_name, IFNAMSIZ, name); ret = ioctl(fd, BIOCSETIF, &ifr); if(ret < 0){ if(ret == ENOBUFS && n>1500){ // Inappropriate buffer size // Retry with half buffer size // If buffer size is under 1500 bytes, something goes wrong n /= 2; continue; } Debug("bpf: binding network failed.\n"); close(fd); return NULL; }else{ break; } } bufsize = n; // Set to promiscuous mode if(local == false){ if (ioctl(fd, BIOCPROMISC, NULL) < 0){ printf("bpf: promisc mode failed.\n"); close(fd); return NULL; } } // Set to immediate mode (Return immediately when packet arrives) n = 1; if (ioctl(fd, BIOCIMMEDIATE, &n) < 0){ Debug("BPF: non-block mode failed.\n"); close(fd); return NULL; } // Set receiving self sending packet n = 1; if (ioctl(fd, BIOCGSEESENT, &n) < 0){ Debug("BPF: see sent mode failed.\n"); close(fd); return NULL; } // Header complete mode (Generate whole header of sending packet) n = 1; if (ioctl(fd, BIOCSHDRCMPLT, &n) < 0){ Debug("BPF: Header complete mode failed.\n"); close(fd); return NULL; } // Set timeout delay to 1 second to.tv_sec = 1; to.tv_usec = 0; if (ioctl(fd, BIOCSRTIMEOUT, &to) < 0){ Debug("BPF: Read timeout setting failed.\n"); close(fd); return NULL; } e = ZeroMalloc(sizeof(ETH)); e->Name = CopyStr(name); e->Title = CopyStr(name); e->IfIndex = -1; e->Socket = fd; e->BufSize = bufsize; #ifdef BRIDGE_BPF_THREAD e->Queue = NewQueue(); e->QueueSize = 0; e->Cancel = NewCancel(); // Start capture thread e->CaptureThread = NewThread(BpfThread, e); WaitThreadInit(e->CaptureThread); #else // BRIDGE_BPF_THREAD c = NewCancel(); UnixDeletePipe(c->pipe_read, c->pipe_write); c->pipe_read = c->pipe_write = -1; c->SpecialFlag = true; c->pipe_read = fd; e->Cancel = c; e->Buffer = Malloc(bufsize); e->Next = e->Buffer; e->Rest = 0; // Set to non-blocking mode UnixSetSocketNonBlockingMode(fd, true); #endif // BRIDGE_BPF_THREAD // Open interface control socket for FreeBSD e->SocketBsdIf = socket(AF_LOCAL, SOCK_DGRAM, 0); // Get MTU value e->InitialMtu = EthGetMtu(e); return e; }
ETH *OpenEthInternal(char *name, bool local, bool tapmode, char *tapaddr) { WP_ADAPTER *t; ETH *e; ADAPTER *a = NULL; HANDLE h; CANCEL *c; MS_ADAPTER *ms; char name_with_id[MAX_SIZE]; SU *su = NULL; SU_ADAPTER *su_adapter = NULL; // Validate arguments if (name == NULL || IsEthSupported() == false) { return NULL; } if (tapmode) { // Tap is not supported in Windows return NULL; } Lock(eth_list_lock); InitEthAdaptersList(); t = Win32EthSearch(name); if (t == NULL) { Unlock(eth_list_lock); return NULL; } Debug("OpenEthInternal: %s\n", t->Name); if (StartWith(t->Name, SL_ADAPTER_ID_PREFIX)) { // Open with SU su = SuInit(); if (su == NULL) { // Fail to initialize SU Unlock(eth_list_lock); return NULL; } su_adapter = SuOpenAdapter(su, t->Name); if (su_adapter == NULL) { // Fail to get adapter SuFree(su); Unlock(eth_list_lock); return NULL; } is_using_selow = true; } else { // Open with SEE a = wp->PacketOpenAdapter(t->Name); if (a == NULL) { Unlock(eth_list_lock); return NULL; } if (IsWin32BridgeWithSee() == false) { MsSetThreadSingleCpu(); } is_using_selow = false; } e = ZeroMalloc(sizeof(ETH)); e->Name = CopyStr(t->Name); Win32EthMakeCombinedName(name_with_id, sizeof(name_with_id), t->Title, t->Guid); e->Title = CopyStr(name_with_id); if (su_adapter != NULL) { // SU e->SuAdapter = su_adapter; e->Su = su; // Get event object h = e->SuAdapter->hEvent; c = NewCancelSpecial(h); e->Cancel = c; } else { // SEE e->Adapter = a; wp->PacketSetBuff(e->Adapter, BRIDGE_WIN32_ETH_BUFFER); wp->PacketSetHwFilter(e->Adapter, local ? 0x0080 : 0x0020); wp->PacketSetMode(e->Adapter, PACKET_MODE_CAPT); wp->PacketSetReadTimeout(e->Adapter, -1); wp->PacketSetNumWrites(e->Adapter, 1); if (wp->PacketSetLoopbackBehavior != NULL) { // Filter loopback packet in kernel if (GET_KETA(GetOsType(), 100) >= 3) { if (MsIsWindows8() == false) { // Enable for Windows XP, Server 2003 or later // But disable for Windows 8 or later bool ret = wp->PacketSetLoopbackBehavior(e->Adapter, 1); Debug("*** PacketSetLoopbackBehavior: %u\n", ret); e->LoopbackBlock = ret; } } } // Get event object h = wp->PacketGetReadEvent(e->Adapter); c = NewCancelSpecial(h); e->Cancel = c; e->Packet = wp->PacketAllocatePacket(); e->PutPacket = wp->PacketAllocatePacket(); } e->Buffer = Malloc(BRIDGE_WIN32_ETH_BUFFER); e->BufferSize = BRIDGE_WIN32_ETH_BUFFER; e->PacketQueue = NewQueue(); // Get MAC address by GUID ms = MsGetAdapterByGuid(t->Guid); if (ms != NULL) { if (ms->AddressSize == 6) { Copy(e->MacAddress, ms->Address, 6); } MsFreeAdapter(ms); } Unlock(eth_list_lock); return e; }
// アダプタを開く (BPF) ETH *OpenEthBpf(char *name, bool local, bool tapmode, char *tapaddr) { ETH *e; CANCEL *c; char devname[MAX_SIZE]; int n = 0; int fd; int ret; UINT bufsize; struct ifreq ifr; struct timeval to; // 未使用の bpf デバイスを探して開く do{ Format(devname, sizeof(devname), "/dev/bpf%d", n++); fd = open (devname, O_RDWR); if(fd<0){ perror("open"); } }while(fd < 0 && errno == EBUSY); // 開くことが出来るbpfデバイスが無ければエラー if(fd < 0){ Debug("BPF: No minor number are free.\n"); return NULL; } // バッファサイズを拡大 n = 524288; // なんとなく(libpcapでは32768だった) while(true){ // バッファサイズを指定 ioctl(fd, BIOCSBLEN, &n); // ネットワークをバインド StrCpy(ifr.ifr_name, IFNAMSIZ, name); ret = ioctl(fd, BIOCSETIF, &ifr); if(ret < 0){ if(ret == ENOBUFS && n>1500){ // バッファサイズが不適切 // サイズを半分にしてリトライ // バッファサイズ1500バイト以下でエラーになるのは何かおかしい n /= 2; continue; } Debug("bpf: binding network failed.\n"); close(fd); return NULL; }else{ break; } } bufsize = n; // プロミスキャスモードに設定 if(local == false){ if (ioctl(fd, BIOCPROMISC, NULL) < 0){ printf("bpf: promisc mode failed.\n"); close(fd); return NULL; } } // 即時モードに設定(パケットを受信するとタイムアウトを待たず、すぐにreadがreturnする) n = 1; if (ioctl(fd, BIOCIMMEDIATE, &n) < 0){ Debug("BPF: non-block mode failed.\n"); close(fd); return NULL; } // 自分が送信するパケットも受信する n = 1; if (ioctl(fd, BIOCGSEESENT, &n) < 0){ Debug("BPF: see sent mode failed.\n"); close(fd); return NULL; } // ヘッダ完全モード(送信するパケットのヘッダも自分で生成する) n = 1; if (ioctl(fd, BIOCSHDRCMPLT, &n) < 0){ Debug("BPF: Header complete mode failed.\n"); close(fd); return NULL; } // read のタイムアウト時間を設定(1秒) to.tv_sec = 1; to.tv_usec = 0; if (ioctl(fd, BIOCSRTIMEOUT, &to) < 0){ Debug("BPF: Read timeout setting failed.\n"); close(fd); return NULL; } e = ZeroMalloc(sizeof(ETH)); e->Name = CopyStr(name); e->Title = CopyStr(name); e->IfIndex = -1; e->Socket = fd; e->BufSize = bufsize; #ifdef BRIDGE_BPF_THREAD e->Queue = NewQueue(); e->QueueSize = 0; e->Cancel = NewCancel(); // キャプチャ用スレッドの開始 e->CaptureThread = NewThread(BpfThread, e); WaitThreadInit(e->CaptureThread); #else // BRIDGE_BPF_THREAD c = NewCancel(); UnixDeletePipe(c->pipe_read, c->pipe_write); c->pipe_read = c->pipe_write = -1; c->SpecialFlag = true; c->pipe_read = fd; e->Cancel = c; e->Buffer = Malloc(bufsize); e->Next = e->Buffer; e->Rest = 0; // ノンブロッキングモードに設定 UnixSetSocketNonBlockingMode(fd, true); #endif // BRIDGE_BPF_THREAD // FreeBSD 用インターフェイス操作用ソケットを作成 e->SocketBsdIf = socket(AF_LOCAL, SOCK_DGRAM, 0); // MTU の取得 e->InitialMtu = EthGetMtu(e); return e; }
int main(int argc, char * argv[]) { if (argc != 4) { fprintf(stderr, "Usage : %s <input file> <input chunking metafile> <instanceID>\n", argv[0]); return 0; } uint64_t i; int ifd = open(argv[1], O_RDONLY); int ofd = open(argv[2], O_RDONLY); assert(ifd != -1); assert(ofd != -1); posix_fadvise(ofd, 0, 0, POSIX_FADV_WILLNEED); uint64_t isize = lseek(ifd, 0, SEEK_END); uint64_t osize = lseek(ofd, 0, SEEK_END); uint64_t entries = osize / sizeof(Segment); uint8_t * data = MMAP_FD_RO(ifd, isize); Segment * base_seg = MMAP_FD_PV(ofd, osize); printf("Number of Segments: %d\n",entries); mmq = LongQueue(); void * cdata = MMAP_MM(MAX_SEG_SIZE * LONGQUEUE_LENGTH); for (i = 0; i < LONGQUEUE_LENGTH; i++) { Enqueue(mmq, cdata + i * MAX_SEG_SIZE); } IndexService * is = GetIndexService(); ImageService * es = GetImageService(); CompressService * cs = GetCompressService(); BucketService * bs = GetBucketService(); Queue * miq = NewQueue(); Queue * icq = NewQueue(); Queue * ceq = NewQueue(); Queue * ebq = NewQueue(); Queue * bmq = NewQueue(); is->start(miq, icq); cs->start(icq, ceq); es->start(ceq, ebq, atoi(argv[3])); bs->start(ebq, bmq); pthread_t mid; pthread_create(&mid, NULL, end, bmq); struct timeval x; TIMERSTART(x); for (i = 0; i < entries; i++) { Segment * seg = base_seg + i; seg->data = data + seg->offset; seg->cdata = Dequeue(mmq); Enqueue(miq, seg); } Enqueue(miq, NULL); pthread_join(mid, NULL); TIMERSTOP(x); printf("%ld.%06ld\n", x.tv_sec, x.tv_usec); is->stop(); cs->stop(); es->stop(); bs->stop(); free(miq); free(icq); free(ceq); free(ebq); free(bmq); munmap(data, isize); munmap(base_seg, osize); munmap(cdata, MAX_SEG_SIZE * LONGQUEUE_LENGTH); free(mmq); close(ifd); close(ofd); return 0; }
// Create a new UDP acceleration function UDP_ACCEL *NewUdpAccel(CEDAR *cedar, IP *ip, bool client_mode, bool random_port, bool no_nat_t) { UDP_ACCEL *a; SOCK *s; UINT max_udp_size; bool is_in_cedar_port_list = false; if (IsZeroIP(ip)) { ip = NULL; } if (client_mode || random_port) { // Use a appropriate vacant port number in the case of using random port or client mode s = NewUDPEx3(0, ip); } else { // Specify in the range in the case of server mode UINT i; s = NULL; LockList(cedar->UdpPortList); { for (i = UDP_SERVER_PORT_LOWER;i <= UDP_SERVER_PORT_HIGHER;i++) { if (IsIntInList(cedar->UdpPortList, i) == false) { s = NewUDPEx3(i, ip); if (s != NULL) { is_in_cedar_port_list = true; break; } } } if (s == NULL) { // Leave the port selection to the OS because the available port is not found within the range s = NewUDPEx3(0, ip); } if (s != NULL && is_in_cedar_port_list) { AddIntDistinct(cedar->UdpPortList, i); } } UnlockList(cedar->UdpPortList); } if (s == NULL) { return NULL; } a = ZeroMalloc(sizeof(UDP_ACCEL)); a->Cedar = cedar; AddRef(a->Cedar->ref); a->NoNatT = no_nat_t; a->NatT_TranId = Rand64(); a->CreatedTick = Tick64(); a->IsInCedarPortList = is_in_cedar_port_list; a->ClientMode = client_mode; a->Now = Tick64(); a->UdpSock = s; Rand(a->MyKey, sizeof(a->MyKey)); Rand(a->YourKey, sizeof(a->YourKey)); Copy(&a->MyIp, ip, sizeof(IP)); a->MyPort = s->LocalPort; a->IsIPv6 = IsIP6(ip); if (a->IsIPv6) { a->NoNatT = true; } a->RecvBlockQueue = NewQueue(); Rand(a->NextIv, sizeof(a->NextIv)); do { a->MyCookie = Rand32(); } while (a->MyCookie == 0); do { a->YourCookie = Rand32(); } while (a->MyCookie == 0 || a->MyCookie == a->YourCookie); // Calculate the maximum transmittable UDP packet size max_udp_size = MTU_FOR_PPPOE; if (a->IsIPv6 == false) { // IPv4 max_udp_size -= 20; } else { // IPv6 max_udp_size -= 40; } // UDP max_udp_size -= 8; a->MaxUdpPacketSize = max_udp_size; Debug("Udp Accel My Port = %u\n", a->MyPort); // Initialize the NAT-T server IP address acquisition thread a->NatT_Lock = NewLock(); a->NatT_HaltEvent = NewEvent(); if (a->NoNatT == false) { a->NatT_GetIpThread = NewThread(NatT_GetIpThread, a); } return a; }