uint32_t progressive_render(int quality, int bytes_read) { printf("%i bytes read, rendering at quality=%.2f%%\n",bytes_read, 0.01*quality); FLIF_IMAGE* image = flif_decoder_get_image(d, 0); if (!image) { printf("Error: No decoded image found\n"); return 1; } uint32_t w = flif_image_get_width(image); uint32_t h = flif_image_get_height(image); if (!window) window = SDL_CreateWindow("FLIF Viewer", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, w, h, 0); if (!window) { printf("Error: Could not create window\n"); return 2; } char title[100]; sprintf(title,"%ix%i FLIF image [read %i bytes, quality=%.2f%%]",w,h,bytes_read, 0.01*quality); SDL_SetWindowTitle(window,title); SDL_Surface *canvas = SDL_GetWindowSurface(window); if (!canvas) { printf("Error: Could not get canvas\n"); return 2; } if (!surf) surf = SDL_CreateRGBSurface(0,w,h,32,0x000000FF,0x0000FF00,0x00FF0000,0xFF000000); if (!surf) { printf("Error: Could not create surface\n"); return 2; } char* pp =(char*) surf->pixels; for (uint32_t r=0; r<h; r++) { flif_image_read_row_RGBA8(image, r, pp, w * sizeof(RGBA)); pp += surf->pitch; } if (flif_image_get_nb_channels(image) > 3) { // SDL_FillRect(canvas,NULL,0); // Draw checkerboard background for image with alpha channel SDL_Rect sq; sq.w=20; sq.h=20; for (sq.y=0; sq.y<h; sq.y+=sq.h) for (sq.x=0; sq.x<w; sq.x+=sq.w) SDL_FillRect(canvas,&sq,((sq.y/sq.h + sq.x/sq.w)&1 ? 0xFF606060 : 0xFFA0A0A0)); } SDL_BlitSurface(surf,NULL,canvas,NULL); SDL_UpdateWindowSurface(window); SDL_Event e; while (SDL_PollEvent(&e)) {if (!do_event(e)) return 0;} // stop decoding //SDL_Delay(500); return quality + 500; // call me back when you have at least 5% better quality }
/*ARGSUSED*/ int vt_sync ( /*Send TELNET SYNC signal (test for UDQ & typed data)*/ char **vec ) { PE udqp; TEXT_UPDATE ud; char mask, image; mask = SYNC; sync_image ^= SYNC; image = sync_image; bzero( (char *) &ud, sizeof ud); ud.echo_sw = cur_emode; ud.type_sw = CTRL_OBJ; ud.updates.co_list.co_name = "SY"; ud.updates.co_list.co_type = 1; ud.updates.co_list.co_cmd.bool_update.value = ℑ ud.updates.co_list.co_cmd.bool_update.val_count = SYNC_SIZE; ud.updates.co_list.co_cmd.bool_update.mask = &mask; ud.updates.co_list.co_cmd.bool_update.mask_count = SYNC_SIZE; if(build_UDQPDU_UDQpdu(&udqp,1,NULL,NULLCP,(PEPYPARM) &ud) == NOTOK) adios(NULLCP,"UDQ build failure"); udqp->pe_context = 1; do_event(VDATreq_u,udqp); pe_free(udqp); return OK; }
void do_run(void) { event_t *event = NULL; while (1) { /* synchronize nodes */ worldsens_synchronize(); /* catch exceptions */ if (exception != NO_EXCEPTION) { return; } /* get next event */ event = scheduler_next(); /* eventually jump in time */ if (event->clock > g_clock) { do_clockadvance(event->clock); } /* do event */ do_event(event); /* catch exceptions */ if (exception != NO_EXCEPTION) { return; } /* release nodes */ worldsens_scheduler_release(); } }
int main(int argc, char **argv) { if (argc < 2 || argc > 2) { printf("Usage: %s image.flif\n",argv[0]); return 0; } d = flif_create_decoder(); if (!d) return 1; SDL_Init(SDL_INIT_VIDEO); flif_decoder_set_quality(d, 100); flif_decoder_set_scale(d, 1); flif_decoder_set_callback(d, &(progressive_render)); printf("Decoding...\n"); if (flif_decoder_decode_file(d, argv[1]) == 0) { printf("Error: decoding failed\n"); return 1; } if (!quit) { printf("Done.\n"); SDL_Event e; while (1) { SDL_WaitEvent(&e); if (!do_event(e)) break; } } flif_destroy_decoder(d); SDL_DestroyWindow(window); SDL_Quit(); return 0; }
void do_hypervisor_callback(struct pt_regs *regs) { unsigned long l1, l2, l1i, l2i; unsigned int port; int cpu = 0; shared_info_t *s = g_sharedInfoArea; vcpu_info_t *vcpu_info = &s->vcpu_info[cpu]; in_callback = 1; vcpu_info->evtchn_upcall_pending = 0; /* NB x86. No need for a barrier here -- XCHG is a barrier on x86. */ #if !defined(__i386__) && !defined(__x86_64__) /* Clear master flag /before/ clearing selector flag. */ wmb(); #endif l1 = xchg(&vcpu_info->evtchn_pending_sel, 0); while (l1 != 0) { l1i = __ffs(l1); l1 &= ~(1UL << l1i); while ((l2 = active_evtchns(cpu, s, l1i)) != 0) { l2i = __ffs(l2); l2 &= ~(1UL << l2i); port = (l1i * (sizeof(unsigned long) * 8)) + l2i; do_event(port, regs); } } in_callback = 0; }
void stretch_window(void) { int dx, dy; int x0, x1, y0, y1; SETMOUSEICON(&mouse_box); move_mouse(screen, mouse, &mousex, &mousey, 0); SETMOUSEICON(DEFAULT_MOUSE_CURSOR); x0 = ACTIVE(x0); y0 = ACTIVE(y0); x1 = x0 + BIT_WIDE(ACTIVE(border)); y1 = y0 + BIT_HIGH(ACTIVE(border)); if (2 * (mousex - x0) < x1 - x0) x0 = x1; dx = mousex - x0; if (2 * (mousey - y0) < y1 - y0) y0 = y1; dy = mousey - y0; /* x0,y0 is corner farthest from mouse. x0+dx,y0+dx is mouse position */ get_rect(screen, mouse, x0, y0, &dx, &dy, 0); do_button(0); /* look for shape event here */ do_event(EVENT_SHAPE, active, E_MAIN); (void)shape(x0, y0, dx, dy); }
int amx_termctl(int cmd,int value) { switch (cmd) { case 0: return 1; /* simple "is terminal support available" check */ case 1: if (createconsole(0, NULL)) { autowrap=value; return 1; } /* if */ return 0; case 2: return 0; case 3: return 0; case 4: while (app != NULL && win != NULL && do_event(app)) /* nothing */; if (win == NULL) deleteconsole(); return (win != NULL); default: return 0; } /* switch */ }
static void* wait_for_wakeup(Parrot_Interp interpreter, void *next) { QUEUE_ENTRY *entry; parrot_event* event; QUEUE * tq = interpreter->task_queue; interpreter->sleeping = 1; /* * event handler likes callbacks or timers are run as normal code * so inside such an even handler function another event might get * handled, which is good (higher priority events can interrupt * other event handler) OTOH we must ensure that all state changes * are done in do_event and we should probably suspend nested * event handlers sometimes * * FIXME: the same is true for the *next param: * get rid of that, instead mangle the resume flags * and offset to stop the runloop * */ while (interpreter->sleeping) { entry = wait_for_entry(tq); event = (parrot_event* )entry->data; mem_sys_free(entry); edebug((stderr, "got ev %s head : %p\n", et(event), tq->head)); next = do_event(interpreter, event, next); } edebug((stderr, "woke up\n")); return next; }
int main(int argc, char **argv) { if (argc < 2 || argc > 2) { printf("Usage: %s image.flif\n",argv[0]); return 0; } d = flif_create_decoder(); if (!d) return 1; SDL_Init(SDL_INIT_VIDEO); window = SDL_CreateWindow("FLIF Viewer", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 200, 200, 0); flif_decoder_set_quality(d, 100); // this is the default flif_decoder_set_scale(d, 1); // this is the default #ifdef PROGRESSIVE_DECODING flif_decoder_set_callback(d, &(progressive_render)); flif_decoder_set_first_callback_quality(d, 500); // do the first callback when at least 5.00% quality has been decoded printf("Decoding progressively...\n"); SDL_Thread *decode_thread = SDL_CreateThread(decodeThread,"Decode_FLIF",argv); if (!decode_thread) { printf("Error: failed to create decode thread\n"); return 1; } #else printf("Decoding entire image...\n"); decodeThread(argv); progressive_render(10000,-1); #endif SDL_Event e; int result = 0; while (!quit) { draw_image(); if (animation) { SDL_Delay(frame_delay[frame]); frame++; frame %= flif_decoder_num_images(d); } else { SDL_WaitEvent(&e); if (!do_event(e)) break; SDL_Delay(100); } while (SDL_PollEvent(&e)) if (!do_event(e)) break; } #ifdef PROGRESSIVE_DECODING while(flif_abort_decoder(d)) SDL_Delay(100); SDL_WaitThread(decode_thread, &result); #endif flif_destroy_decoder(d); SDL_DestroyWindow(window); SDL_Quit(); return result; }
bool qt_processTermEvent(gp_event_t* event) { // Intercepts resize event if (event->type == GE_fontprops) { // This is an answer to a font metric request. We don't send it back to gnuplot if ((event->par1 > 0) && (event->par2 > 0)) { fprintf(stderr, "qt_processTermEvent received a GE_fontprops event. This should not have happened\n"); return false; } // This is a resize event qt_setSize = true; qt_setWidth = event->mx; qt_setHeight = event->my; } // Scale mouse events else { QPoint p = qt_gnuplotCoord(event->mx, event->my); event->mx = p.x(); event->my = p.y(); } if (event->type == GE_raise) { #ifdef _WIN32 # ifndef WGP_CONSOLE SetForegroundWindow(textwin.hWndParent); # else SetForegroundWindow(GetConsoleWindow()); # endif WinRaiseConsole(); #endif return true; } // Send the event to gnuplot core do_event(event); // Process pause_for_mouse if ((event->type == GE_buttonrelease) && (paused_for_mouse & PAUSE_CLICK)) { int button = event->par1; if (((button == 1) && (paused_for_mouse & PAUSE_BUTTON1)) || ((button == 2) && (paused_for_mouse & PAUSE_BUTTON2)) || ((button == 3) && (paused_for_mouse & PAUSE_BUTTON3))) paused_for_mouse = 0; if (paused_for_mouse == 0) return true; } if ((event->type == GE_keypress) && (paused_for_mouse & PAUSE_KEYSTROKE) && (event->par1 > '\0')) { paused_for_mouse = 0; return true; } return false; }
int main(int argc, char **argv) { if (argc < 2 || argc > 2) { printf("Usage: %s image.flif\n",argv[0]); return 0; } SDL_Init(SDL_INIT_VIDEO); SDL_EventState(SDL_MOUSEMOTION,SDL_IGNORE); window = SDL_CreateWindow("FLIF Viewer -- Loading...", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 200, 200, SDL_WINDOW_RESIZABLE); renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); SDL_SetRenderDrawColor(renderer, 127, 127, 127, 255); // background color (in case aspect ratio of window doesn't match image) SDL_RenderClear(renderer); SDL_RenderPresent(renderer); if (SDL_GetWindowDisplayMode(window,&dm)) { printf("Error: SDL_GetWindowDisplayMode\n"); return 1; } int result = 0; #ifdef PROGRESSIVE_DECODING printf("Decoding progressively...\n"); SDL_Thread *decode_thread = SDL_CreateThread(decodeThread,"Decode_FLIF",argv); if (!decode_thread) { printf("Error: failed to create decode thread\n"); return 1; } #else printf("Decoding entire image...\n"); result = decodeThread(argv); #endif SDL_Event e; unsigned int current_time; unsigned int begin=SDL_GetTicks(); while (!quit) { if (nb_frames > 1) { current_time = SDL_GetTicks(); draw_image(); int time_passed = SDL_GetTicks()-current_time; int time_to_wait = frame_delay[frame] - time_passed; if (time_to_wait>0) SDL_Delay(time_to_wait); // todo: if the animation has extremely long frame delays, this makes the viewer unresponsive frame++; frame %= nb_frames; } else { SDL_Delay(200); // if it's not an animation, check event queue 5 times per second } while (SDL_PollEvent(&e)) do_event(e); } if (nb_frames > 1) printf("Rendered %i frames in %.2f seconds, %.4f frames per second\n", framecount, 0.001*(SDL_GetTicks()-begin), 1000.0*framecount/(SDL_GetTicks()-begin)); #ifdef PROGRESSIVE_DECODING // make sure the decoding gets properly aborted (in case it was not done yet) while(flif_abort_decoder(d)) SDL_Delay(100); SDL_WaitThread(decode_thread, &result); #endif SDL_DestroyWindow(window); SDL_Quit(); return result; }
/*---------------------------------------------------------------------------*/ int process_run(void) { /* Process poll events. */ if (poll_requested) { do_poll(); } /* Process one event from the queue */ do_event(); return nevents + poll_requested; }
int createconsole(int argc, char *argv[]) { if (win != NULL) return 1; if (app != NULL) /* delete existing partial data structures */ deleteconsole(); lines = malloc(NUM_LINES*NUM_COLUMNS*sizeof(TCHAR)); if (lines == NULL) return 0; memset(lines, __T(' '), NUM_LINES * NUM_COLUMNS); app = new_app(argc, argv); if (app == NULL) { deleteconsole(); return 0; } /* if */ font = new_font(app, "unifont", PLAIN | PORTABLE_FONT, 16); if (font == NULL) font = new_font(app, "courier", PLAIN | NATIVE_FONT, 16); if (font == NULL) font = find_default_font(app); if (font == NULL) { deleteconsole(); return 0; } /* if */ win = new_window(app, rect(0,0, NUM_COLUMNS*font_width(font,"x",1), NUM_LINES*font_height(font)), "Pawn console", TITLEBAR|CLOSEBOX|MAXIMIZE|MINIMIZE|CENTRED); on_window_redraw(win, window_redraw); on_window_close (win, window_close); on_window_key_down(win, window_key_action); /* normal keys (including CR) */ show_window(win); /* handle any pending events */ while (do_event(app)) /* nothing */; csrx = 0; csry = 0; autowrap = 0; attrib = 0x07; return 1; }
int amx_getch(void) { int c=-1; if (createconsole(0, NULL)) { while (keyq_start==keyq_end && app!=NULL) { wait_event(app); do_event(app); } /* while */ c=(int)keyqueue[keyq_start]; keyq_start=(keyq_start+1)%KEYQUEUE_SIZE; } /* if */ return c; }
/*{{{ shape_window -- reshape a window with the mouse*/ void shape_window(void) { int dx = 16, dy = 16; SETMOUSEICON(&mouse_box); move_mouse(screen, mouse, &mousex, &mousey, 0); SETMOUSEICON(DEFAULT_MOUSE_CURSOR); get_rect(screen, mouse, mousex, mousey, &dx, &dy, 0); do_button(0); /* look for shape event here */ do_event(EVENT_SHAPE, active, E_MAIN); (void)shape(mousex, mousey, dx, dy); }
static void job_proc(void) { struct ipc_struct ipc; struct pack *p; struct ProcChild *sender; char *t, *s; int cmd; size_t size; p = pack_new(256); while (1) { if (1 == proc_listen(&sender, &cmd, &size, 1)) break; } proc_get(sender, &ipc, p, size); bk_channel = ipc.source; switch (cmd) { case CMD_REGISTER: pack_get(p, &t, NULL); pack_get(p, &s, NULL); do_register(ipc.node, t, s); break; case CMD_REMOVE: pack_get(p, &t, NULL); do_remove(t); break; case CMD_CALL: do_call(ipc.node, p); break; case CMD_CALL_PACKAGE: pack_get(p, &t, NULL); do_call_package(ipc.node, t, p); break; case CMD_GETLIST: do_getlist(ipc.node); break; case CMD_DUMP_PROFILE: do_dump_profile(); break; case CMD_EVENT: pack_get(p, &t, NULL); pack_get(p, &s, NULL); do_event(t, ipc.node, s, p); break; } }
bool qt_processTermEvent(gp_event_t* event) { // Intercepts resize event if (event->type == GE_fontprops) { // This is an answer to a font metric request. We don't send it back to gnuplot if ((event->par1 > 0) && (event->par2 > 0)) { qDebug() << "qt_processTermEvent received a GE_fontprops event. This should not have happened"; return false; } // This is a resize event qt_setSize = true; qt_setWidth = event->mx; qt_setHeight = event->my; } // Scale mouse events else { QPoint p = qt_gnuplotCoord(event->mx, event->my); event->mx = p.x(); event->my = p.y(); } // Send the event to gnuplot core do_event(event); // Process pause_for_mouse if ((event->type == GE_buttonrelease) && (paused_for_mouse & PAUSE_CLICK)) { int button = event->par1; if (((button == 1) && (paused_for_mouse & PAUSE_BUTTON1)) || ((button == 2) && (paused_for_mouse & PAUSE_BUTTON2)) || ((button == 3) && (paused_for_mouse & PAUSE_BUTTON3))) paused_for_mouse = 0; if (paused_for_mouse == 0) return true; } if ((event->type == GE_keypress) && (paused_for_mouse & PAUSE_KEYSTROKE) && (event->par1 > '\0')) { paused_for_mouse = 0; return true; } return false; }
void * Parrot_do_handle_events(Parrot_Interp interpreter, int restore, void *next) { QUEUE_ENTRY *entry; parrot_event* event; QUEUE * tq = interpreter->task_queue; if (restore) disable_event_checking(interpreter); if (!peek_entry(tq)) return next; while (peek_entry(tq)) { entry = pop_entry(tq); event = (parrot_event* )entry->data; mem_sys_free(entry); next = do_event(interpreter, event, next); } return next; }
int execute_event(void *data) { t_event *event; struct itimerspec new_value; if (event = pop_event(((t_evq*)data)->eventq)) do_event(event, ((t_evq*)data)->p_id, ((t_evq*)data)->p_fd); else { debug("Timer set but no events registered"); new_value.it_value.tv_sec = 0; new_value.it_value.tv_nsec = 0; new_value.it_interval.tv_sec = 0; new_value.it_interval.tv_nsec = 0; timerfd_settime(((t_evq*)data)->eventq->timerfd, TFD_TIMER_ABSTIME, &new_value, NULL); } debug("Event executed"); return (EXIT_SUCCESS); }
int amx_getch(void) { int c=-1; if (createconsole(0, NULL)) { int cursor=0; if (keyq_start==keyq_end) { amx_putchar(__T('_')); /* must wait for character, so put pseudo-cursor */ cursor=1; } /* if */ while (keyq_start==keyq_end && app!=NULL) { wait_event(app); do_event(app); } /* while */ c=(int)keyqueue[keyq_start]; if (c=='\n') c='\r'; /* enter key must be '\r' for Pawn */ keyq_start=(keyq_start+1)%KEYQUEUE_SIZE; if (cursor) amx_putchar(__T('\b')); /* remove speudo-cursor */ } /* if */ return c; }
bool qt_processTermEvent(gp_event_t* event) { // Intercepts resize event if (event->type == GE_fontprops) { qt_setSize = true; qt_setWidth = event->mx; qt_setHeight = event->my; } // Scale mouse events else { event->mx *= qt_oversampling; event->my = (qt_setHeight - event->my)*qt_oversampling; } // Send the event to gnuplot core do_event(event); // Process pause_for_mouse if ((event->type == GE_buttonrelease) && (paused_for_mouse & PAUSE_CLICK)) { int button = event->par1; if (((button == 1) && (paused_for_mouse & PAUSE_BUTTON1)) || ((button == 2) && (paused_for_mouse & PAUSE_BUTTON2)) || ((button == 3) && (paused_for_mouse & PAUSE_BUTTON3))) paused_for_mouse = 0; if (paused_for_mouse == 0) return true; } if ((event->type == GE_keypress) && (paused_for_mouse & PAUSE_KEYSTROKE) && (event->par1 > '\0')) { paused_for_mouse = 0; return true; } return false; }
/*{{{ redraw -- redraw screen, restore contents of saved windows*/ int redraw() { register WINDOW *win; #ifdef DEBUG dprintf(b)(stderr,"\r\n\tREDRAW\r\n"); #endif for(win=active;win != (WINDOW *) 0;win=W(next)) { if (W(flags)&W_ACTIVE) { save_win(win); do_event(EVENT_REDRAW,win,E_MAIN); } } erase_win(screen); if (active) { for(win=ACTIVE(prev);win != active;win=W(prev)) { restore_win(win); border(win,BLK_BDR,WH_BDR); } restore_win(active); border(active,BLK_BDR,WH_BDR); } }
int main(int argc, char *argv[]) { fprintf(stderr, "**** %s:%s() ****\n", __FILE__, __func__); setenv_window(); const char* cfgfilename = "../configs/pcaster_options_viewer.cfg"; pops = new pcaster_options(0, 0, cfgfilename); // window_w = pcaster_options::render_wid; // window_h = pcaster_options::render_hei; window_noframe = pcaster_options::window_noframe; window_fullscreen = pcaster_options::window_fullscreen; tangible = new Event_Relayer(myrank, runsize, GL_IO::MOUSE_KEY | GL_IO::TUIKIT, GL_IO::NET_TCP, 1); tangible->mapto_world_transform(objpos, objrot); #ifdef _STREAMING // std::cout << pcaster_options::viewer << "\n"; tangible->init_data_mover( Socket_Data_Mover::NET_SERVER, pcaster_options::viewer, 9332); #endif streamer = new Image_Streamer(myrank, runsize, GL_IO::NET_TCP, GL_IO::DDB, 1, GL_RGB, pcaster_options::render_wid, pcaster_options::render_hei); #ifdef _STREAMING streamer->init_data_mover( Socket_Data_Mover::NET_SERVER, pcaster_options::viewer, 9333 ); #endif if (SDL_Init(SDL_INIT_VIDEO) == 0) { SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 0); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); if (SDL_SetVideoMode(window_w, window_h, 0, window_noframe * SDL_NOFRAME | window_fullscreen * SDL_FULLSCREEN | SDL_OPENGL)) { viewer = new Viewer(window_w, window_h, pcaster_options::render_wid, pcaster_options::render_hei); viewer->init(); viewer->assert_application_mode(); streamer->register_image_receiver(viewer); int run = 1; while (run) { SDL_Event e; //if(SDL_WaitEvent(&e)) run &= do_event(&e); while (SDL_PollEvent(&e)) run &= do_event(&e); idle(); display(); //sleep(10); //run = 0; } } else fprintf(stderr, "SDL_SetVideoMode: %s\n", SDL_GetError()); SDL_Quit(); } else fprintf(stderr, "SDL_Init: %s\n", SDL_GetError()); return 0; }
inline int app::run() { int retval = 0; while( do_event(retval) ); return retval; }
QoreHashNode* qore_httpclient_priv::send_internal(ExceptionSink* xsink, const char* mname, const char* meth, const char* mpath, const QoreHashNode* headers, const void* data, unsigned size, const ResolvedCallReferenceNode* send_callback, bool getbody, QoreHashNode* info, int timeout_ms, const ResolvedCallReferenceNode* recv_callback, QoreObject* obj) { assert(!(data && send_callback)); // check if method is valid method_map_t::const_iterator i = method_map.find(meth); if (i == method_map.end()) { i = additional_methods_map.find(meth); if (i == additional_methods_map.end()) { xsink->raiseException("HTTP-CLIENT-METHOD-ERROR", "HTTP method (%s) not recognized.", meth); return 0; } } // make sure the capitalized version is used meth = i->first.c_str(); bool bodyp = i->second; // use the default timeout value if a zero value is given in the call if (!timeout_ms) timeout_ms = timeout; SafeLocker sl(msock->m); Queue* cb_queue = msock->socket->getQueue(); ReferenceHolder<QoreHashNode> nh(new QoreHashNode, xsink); bool keep_alive = true; bool transfer_encoding = false; if (headers) { ConstHashIterator hi(headers); while (hi.next()) { // if one of the mandatory headers is found, then ignore it strcase_set_t::iterator si = header_ignore.find(hi.getKey()); if (si != header_ignore.end()) continue; // otherwise set the value in the hash const AbstractQoreNode* n = hi.getValue(); if (!is_nothing(n)) { if (!strcasecmp(hi.getKey(), "transfer-encoding")) transfer_encoding = true; nh->setKeyValue(hi.getKey(), n->refSelf(), xsink); if (!strcasecmp(hi.getKey(), "connection") || (proxy_connection.has_url() && !strcasecmp(hi.getKey(), "proxy-connection"))) { const char* conn = get_string_header(xsink, **nh, hi.getKey(), true); if (*xsink) { disconnect_unlocked(); return 0; } if (conn && !strcasecmp(conn, "close")) keep_alive = false; } } } } // add default headers if they weren't overridden for (header_map_t::const_iterator hdri = default_headers.begin(), e = default_headers.end(); hdri != e; ++hdri) { // look in original headers to see if the key was already given if (headers) { bool skip = false; ConstHashIterator hi(headers); while (hi.next()) { if (!strcasecmp(hi.getKey(), hdri->first.c_str())) { skip = true; break; } } if (skip) continue; } // if there is no message body then do not send the "content-type" header if (!data && !send_callback && !strcmp(hdri->first.c_str(), "Content-Type")) continue; nh->setKeyValue(hdri->first.c_str(), new QoreStringNode(hdri->second.c_str()), xsink); } // set Transfer-Encoding: chunked if used with a send callback if (send_callback && !transfer_encoding) nh->setKeyValue("Transfer-Encoding", new QoreStringNode("chunked"), xsink); if (!connection.username.empty()) { // check for "Authorization" header bool auth_found = false; if (headers) { ConstHashIterator hi(headers); while (hi.next()) { if (!strcasecmp(hi.getKey(), "Authorization")) { auth_found = true; break; } } } if (!auth_found) { QoreString tmp; tmp.sprintf("%s:%s", connection.username.c_str(), connection.password.c_str()); QoreStringNode* auth_str = new QoreStringNode("Basic "); auth_str->concatBase64(&tmp); nh->setKeyValue("Authorization", auth_str, xsink); } } // save original HTTP method in case we have to issue a CONNECT request to a proxy for an HTTPS connection const char* meth_orig = meth; bool use_proxy_connect = false; const char* proxy_path = 0; ReferenceHolder<QoreHashNode> proxy_headers(xsink); QoreString hostport; if (!proxy_connected && proxy_connection.has_url()) { // use CONNECT if we need to make an HTTPS connection from the proxy if (!proxy_connection.ssl && connection.ssl) { meth = "CONNECT"; use_proxy_connect = true; hostport.concat(connection.host); if (connection.port) hostport.sprintf(":%d", connection.port); proxy_path = hostport.getBuffer(); proxy_headers = new QoreHashNode; proxy_headers->setKeyValue("Host", new QoreStringNode(hostport), xsink); addProxyAuthorization(headers, **proxy_headers, xsink); } else addProxyAuthorization(headers, **nh, xsink); } bool host_override = headers ? (bool)headers->getKeyValue("Host") : false; int code; ReferenceHolder<QoreHashNode> ans(xsink); int redirect_count = 0; const char* location = 0; // flag for aborted chunked sends bool send_aborted = false; while (true) { // set host field automatically if not overridden if (!host_override) nh->setKeyValue("Host", getHostHeaderValue(), xsink); if (info) { info->setKeyValue("headers", nh->copy(), xsink); if (*xsink) return 0; } //printd(5, "qore_httpclient_priv::send_internal() meth=%s proxy_path=%s mpath=%s upc=%d\n", meth, proxy_path ? proxy_path : "n/a", mpath, use_proxy_connect); // send HTTP message and get response header if (use_proxy_connect) ans = sendMessageAndGetResponse(meth, proxy_path, *(*proxy_headers), 0, 0, 0, info, true, timeout_ms, code, send_aborted, xsink); else ans = sendMessageAndGetResponse(meth, mpath, *(*nh), data, size, send_callback, info, false, timeout_ms, code, send_aborted, xsink); if (!ans) return 0; if (info) { info->setKeyValue("response-headers", ans->refSelf(), xsink); if (*xsink) return 0; } if (code >= 300 && code < 400) { disconnect_unlocked(); host_override = false; const QoreStringNode* mess = reinterpret_cast<QoreStringNode*>(ans->getKeyValue("status_message")); const QoreStringNode* loc = get_string_header_node(xsink, **ans, "location"); if (*xsink) return 0; const char* location = loc && !loc->empty() ? loc->getBuffer() : 0; if (!location) { sl.unlock(); const char* msg = mess ? mess->getBuffer() : "<no message>"; xsink->raiseException("HTTP-CLIENT-REDIRECT-ERROR", "no redirect location given for status code %d: message: '%s'", code, msg); return 0; } if (cb_queue) do_redirect_event(cb_queue, msock->socket->getObjectIDForEvents(), loc, mess); if (++redirect_count > max_redirects) break; if (set_url_unlocked(location, xsink)) { sl.unlock(); const char* msg = mess ? mess->getBuffer() : "<no message>"; xsink->raiseException("HTTP-CLIENT-REDIRECT-ERROR", "exception occurred while setting URL for new location '%s' (code %d: message: '%s')", location, code, msg); return 0; } // set redirect info in info hash if present if (info) { QoreString tmp; tmp.sprintf("redirect-%d", redirect_count); info->setKeyValue(tmp.getBuffer(), loc->refSelf(), xsink); if (*xsink) return 0; tmp.clear(); tmp.sprintf("redirect-message-%d", redirect_count); info->setKeyValue(tmp.getBuffer(), mess ? mess->refSelf() : 0, xsink); } // FIXME: reset send callback and send_aborted here // set mpath to NULL so that the new path will be taken mpath = 0; continue; } else if (use_proxy_connect) { meth = meth_orig; use_proxy_connect = false; proxy_path = 0; if (msock->socket->upgradeClientToSSL(0, 0, xsink)) { disconnect_unlocked(); return 0; } proxy_connected = true; // remove "Proxy-Authorization" header nh->removeKey("Proxy-Authorization", xsink); if (*xsink) return 0; // try again as if we are talking directly to the client continue; } break; } if (code >= 300 && code < 400) { sl.unlock(); const char* mess = get_string_header(xsink, **ans, "status_message"); if (!mess) mess = "<no message>"; if (!location) location = "<no location>"; xsink->raiseException("HTTP-CLIENT-MAXIMUM-REDIRECTS-EXCEEDED", "maximum redirections (%d) exceeded; redirect code %d to '%s' ignored (message: '%s')", max_redirects, code, location, mess); return 0; } // process content-type const QoreStringNode* v = get_string_header_node(xsink, **ans, "content-type"); if (*xsink) { disconnect_unlocked(); return 0; } //ans->getKeyValue("content-type"); // see if there is a character set specification in the content-type header if (v) { // save original content-type header before processing ans->setKeyValue("_qore_orig_content_type", v->refSelf(), xsink); const char* str = v->getBuffer(); const char* p = strstr(str, "charset="); if (p && (p == str || *(p - 1) == ';' || *(p - 1) == ' ')) { // move p to start of encoding const char* c = p + 8; char quote = '\0'; if (*c == '\'' || *c == '"') { quote = *c; ++c; } QoreString enc; while (*c && *c != ';' && *c != ' ' && *c != quote) enc.concat(*(c++)); if (quote && *c == quote) ++c; printd(5, "QoreHttpClientObject::send_intern() setting encoding to '%s' from content-type header: '%s' (cs=%p c=%p %d)\n", enc.getBuffer(), str, p + 8, c); // set new encoding msock->socket->setEncoding(QEM.findCreate(&enc)); // strip from content-type QoreStringNode* nc = new QoreStringNode(); // skip any spaces before the charset= while (p != str && (*(p - 1) == ' ' || *(p - 1) == ';')) p--; if (p != str) nc->concat(str, p - str); if (*c) nc->concat(c); ans->setKeyValue("content-type", nc, xsink); str = nc->getBuffer(); } // split into a list if ";" characters are present p = strchr(str, ';'); if (p) { bool multipart = false; QoreListNode* l = new QoreListNode(); do { // skip whitespace while (*str == ' ') str++; if (str != p) { int len = p - str; check_headers(str, len, multipart, *(*ans), msock->socket->getEncoding(), xsink); l->push(new QoreStringNode(str, len, msock->socket->getEncoding())); } str = p + 1; } while ((p = strchr(str, ';'))); // skip whitespace while (*str == ' ') str++; // add last field if (*str) { check_headers(str, strlen(str), multipart, *(*ans), msock->socket->getEncoding(), xsink); l->push(new QoreStringNode(str, msock->socket->getEncoding())); } ans->setKeyValue("content-type", l, xsink); } } // send headers to recv_callback if (recv_callback && msock->socket->priv->runHeaderCallback(xsink, mname, *recv_callback, &msock->m, *ans, send_aborted, obj)) return 0; AbstractQoreNode* body = 0; const char* content_encoding = 0; // do not read any message body for messages that cannot have one // rfc 2616 4.4 p1 (http://tools.ietf.org/html/rfc2616#section-4.4) /* 1.Any response message which "MUST NOT" include a message-body (such as the 1xx, 204, and 304 responses and any response to a HEAD request) is always terminated by the first empty line after the header fields, regardless of the entity-header fields present in the message. */ //printd(5, "qore_httpclient_priv::send_internal() this: %p bodyp: %d code: %d\n", this, bodyp, code); qore_uncompress_to_string_t dec = 0; // code >= 300 && < 400 is already handled above if (bodyp && (code < 100 || code >= 200) && code != 204) { // see if we should do a binary or string read content_encoding = get_string_header(xsink, **ans, "content-encoding"); if (*xsink) { disconnect_unlocked(); return 0; } if (content_encoding) { // check for misuse (? not sure: check RFCs again) of this field by including a character encoding value if (!strncasecmp(content_encoding, "iso", 3) || !strncasecmp(content_encoding, "utf-", 4)) { msock->socket->setEncoding(QEM.findCreate(content_encoding)); content_encoding = 0; } else if (!recv_callback) { // only decode message bodies automatically if there is no receive callback if (!strcasecmp(content_encoding, "deflate") || !strcasecmp(content_encoding, "x-deflate")) dec = qore_inflate_to_string; else if (!strcasecmp(content_encoding, "gzip") || !strcasecmp(content_encoding, "x-gzip")) dec = qore_gunzip_to_string; else if (!strcasecmp(content_encoding, "bzip2") || !strcasecmp(content_encoding, "x-bzip2")) dec = qore_bunzip2_to_string; } } const char* te = get_string_header(xsink, **ans, "transfer-encoding"); if (*xsink) { disconnect_unlocked(); return 0; } // get response body, if any const char* cl = get_string_header(xsink, **ans, "content-length"); if (*xsink) { disconnect_unlocked(); return 0; } int len = cl ? atoi(cl) : 0; if (cl && cb_queue) do_content_length_event(cb_queue, msock->socket->getObjectIDForEvents(), len); if (te && !strcasecmp(te, "chunked")) { // check for chunked response body if (cb_queue) do_event(cb_queue, msock->socket->getObjectIDForEvents(), QORE_EVENT_HTTP_CHUNKED_START); ReferenceHolder<QoreHashNode> nah(xsink); if (recv_callback) { if (content_encoding) msock->socket->priv->readHttpChunkedBodyBinary(timeout_ms, xsink, QORE_SOURCE_HTTPCLIENT, recv_callback, &msock->m, obj); else msock->socket->priv->readHttpChunkedBody(timeout_ms, xsink, QORE_SOURCE_HTTPCLIENT, recv_callback, &msock->m, obj); } else { if (content_encoding) nah = msock->socket->priv->readHttpChunkedBodyBinary(timeout_ms, xsink, QORE_SOURCE_HTTPCLIENT); else nah = msock->socket->priv->readHttpChunkedBody(timeout_ms, xsink, QORE_SOURCE_HTTPCLIENT); } if (cb_queue) do_event(cb_queue, msock->socket->getObjectIDForEvents(), QORE_EVENT_HTTP_CHUNKED_END); if (!nah && !recv_callback) { if (!msock->socket->isOpen()) disconnect_unlocked(); return 0; } if (info) { info->setKeyValue("chunked", &True, xsink); if (*xsink) return 0; } if (!recv_callback) { body = nah->takeKeyValue("body"); ans->merge(*nah, xsink); } } else if (getbody || len) { if (content_encoding) { SimpleRefHolder<BinaryNode> bobj(msock->socket->recvBinary(len, timeout_ms, xsink)); if (!(*xsink) && bobj) body = bobj.release(); } else { QoreStringNodeHolder bstr(msock->socket->recv(len, timeout_ms, xsink)); if (!(*xsink) && bstr) body = bstr.release(); } if (*xsink && !msock->socket->isOpen()) disconnect_unlocked(); //printf("body=%p\n", body); } } // check for connection: close header if (!keep_alive) disconnect_unlocked(); else { const char* conn = get_string_header(xsink, **ans, "connection", true); if (*xsink) { disconnect_unlocked(); return 0; } if (conn && !strcasecmp(conn, "close")) disconnect_unlocked(); } sl.unlock(); // for content-encoding processing we can run unlocked // add body to result hash and process content encoding if necessary if (body) { if (content_encoding) { if (!dec) { if (!recv_callback) { xsink->raiseException("HTTP-CLIENT-RECEIVE-ERROR", "don't know how to handle content-encoding '%s'", content_encoding); ans = 0; } } else { BinaryNode* bobj = reinterpret_cast<BinaryNode*>(body); QoreStringNode* str = dec(bobj, msock->socket->getEncoding(), xsink); bobj->deref(); body = str; } } if (body) { // send data to recv_callback (already unlocked) if (recv_callback) { ReferenceHolder<> bh(body, xsink); if (msock->socket->priv->runDataCallback(xsink, mname, *recv_callback, 0, body, false) || msock->socket->priv->runHeaderCallback(xsink, mname, *recv_callback, 0, 0, send_aborted, obj)) return 0; } else ans->setKeyValue("body", body, xsink); } } // do not throw an exception if a receive callback is used if (!recv_callback && !*xsink && (code < 100 || code >= 300)) { const char* mess = get_string_header(xsink, **ans, "status_message"); if (!mess) mess = "<no message>"; assert(!*xsink); xsink->raiseExceptionArg("HTTP-CLIENT-RECEIVE-ERROR", ans.release(), "HTTP status code %d received: message: %s", code, mess); return 0; } return *xsink || recv_callback ? 0 : ans.release(); }
static void tk_do_events(void) { if (!interp) return; while (Tk_MainWindow(interp) && do_event()) ; if (!Tk_MainWindow(interp)) tk_stop(); }