/* * Asynchronously create a new http connection for 'Url' * We'll set some socket parameters; the rest will be set later * when the IP is known. * ( Data1 = Web structure ) * Return value: 0 on success, -1 otherwise */ static int Http_get(ChainLink *Info, void *Data1) { SocketData_t *S; char *hostname; S = a_Klist_get_data(ValidSocks, VOIDP2INT(Info->LocalKey)); /* Reference Web data */ S->web = Data1; /* Reference Info data */ S->Info = Info; /* Proxy support */ if (Http_must_use_proxy(S->web->url)) { hostname = dStrdup(URL_HOST(HTTP_Proxy)); S->port = URL_PORT(HTTP_Proxy); S->flags |= HTTP_SOCKET_USE_PROXY; } else { hostname = dStrdup(URL_HOST(S->web->url)); S->port = URL_PORT(S->web->url); S->flags &= ~HTTP_SOCKET_USE_PROXY; } /* Let the user know what we'll do */ MSG_BW(S->web, 1, "DNS resolving %s", URL_HOST_(S->web->url)); /* Let the DNS engine resolve the hostname, and when done, * we'll try to connect the socket from the callback function */ a_Dns_resolve(hostname, Http_dns_cb, Info->LocalKey); dFree(hostname); return 0; }
/* * Callback function for the DNS resolver. * Continue connecting the socket, or abort upon error condition. * S->web is checked to assert the operation wasn't aborted while waiting. */ static void Http_dns_cb(int Status, Dlist *addr_list, void *data) { int SKey = VOIDP2INT(data); SocketData_t *S; HostConnection_t *hc; S = a_Klist_get_data(ValidSocks, SKey); if (S) { if (!a_Web_valid(S->web)) { a_Chain_bfcb(OpAbort, S->Info, NULL, "Both"); dFree(S->Info); Http_socket_free(SKey); } else if (Status == 0 && addr_list) { /* Successful DNS answer; save the IP */ S->addr_list = addr_list; S->flags |= HTTP_SOCKET_QUEUED; if (S->flags & HTTP_SOCKET_USE_PROXY) hc = Http_host_connection_get(URL_HOST(HTTP_Proxy)); else hc = Http_host_connection_get(URL_HOST(S->web->url)); Http_socket_enqueue(&hc->queue, S); Http_connect_queued_sockets(hc); } else { /* DNS wasn't able to resolve the hostname */ MSG_BW(S->web, 0, "ERROR: Dns can't resolve %s", (S->flags & HTTP_SOCKET_USE_PROXY) ? URL_HOST_(HTTP_Proxy) : URL_HOST_(S->web->url)); a_Chain_bfcb(OpAbort, S->Info, NULL, "Both"); dFree(S->Info); Http_socket_free(SKey); } } }
static void Http_connect_queued_sockets(HostConnection_t *hc) { SocketData_t *sd; while (hc->active_connections < prefs.http_max_conns && (sd = Http_socket_dequeue(&hc->queue))) { sd->flags &= ~HTTP_SOCKET_QUEUED; if (sd->flags & HTTP_SOCKET_TO_BE_FREED) { dFree(sd); } else if (a_Web_valid(sd->web)) { /* start connecting the socket */ if (Http_connect_socket(sd->Info) < 0) { ChainLink *Info = sd->Info; MSG_BW(sd->web, 1, "ERROR: %s", dStrerror(sd->Err)); a_Chain_bfcb(OpAbort, Info, NULL, "Both"); Http_socket_free(VOIDP2INT(Info->LocalKey)); /* free sd */ dFree(Info); } else { sd->connected_to = hc->host; hc->active_connections++; } } } }
/* * CCC function for the HTTP module */ void a_Http_ccc(int Op, int Branch, int Dir, ChainLink *Info, void *Data1, void *Data2) { int SKey = VOIDP2INT(Info->LocalKey); (void)Data2; /* suppress unused parameter warning */ dReturn_if_fail( a_Chain_check("a_Http_ccc", Op, Branch, Dir, Info) ); if (Branch == 1) { if (Dir == BCK) { /* HTTP query branch */ switch (Op) { case OpStart: /* ( Data1 = Web ) */ SKey = Http_sock_new(); Info->LocalKey = INT2VOIDP(SKey); /* link IO */ a_Chain_link_new(Info, a_Http_ccc, BCK, a_IO_ccc, 1, 1); a_Chain_bcb(OpStart, Info, NULL, NULL); /* async. connection */ Http_get(Info, Data1); break; case OpEnd: /* finished the HTTP query branch */ a_Chain_bcb(OpEnd, Info, NULL, NULL); Http_socket_free(SKey); dFree(Info); break; case OpAbort: /* something bad happened... */ a_Chain_bcb(OpAbort, Info, NULL, NULL); Http_socket_free(SKey); dFree(Info); break; } } else { /* 1 FWD */ /* HTTP send-query status branch */ switch (Op) { default: MSG_WARN("Unused CCC\n"); break; } } } }
void pnlInventory_t::onSetChase(ChoiceGrid::Item *parent, ChoiceGrid::Item *olditem) { options.chasemode = VOIDP2INT(parent->data); ((GM_Gameworld*)g_game)->m_protocol->sendFightModes(options.battlemode, options.chasemode, options.safemode); options.Save(); }
/* * This function gets called after the DNS succeeds solving a hostname. * Task: Finish socket setup and start connecting the socket. * Return value: 0 on success; -1 on error. */ static int Http_connect_socket(ChainLink *Info) { int i, status; #ifdef ENABLE_IPV6 struct sockaddr_in6 name; #else struct sockaddr_in name; #endif SocketData_t *S; DilloHost *dh; socklen_t socket_len = 0; S = a_Klist_get_data(ValidSocks, VOIDP2INT(Info->LocalKey)); /* TODO: iterate this address list until success, or end-of-list */ for (i = 0; (dh = dList_nth_data(S->addr_list, i)); ++i) { if ((S->SockFD = socket(dh->af, SOCK_STREAM, IPPROTO_TCP)) < 0) { S->Err = errno; MSG("Http_connect_socket ERROR: %s\n", dStrerror(errno)); continue; } /* set NONBLOCKING and close on exec. */ fcntl(S->SockFD, F_SETFL, O_NONBLOCK | fcntl(S->SockFD, F_GETFL)); fcntl(S->SockFD, F_SETFD, FD_CLOEXEC | fcntl(S->SockFD, F_GETFD)); /* Some OSes require this... */ memset(&name, 0, sizeof(name)); /* Set remaining parms. */ switch (dh->af) { case AF_INET: { struct sockaddr_in *sin = (struct sockaddr_in *)&name; socket_len = sizeof(struct sockaddr_in); sin->sin_family = dh->af; sin->sin_port = S->port ? htons(S->port) : htons(DILLO_URL_HTTP_PORT); memcpy(&sin->sin_addr, dh->data, (size_t)dh->alen); if (a_Web_valid(S->web) && (S->web->flags & WEB_RootUrl)) MSG("Connecting to %s\n", inet_ntoa(sin->sin_addr)); break; } #ifdef ENABLE_IPV6 case AF_INET6: { char buf[128]; struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&name; socket_len = sizeof(struct sockaddr_in6); sin6->sin6_family = dh->af; sin6->sin6_port = S->port ? htons(S->port) : htons(DILLO_URL_HTTP_PORT); memcpy(&sin6->sin6_addr, dh->data, dh->alen); inet_ntop(dh->af, dh->data, buf, sizeof(buf)); if (a_Web_valid(S->web) && (S->web->flags & WEB_RootUrl)) MSG("Connecting to %s\n", buf); break; } #endif }/*switch*/ MSG_BW(S->web, 1, "Contacting host..."); status = connect(S->SockFD, (struct sockaddr *)&name, socket_len); if (status == -1 && errno != EINPROGRESS) { S->Err = errno; Http_socket_close(S); MSG("Http_connect_socket ERROR: %s\n", dStrerror(S->Err)); } else { a_Chain_bcb(OpSend, Info, &S->SockFD, "FD"); a_Chain_fcb(OpSend, Info, &S->SockFD, "FD"); Http_send_query(S->Info, S); return 0; /* Success */ } } return -1; }
/* * Compare function for searching a Client by its key */ static int Cache_client_by_key_cmp(const void *client, const void *key) { return ((CacheClient_t *)client)->Key - VOIDP2INT(key); }