static void ottcp_disconnect(OTTCP *x) { EnterCallback(); x->o_inetHostName = 0; x->o_inetPort = 0; x->o_inetHost = 0; change_connection(x); ExitCallback(); }
static void ottcp_connect(OTTCP *x, Symbol *hostName, long port) { OSStatus s; InetHost host; EnterCallback(); if (LookUpInetHost(hostName->s_name, &host) == 0) { post("е OTTCP: can't understand host \"%s\"; not connecting", hostName->s_name); return; } x->o_inetHostName = hostName->s_name; x->o_inetPort = port; x->o_inetHost = host; change_connection(x); ExitCallback(); }
void end_dump(struct status *stat, void *p) { struct cache_entry *ce = stat->ce; int oh = get_output_handle(); if (oh == -1) return; if (ce && ce->redirect && dump_red_count++ < MAX_REDIRECTS) { unsigned char *u, *p; if (stat->state >= 0) change_connection(stat, NULL, PRI_CANCEL); u = join_urls(ce->url, ce->redirect); if (!http_bugs.bug_302_redirect) if (!ce->redirect_get && (p = strchr(ce->url, POST_CHAR))) add_to_strn(&u, p); load_url(u, stat, PRI_MAIN, 0); mem_free(u); return; } if (stat->state >= 0 && stat->state < S_TRANS) return; if (stat->state >= S_TRANS && dmp != D_SOURCE) return; if (dmp == D_SOURCE) { if (ce) { struct fragment *frag; nextfrag: foreach(frag, ce->frag) if (frag->offset <= dump_pos && frag->offset + frag->length > dump_pos) { int l = frag->length - (dump_pos - frag->offset); int w = hard_write(oh, frag->data + dump_pos - frag->offset, l); if (w != l) { detach_connection(stat, dump_pos); if (w < 0) fprintf(stderr, "Error writing to stdout: %s.\n", strerror(errno)); else fprintf(stderr, "Can't write to stdout.\n"); retval = RET_ERROR; goto terminate; } dump_pos += w; detach_connection(stat, dump_pos); goto nextfrag; } } if (stat->state >= 0) return; } else if (ce) {
int main_program(int num_channels, int num_connections, const char *server_hostname, int server_port, int timeout) { struct sockaddr_in server_address; int main_sd = -1, num_events = 0, i, j, event_mask, channels_per_connection, num, start_time = 0, iters_to_next_summary = 0; Connection *connections = NULL, *connection; Statistics stats = {0,0,0,0,0}; int exitcode = EXIT_SUCCESS; struct epoll_event events[MAX_EVENTS]; char buffer[BIG_BUFFER_SIZE]; info("Subscriber starting up\n"); info("Subscriber: %d connections to %d channels on server: %s:%d\n", num_connections, num_channels, server_hostname, server_port); if ((fill_server_address(server_hostname, server_port, &server_address)) != 0) { error2("ERROR host name not found\n"); } if ((main_sd = epoll_create(200 /* this size is not used on Linux kernel 2.6.8+ */)) < 0) { error3("Failed %d creating main epoll socket\n", errno); } if ((connections = init_connections(num_connections, &server_address, main_sd)) == NULL) { error2("Failed to create to connections\n"); } stats.requested_connections = num_connections; for (i = 0; i < num_connections; i++) { connections[i].channel_start = 0; connections[i].channel_end = num_channels - 1; } // infinite loop debug("Entering Infinite Loop\n"); iters_to_next_summary = ITERATIONS_TILL_SUMMARY_PER_TIMEOUT/timeout; for(;;) { if ((num_events = epoll_wait(main_sd, events, MAX_EVENTS, timeout)) < 0) { error3("epoll_wait failed\n"); } for (i = 0; i < num_events; i++) { event_mask = events[i].events; connection = (Connection *)(events[i].data.ptr); if (event_mask & EPOLLHUP) { // SERVER HUNG UP debug("EPOLLHUP\n"); info("Server hung up on conncetion %d. Reconecting...\n", connection->index); sleep(1); stats.connections--; reopen_connection(connection); continue; } if (event_mask & EPOLLERR) { debug("EPOLLERR\n"); info("Server returned an error on connection %d. Reconecting...\n", connection->index); stats.connections--; reopen_connection(connection); continue; } if (event_mask & EPOLLIN) { // READ debug("----------READ AVAILABLE-------\n"); if (connection->state == CONNECTED) { read_response(connection, &stats, buffer, BIG_BUFFER_SIZE); } } if (event_mask & EPOLLOUT) { // WRITE debug("----------WRITE AVAILABLE-------\n"); if (start_time == 0) { start_time = time(NULL); } if (connection->state == CONNECTING) { connection->state = CONNECTED; stats.connections++; debug("Connection opened for index=%d\n", connection->index); subscribe_channels(connection, &stats); // remove write flag from event if (change_connection(connection, EPOLLIN | EPOLLHUP) < 0) { error2("Failed creating socket for connection = %d\n", connection->index); } } } } if ((iters_to_next_summary-- <= 0)) { iters_to_next_summary = ITERATIONS_TILL_SUMMARY_PER_TIMEOUT/timeout; summary("Connections=%ld, Messages=%ld BytesRead=%ld Msg/Sec=%0.2f\n", stats.connections, stats.messages, stats.bytes_read, calc_message_per_second(stats.messages, start_time)); } if (stats.connections == 0) { num = 0; for (j = 0; j < num_connections; j++) { if (connections[i].state != CLOSED) { num++; break; } } if (num == 0) { exitcode = EXIT_SUCCESS; goto exit; } } } exit: if (connections != NULL) free(connections); return exitcode; }
pascal void OTTCPNotifier(void* vobj, OTEventCode code, OTResult result, void* cookie) { OTTCP *x = (OTTCP *) vobj; long oldA5; OSStatus s; EnterCallback(); oldA5 = SetA5(x->o_a5); post("*** OTTCPNotifier(code %x, result %ld)", (long) code, (long) result); if (code == T_OPENCOMPLETE) { if (result != noErr) { post("OTTCPNotifier got a T_OPENCOMPLETE code with error %ld", result); } // Even if we got an error, we'll use the endpoint. x->o_tcp_ep = (EndpointRef) cookie; if (x->o_inetHostName != 0) { BindTheEndpoint(x); // Now we expect a T_BINDCOMPLETE message. } } else if (code == T_BINDCOMPLETE) { TCall sndCall; InetAddress inAddr; // See what ephemeral port number OT gave us x->o_receiveInetPort = x->o_addrWeActuallyGot.fPort; // Now the endpoint has been bound; next trick is connecting OTInitInetAddress(&inAddr, x->o_inetPort, x->o_inetHost); OTMemzero(&sndCall, sizeof(TCall)); sndCall.addr.buf = (void *) &inAddr; sndCall.addr.len = sizeof(InetAddress); post("** About to OTConnect"); s = OTConnect(x->o_tcp_ep, &sndCall, NULL); if (s == kOTNoDataErr) { // No problem; that means connection is in progress post("** OTConnect returned kOTNoDataErr - good"); } else { post("е OTTCP: error: OTConnect returned %ld; not connecting.", s); } // Now we expect T_CONNECT } else if (code == T_CONNECT) { if (result == kOTBadAddressErr) { post("е OTTCP: error: bad address. Disconnecting"); x->o_inetHost = 0; change_connection(x); } else { post("** Got T_CONNECT"); post("** Result passed to notifier: %ld", (long) result); post("** Endpoint state before OTRcvConnect: %ld", (long) OTGetEndpointState(x->o_tcp_ep)); // We could pass in buffers to find out the actual address we connected to, etc. s = OTRcvConnect(x->o_tcp_ep, nil); if (s != kOTNoError) { post("е OTTCP: error: RcvConnect returned %ld", s); } post("** Endpoint state after OTRcvConnect: %ld", (long) OTGetEndpointState(x->o_tcp_ep)); ChangeState(x, NO_REQUEST); x->o_connectionSymbol = ps_connected; clock_delay(x->o_connectedclock, 0); } } else if (code == T_UNBINDCOMPLETE) { // If we have a new inetHost, try to bind it if (x->o_inetHost != 0) { BindTheEndpoint(x); // Now we expect T_BINDCOMPLETE } else { // No inetHost, so we're disonnected x->o_connectionSymbol = ps_disconnected; clock_delay(x->o_connectedclock, 0); } } else if (code == T_DISCONNECTCOMPLETE) { // We always want to rebind when we reconnect, so after disconnecting we unbind s = OTUnbind(x->o_tcp_ep); if (s != kOTNoError) { post("OTTCP: warning: OTUnbind returned %ld", s); } } else if (code == T_DATA) { ottcp_handleIncomingData(x); } else if (code == T_UDERR) { if (x->o_errorreporting) { PostUDERR("OTTCPNotifier was called for a T_UDERR code", x->o_tcp_ep); } else { /* We still have to receive the error to clear the condition */ OTRcvUDErr(x->o_tcp_ep, 0); } } else if (code == T_GODATA) { // Flow control restriction has lifted; now it's OK to send more data. do_write(x, 0, 0); } else if (code == T_DISCONNECT) { // The other dude wants to disconnect post("OTTCP: peer wants to disconnect"); s = OTRcvDisconnect(x->o_tcp_ep, NULL); if (s == kOTNoError) { x->o_inetHost = 0; change_connection(x); } else if (s == kOTNoDisconnectErr) { // false alarm } else { post("е OTTCP: error: OTRcvDisconnect returned %ld", s); } } else if (code == T_ORDREL) { post("*** Got T_ORDREL"); s = OTRcvOrderlyDisconnect(x->o_tcp_ep); if (s == kOTNoReleaseErr) { post("...false alarm!"); } else if (s == kOTNoError) { x->o_inetHost = 0; change_connection(x); } else { post("е OTTCP: error: OTRcvOrderlyDisconnect returned %ld", s); } } else { if (x->o_errorreporting) { post("OTTCP: Unrecognized OTEventCode %ld in event handler. Oh well.", (long) code); } } done: SetA5(oldA5); ExitCallback(); }